c3cadd88b6f0de3aa134c3fd0a39f4ed77ca1578
[people/sha0/mDNSResponder.git] / mDNSWindows / mDNSWin32.c
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>\r
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        "DNSCommon.h"
50 #include        "mDNSWin32.h"
51
52 #if 0
53 #pragma mark == Constants ==
54 #endif
55
56 //===========================================================================================================================
57 //      Constants
58 //===========================================================================================================================
59
60 #define DEBUG_NAME                                                                      "[mDNSWin32] "
61
62 #define MDNS_WINDOWS_USE_IPV6_IF_ADDRS                          1
63 #define MDNS_WINDOWS_ENABLE_IPV4                                        1
64 #define MDNS_WINDOWS_ENABLE_IPV6                                        1
65 #define MDNS_FIX_IPHLPAPI_PREFIX_BUG                            1
66 #define MDNS_SET_HINFO_STRINGS                                          0
67
68 #define kMDNSDefaultName                                                        "My Computer"
69
70 #define kWinSockMajorMin                                                        2
71 #define kWinSockMinorMin                                                        2
72
73 #define kRegistryMaxKeyLength                                           255
74 #define kRegistryMaxValueName                                           16383
75
76 static GUID                                                                                     kWSARecvMsgGUID = WSAID_WSARECVMSG;
77
78 #define kIPv6IfIndexBase                                                        (10000000L)
79 #define SMBPortAsNumber                                                         445
80 #define DEVICE_PREFIX                                                           "\\\\.\\"
81
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 CALLBACK         TCPFreeSocket( TCPSocket *sock );
146 mDNSlocal OSStatus                      UDPBeginRecv( UDPSocket * socket );
147 mDNSlocal void CALLBACK         UDPEndRecv( DWORD err, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags );
148 mDNSlocal void CALLBACK         UDPFreeSocket( UDPSocket * sock );
149 mDNSlocal mStatus           SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa);
150 mDNSlocal void                          GetDDNSFQDN( domainname *const fqdn );
151 #ifdef UNICODE
152 mDNSlocal void                          GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey );
153 #else
154 mDNSlocal void                          GetDDNSDomains( DNameListElem ** domains, LPCSTR lpSubKey );
155 #endif
156 mDNSlocal void                          SetDomainSecrets( mDNS * const inMDNS );
157 mDNSlocal void                          SetDomainSecret( mDNS * const m, const domainname * inDomain );
158 mDNSlocal void                          CheckFileShares( mDNS * const inMDNS );
159 mDNSlocal void                          SMBCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
160 mDNSlocal mDNSu8                        IsWOMPEnabledForAdapter( const char * adapterName );
161
162 #ifdef  __cplusplus
163         }
164 #endif
165
166 #if 0
167 #pragma mark == Globals ==
168 #endif
169
170 //===========================================================================================================================
171 //      Globals
172 //===========================================================================================================================
173
174 mDNSlocal mDNS_PlatformSupport  gMDNSPlatformSupport;
175 mDNSs32                                                 mDNSPlatformOneSecond = 0;
176 mDNSlocal UDPSocket             *               gUDPSocketList                  = NULL;
177 mDNSlocal int                                   gUDPSockets                             = 0;
178
179 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
180
181         typedef DWORD
182                 ( WINAPI * GetAdaptersAddressesFunctionPtr )( 
183                         ULONG                                   inFamily, 
184                         DWORD                                   inFlags, 
185                         PVOID                                   inReserved, 
186                         PIP_ADAPTER_ADDRESSES   inAdapter, 
187                         PULONG                                  outBufferSize );
188
189         mDNSlocal HMODULE                                                               gIPHelperLibraryInstance                        = NULL;
190         mDNSlocal GetAdaptersAddressesFunctionPtr               gGetAdaptersAddressesFunctionPtr        = NULL;
191
192 #endif
193
194
195 #ifndef HCRYPTPROV
196    typedef ULONG_PTR HCRYPTPROV;    // WinCrypt.h, line 249
197 #endif
198
199
200 #ifndef CRYPT_MACHINE_KEYSET
201 #       define CRYPT_MACHINE_KEYSET    0x00000020
202 #endif
203
204 #ifndef CRYPT_NEWKEYSET
205 #       define CRYPT_NEWKEYSET         0x00000008
206 #endif
207
208 #ifndef PROV_RSA_FULL
209 #  define PROV_RSA_FULL 1
210 #endif
211
212 typedef BOOL (__stdcall *fnCryptGenRandom)( HCRYPTPROV, DWORD, BYTE* ); 
213 typedef BOOL (__stdcall *fnCryptAcquireContext)( HCRYPTPROV*, LPCTSTR, LPCTSTR, DWORD, DWORD);
214 typedef BOOL (__stdcall *fnCryptReleaseContext)(HCRYPTPROV, DWORD);
215
216 static fnCryptAcquireContext g_lpCryptAcquireContext    = NULL;
217 static fnCryptReleaseContext g_lpCryptReleaseContext    = NULL;
218 static fnCryptGenRandom          g_lpCryptGenRandom             = NULL;
219 static HINSTANCE                         g_hAAPI32                                      = NULL;
220 static HCRYPTPROV                        g_hProvider                            = ( ULONG_PTR ) NULL;
221
222
223 #if 0
224 #pragma mark -
225 #pragma mark == Platform Support ==
226 #endif
227
228 //===========================================================================================================================
229 //      mDNSPlatformInit
230 //===========================================================================================================================
231
232 mDNSexport mStatus      mDNSPlatformInit( mDNS * const inMDNS )
233 {
234         mStatus         err;
235         WSADATA         wsaData;
236         int                     supported;
237         struct sockaddr_in      sa4;
238         struct sockaddr_in6 sa6;
239         int                                     sa4len;
240         int                                     sa6len;
241         DWORD                           size;
242         DWORD                           val;
243         
244         dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" );
245         
246         // Initialize variables. If the PlatformSupport pointer is not null then just assume that a non-Apple client is 
247         // calling mDNS_Init and wants to provide its own storage for the platform-specific data so do not overwrite it.
248         
249         mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) );
250         if( !inMDNS->p ) inMDNS->p                              = &gMDNSPlatformSupport;
251         inMDNS->p->mainThread                                   = OpenThread( THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId() );
252         require_action( inMDNS->p->mainThread, exit, err = mStatus_UnknownErr );
253         mDNSPlatformOneSecond                                   = 1000;         // Use milliseconds as the quantum of time
254         
255         // Startup WinSock 2.2 or later.
256         
257         err = WSAStartup( MAKEWORD( kWinSockMajorMin, kWinSockMinorMin ), &wsaData );
258         require_noerr( err, exit );
259         
260         supported = ( ( LOBYTE( wsaData.wVersion ) == kWinSockMajorMin ) && ( HIBYTE( wsaData.wVersion ) == kWinSockMinorMin ) );
261         require_action( supported, exit, err = mStatus_UnsupportedErr );
262         
263         inMDNS->CanReceiveUnicastOn5353 = CanReceiveUnicast();
264         
265         // Setup the HINFO HW strings.
266         //<rdar://problem/7245119> device-info should have model=Windows
267
268         strcpy_s( ( char* ) &inMDNS->HIHardware.c[ 1 ], sizeof( inMDNS->HIHardware.c ) - 2, "Windows" );
269         inMDNS->HIHardware.c[ 0 ] = ( mDNSu8 ) mDNSPlatformStrLen( &inMDNS->HIHardware.c[ 1 ] );\r
270         dlog( kDebugLevelInfo, DEBUG_NAME "HIHardware: %#s\n", inMDNS->HIHardware.c );
271
272         // Setup the HINFO SW strings.
273 #if ( MDNS_SET_HINFO_STRINGS )
274         mDNS_snprintf( (char *) &inMDNS->HISoftware.c[ 1 ], sizeof( inMDNS->HISoftware.c ) - 2, 
275                 "mDNSResponder (%s %s)", __DATE__, __TIME__ );
276         inMDNS->HISoftware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HISoftware.c[ 1 ] );
277         dlog( kDebugLevelInfo, DEBUG_NAME "HISoftware: %#s\n", inMDNS->HISoftware.c );
278 #endif
279
280         // Set the thread global overlapped flag
281
282         val = 0;
283         err = setsockopt( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, ( char* ) &val, sizeof( val ) );
284         err = translate_errno( err != SOCKET_ERROR, WSAGetLastError(), kUnknownErr );
285         require_noerr( err, exit );
286
287         // Set up the IPv4 unicast socket
288
289         inMDNS->p->unicastSock4.fd                      = INVALID_SOCKET;
290         inMDNS->p->unicastSock4.recvMsgPtr      = NULL;
291         inMDNS->p->unicastSock4.ifd                     = NULL;
292         inMDNS->p->unicastSock4.next            = NULL;
293         inMDNS->p->unicastSock4.m                       = inMDNS;
294
295 #if ( MDNS_WINDOWS_ENABLE_IPV4 )
296
297         sa4.sin_family          = AF_INET;
298         sa4.sin_addr.s_addr = INADDR_ANY;
299         err = SetupSocket( inMDNS, (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4.fd );
300         check_noerr( err );
301         sa4len = sizeof( sa4 );
302         err = getsockname( inMDNS->p->unicastSock4.fd, (struct sockaddr*) &sa4, &sa4len );
303         require_noerr( err, exit );
304         inMDNS->p->unicastSock4.port.NotAnInteger = sa4.sin_port;
305         inMDNS->UnicastPort4 = inMDNS->p->unicastSock4.port;
306         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 );
307                 
308         if ( err )
309         {
310                 inMDNS->p->unicastSock4.recvMsgPtr = NULL;
311         }
312
313         err = UDPBeginRecv( &inMDNS->p->unicastSock4 );
314         require_noerr( err, exit ); 
315
316 #endif
317
318         // Set up the IPv6 unicast socket
319
320         inMDNS->p->unicastSock6.fd                      = INVALID_SOCKET;
321         inMDNS->p->unicastSock6.recvMsgPtr      = NULL;
322         inMDNS->p->unicastSock6.ifd                     = NULL;
323         inMDNS->p->unicastSock6.next            = NULL;
324         inMDNS->p->unicastSock6.m                       = inMDNS;
325
326 #if ( MDNS_WINDOWS_ENABLE_IPV6 )
327
328         sa6.sin6_family         = AF_INET6;
329         sa6.sin6_addr           = in6addr_any;
330         sa6.sin6_scope_id       = 0;
331
332         // This call will fail if the machine hasn't installed IPv6.  In that case,
333         // the error will be WSAEAFNOSUPPORT.
334
335         err = SetupSocket( inMDNS, (const struct sockaddr*) &sa6, zeroIPPort, &inMDNS->p->unicastSock6.fd );
336         require_action( !err || ( err == WSAEAFNOSUPPORT ), exit, err = (mStatus) WSAGetLastError() );
337         err = kNoErr;
338         
339         // If we weren't able to create the socket (because IPv6 hasn't been installed) don't do this
340
341         if ( inMDNS->p->unicastSock6.fd != INVALID_SOCKET )
342         {
343                 sa6len = sizeof( sa6 );
344                 err = getsockname( inMDNS->p->unicastSock6.fd, (struct sockaddr*) &sa6, &sa6len );
345                 require_noerr( err, exit );
346                 inMDNS->p->unicastSock6.port.NotAnInteger = sa6.sin6_port;
347                 inMDNS->UnicastPort6 = inMDNS->p->unicastSock6.port;
348
349                 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 );
350                 
351                 if ( err != 0 )
352                 {
353                         inMDNS->p->unicastSock6.recvMsgPtr = NULL;
354                 }
355
356                 err = UDPBeginRecv( &inMDNS->p->unicastSock6 );
357                 require_noerr( err, exit );
358         } 
359
360 #endif
361
362         // Notify core of domain secret keys
363
364         SetDomainSecrets( inMDNS );
365         
366         // Success!
367
368         mDNSCoreInitComplete( inMDNS, err );
369
370         // See if we need to advertise file sharing
371
372         inMDNS->p->smbRegistered = mDNSfalse;
373         
374 exit:
375
376         if ( err )
377         {
378                 mDNSPlatformClose( inMDNS );
379         }
380
381         dlog( kDebugLevelTrace, DEBUG_NAME "platform init done (err=%d %m)\n", err, err );
382         return( err );
383 }
384
385 //===========================================================================================================================
386 //      mDNSPlatformClose
387 //===========================================================================================================================
388
389 mDNSexport void mDNSPlatformClose( mDNS * const inMDNS )
390 {
391         mStatus         err;
392         
393         dlog( kDebugLevelTrace, DEBUG_NAME "platform close\n" );
394         check( inMDNS );
395
396         if ( inMDNS->p->smbRegistered )
397         {
398                 err = mDNS_DeregisterService( inMDNS, &inMDNS->p->smbSRS );
399                 check( !err );
400
401                 inMDNS->p->smbRegistered = mDNSfalse;
402         }
403
404         // Tear everything down in reverse order to how it was set up.
405         
406         err = TearDownInterfaceList( inMDNS );
407         check_noerr( err );
408         check( !inMDNS->p->inactiveInterfaceList );
409
410 #if ( MDNS_WINDOWS_ENABLE_IPV4 )
411
412         if ( inMDNS->p->unicastSock4.fd != INVALID_SOCKET )
413         {
414                 closesocket( inMDNS->p->unicastSock4.fd );
415                 inMDNS->p->unicastSock4.fd = INVALID_SOCKET;
416         }
417
418 #endif
419         
420 #if ( MDNS_WINDOWS_ENABLE_IPV6 )
421
422         if ( inMDNS->p->unicastSock6.fd != INVALID_SOCKET )
423         {
424                 closesocket( inMDNS->p->unicastSock6.fd );
425                 inMDNS->p->unicastSock6.fd = INVALID_SOCKET;
426         }
427
428 #endif
429
430         // Free the DLL needed for IPv6 support.
431         
432 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
433         if( gIPHelperLibraryInstance )
434         {
435                 gGetAdaptersAddressesFunctionPtr = NULL;
436                 
437                 FreeLibrary( gIPHelperLibraryInstance );
438                 gIPHelperLibraryInstance = NULL;
439         }
440 #endif
441
442         if ( g_hAAPI32 )
443         {
444                 // Release any resources
445
446                 if ( g_hProvider && g_lpCryptReleaseContext )
447                 {
448                         ( g_lpCryptReleaseContext )( g_hProvider, 0 );
449                 }
450
451                 // Free the AdvApi32.dll
452
453                 FreeLibrary( g_hAAPI32 );
454
455                 // And reset all the data
456
457                 g_lpCryptAcquireContext = NULL;
458                 g_lpCryptReleaseContext = NULL;
459                 g_lpCryptGenRandom              = NULL;
460                 g_hProvider                     = ( ULONG_PTR ) NULL;
461                 g_hAAPI32                               = NULL;
462         }
463
464         // Clear out the APC queue
465
466         while ( SleepEx( 0, TRUE ) == WAIT_IO_COMPLETION );
467
468         WSACleanup();
469         
470         dlog( kDebugLevelTrace, DEBUG_NAME "platform close done\n" );
471 }
472
473
474 //===========================================================================================================================
475 //      mDNSPlatformLock
476 //===========================================================================================================================
477
478 mDNSexport void mDNSPlatformLock( const mDNS * const inMDNS )
479 {
480         ( void ) inMDNS;
481 }
482
483 //===========================================================================================================================
484 //      mDNSPlatformUnlock
485 //===========================================================================================================================
486
487 mDNSexport void mDNSPlatformUnlock( const mDNS * const inMDNS )
488 {
489         ( void ) inMDNS;
490 }
491
492 //===========================================================================================================================
493 //      mDNSPlatformStrCopy
494 //===========================================================================================================================
495
496 mDNSexport void mDNSPlatformStrCopy( void *inDst, const void *inSrc )
497 {
498         check( inSrc );
499         check( inDst );
500         
501         strcpy( (char *) inDst, (const char*) inSrc );
502 }
503
504 //===========================================================================================================================
505 //      mDNSPlatformStrLen
506 //===========================================================================================================================
507
508 mDNSexport mDNSu32      mDNSPlatformStrLen( const void *inSrc )
509 {
510         check( inSrc );
511         
512         return( (mDNSu32) strlen( (const char *) inSrc ) );
513 }
514
515 //===========================================================================================================================
516 //      mDNSPlatformMemCopy
517 //===========================================================================================================================
518
519 mDNSexport void mDNSPlatformMemCopy( void *inDst, const void *inSrc, mDNSu32 inSize )
520 {
521         check( inSrc );
522         check( inDst );
523         
524         memcpy( inDst, inSrc, inSize );
525 }
526
527 //===========================================================================================================================
528 //      mDNSPlatformMemSame
529 //===========================================================================================================================
530
531 mDNSexport mDNSBool     mDNSPlatformMemSame( const void *inDst, const void *inSrc, mDNSu32 inSize )
532 {
533         check( inSrc );
534         check( inDst );
535         
536         return( (mDNSBool)( memcmp( inSrc, inDst, inSize ) == 0 ) );
537 }
538
539 //===========================================================================================================================
540 //      mDNSPlatformMemZero
541 //===========================================================================================================================
542
543 mDNSexport void mDNSPlatformMemZero( void *inDst, mDNSu32 inSize )
544 {
545         check( inDst );
546         
547         memset( inDst, 0, inSize );
548 }
549
550 //===========================================================================================================================
551 //      mDNSPlatformMemAllocate
552 //===========================================================================================================================
553
554 mDNSexport void *       mDNSPlatformMemAllocate( mDNSu32 inSize )
555 {
556         void *          mem;
557         
558         check( inSize > 0 );
559         
560         mem = malloc( inSize );
561         check( mem );
562         
563         return( mem );
564 }
565
566 //===========================================================================================================================
567 //      mDNSPlatformMemFree
568 //===========================================================================================================================
569
570 mDNSexport void mDNSPlatformMemFree( void *inMem )
571 {
572         check( inMem );
573         
574         free( inMem );
575 }
576
577 //===========================================================================================================================
578 //      mDNSPlatformRandomNumber
579 //===========================================================================================================================
580
581 mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
582 {
583         mDNSu32         randomNumber = 0;
584         BOOL            bResult;
585         OSStatus        err = 0;
586
587         if ( !g_hAAPI32 )
588         {
589                 g_hAAPI32 = LoadLibrary( TEXT("AdvAPI32.dll") );
590                 err = translate_errno( g_hAAPI32 != NULL, GetLastError(), mStatus_UnknownErr );
591                 require_noerr( err, exit );
592         }
593
594         // Function Pointer: CryptAcquireContext
595
596         if ( !g_lpCryptAcquireContext )
597         {
598                 g_lpCryptAcquireContext = ( fnCryptAcquireContext )
599 #ifdef UNICODE
600                         ( GetProcAddress( g_hAAPI32, "CryptAcquireContextW" ) );
601 #else
602                         ( GetProcAddress( g_hAAPI32, "CryptAcquireContextA" ) );
603 #endif
604                 err = translate_errno( g_lpCryptAcquireContext != NULL, GetLastError(), mStatus_UnknownErr );
605                 require_noerr( err, exit );
606         }
607
608         // Function Pointer: CryptReleaseContext
609
610         if ( !g_lpCryptReleaseContext )
611         {
612                 g_lpCryptReleaseContext = ( fnCryptReleaseContext )
613          ( GetProcAddress( g_hAAPI32, "CryptReleaseContext" ) );
614                 err = translate_errno( g_lpCryptReleaseContext != NULL, GetLastError(), mStatus_UnknownErr );
615                 require_noerr( err, exit );
616         }
617       
618         // Function Pointer: CryptGenRandom
619
620         if ( !g_lpCryptGenRandom )
621         {
622                 g_lpCryptGenRandom = ( fnCryptGenRandom )
623           ( GetProcAddress( g_hAAPI32, "CryptGenRandom" ) );
624                 err = translate_errno( g_lpCryptGenRandom != NULL, GetLastError(), mStatus_UnknownErr );
625                 require_noerr( err, exit );
626         }
627
628         // Setup
629
630         if ( !g_hProvider )
631         {
632                 bResult = (*g_lpCryptAcquireContext)( &g_hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET );
633
634                 if ( !bResult )
635                 {
636                         bResult =  ( *g_lpCryptAcquireContext)( &g_hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET );
637                         err = translate_errno( bResult, GetLastError(), mStatus_UnknownErr );
638                         require_noerr( err, exit );
639                 }
640         }
641
642         bResult = (*g_lpCryptGenRandom)( g_hProvider, sizeof( randomNumber ), ( BYTE* ) &randomNumber );
643         err = translate_errno( bResult, GetLastError(), mStatus_UnknownErr );
644         require_noerr( err, exit );
645
646 exit:
647
648         if ( err )
649         {
650                 randomNumber = rand();
651         }
652
653         return randomNumber;
654 }
655
656 //===========================================================================================================================
657 //      mDNSPlatformTimeInit
658 //===========================================================================================================================
659
660 mDNSexport mStatus      mDNSPlatformTimeInit( void )
661 {
662         // No special setup is required on Windows -- we just use GetTickCount().
663         return( mStatus_NoError );
664 }
665
666 //===========================================================================================================================
667 //      mDNSPlatformRawTime
668 //===========================================================================================================================
669
670 mDNSexport mDNSs32      mDNSPlatformRawTime( void )
671 {
672         return( (mDNSs32) GetTickCount() );
673 }
674
675 //===========================================================================================================================
676 //      mDNSPlatformUTC
677 //===========================================================================================================================
678
679 mDNSexport mDNSs32      mDNSPlatformUTC( void )
680 {
681         return ( mDNSs32 ) time( NULL );
682 }
683
684 //===========================================================================================================================
685 //      mDNSPlatformInterfaceNameToID
686 //===========================================================================================================================
687
688 mDNSexport mStatus      mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID )
689 {
690         mStatus                                 err;
691         mDNSInterfaceData *             ifd;
692         
693         check( inMDNS );
694         check( inMDNS->p );
695         check( inName );
696         
697         // Search for an interface with the specified name,
698         
699         for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
700         {
701                 if( strcmp( ifd->name, inName ) == 0 )
702                 {
703                         break;
704                 }
705         }
706         require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
707         
708         // Success!
709         
710         if( outID )
711         {
712                 *outID = (mDNSInterfaceID) ifd;
713         }
714         err = mStatus_NoError;
715         
716 exit:
717         return( err );
718 }
719
720 //===========================================================================================================================
721 //      mDNSPlatformInterfaceIDToInfo
722 //===========================================================================================================================
723
724 mDNSexport mStatus      mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo )
725 {
726         mStatus                                 err;
727         mDNSInterfaceData *             ifd;
728         
729         check( inMDNS );
730         check( inID );
731         check( outInfo );
732         
733         // Search for an interface with the specified ID,
734         
735         for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
736         {
737                 if( ifd == (mDNSInterfaceData *) inID )
738                 {
739                         break;
740                 }
741         }
742         require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
743         
744         // Success!
745         
746         outInfo->name   = ifd->name;
747         outInfo->ip     = ifd->interfaceInfo.ip;
748         err                     = mStatus_NoError;
749         
750 exit:
751         return( err );
752 }
753
754 //===========================================================================================================================
755 //      mDNSPlatformInterfaceIDfromInterfaceIndex
756 //===========================================================================================================================
757
758 mDNSexport mDNSInterfaceID      mDNSPlatformInterfaceIDfromInterfaceIndex( mDNS * const inMDNS, mDNSu32 inIndex )
759 {
760         mDNSInterfaceID         id;
761         
762         id = mDNSNULL;
763         if( inIndex == kDNSServiceInterfaceIndexLocalOnly )
764         {
765                 id = mDNSInterface_LocalOnly;
766         }
767         else if( inIndex != 0 )
768         {
769                 mDNSInterfaceData *             ifd;
770                 
771                 for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
772                 {
773                         if( ( ifd->scopeID == inIndex ) && ifd->interfaceInfo.InterfaceActive )
774                         {
775                                 id = ifd->interfaceInfo.InterfaceID;
776                                 break;
777                         }
778                 }
779                 check( ifd );
780         }
781         return( id );
782 }
783
784 //===========================================================================================================================
785 //      mDNSPlatformInterfaceIndexfromInterfaceID
786 //===========================================================================================================================
787         
788 mDNSexport mDNSu32      mDNSPlatformInterfaceIndexfromInterfaceID( mDNS * const inMDNS, mDNSInterfaceID inID )
789 {
790         mDNSu32         index;
791         
792         index = 0;
793         if( inID == mDNSInterface_LocalOnly )
794         {
795                 index = (mDNSu32) kDNSServiceInterfaceIndexLocalOnly;
796         }
797         else if( inID )
798         {
799                 mDNSInterfaceData *             ifd;
800                 
801                 // Search active interfaces.
802                 for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
803                 {
804                         if( (mDNSInterfaceID) ifd == inID )
805                         {
806                                 index = ifd->scopeID;
807                                 break;
808                         }
809                 }
810                 
811                 // Search inactive interfaces too so remove events for inactive interfaces report the old interface index.
812                 
813                 if( !ifd )
814                 {
815                         for( ifd = inMDNS->p->inactiveInterfaceList; ifd; ifd = ifd->next )
816                         {
817                                 if( (mDNSInterfaceID) ifd == inID )
818                                 {
819                                         index = ifd->scopeID;
820                                         break;
821                                 }
822                         }
823                 }
824                 check( ifd );
825         }
826         return( index );
827 }
828
829
830 //===========================================================================================================================
831 //      mDNSPlatformTCPSocket
832 //===========================================================================================================================
833
834 TCPSocket *
835 mDNSPlatformTCPSocket
836         (
837         mDNS                    * const m,
838         TCPSocketFlags          flags,
839         mDNSIPPort                      *       port 
840         )
841 {
842         TCPSocket *             sock    = NULL;
843         u_long                          on              = 1;  // "on" for setsockopt
844         struct sockaddr_in      saddr;
845         int                                     len;
846         mStatus                         err             = mStatus_NoError;
847
848         DEBUG_UNUSED( m );
849
850         require_action( flags == 0, exit, err = mStatus_UnsupportedErr );
851
852         // Setup connection data object
853
854         sock = (TCPSocket *) malloc( sizeof( TCPSocket ) );
855         require_action( sock, exit, err = mStatus_NoMemoryErr );
856         mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
857         sock->fd                = INVALID_SOCKET;
858         sock->flags             = flags;
859         sock->m                 = m;
860
861         mDNSPlatformMemZero(&saddr, sizeof(saddr));
862         saddr.sin_family                = AF_INET;
863         saddr.sin_addr.s_addr   = htonl( INADDR_ANY );
864         saddr.sin_port                  = port->NotAnInteger;
865         
866         // Create the socket
867
868         sock->fd = socket(AF_INET, SOCK_STREAM, 0);
869         err = translate_errno( sock->fd != INVALID_SOCKET, WSAGetLastError(), mStatus_UnknownErr );
870         require_noerr( err, exit );
871
872         // bind
873
874         err = bind( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr )  );
875         err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
876         require_noerr( err, exit );
877
878         // Set it to be non-blocking
879
880         err = ioctlsocket( sock->fd, FIONBIO, &on );
881         err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
882         require_noerr( err, exit );
883
884         // Get port number
885
886         mDNSPlatformMemZero( &saddr, sizeof( saddr ) );
887         len = sizeof( saddr );
888
889         err = getsockname( sock->fd, ( struct sockaddr* ) &saddr, &len );
890         err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
891         require_noerr( err, exit );
892
893         port->NotAnInteger = saddr.sin_port;
894
895 exit:
896
897         if ( err && sock )
898         {
899                 TCPFreeSocket( sock );
900                 sock = mDNSNULL;
901         }
902
903         return sock;
904
905
906 //===========================================================================================================================
907 //      mDNSPlatformTCPConnect
908 //===========================================================================================================================
909
910 mStatus
911 mDNSPlatformTCPConnect
912         (
913         TCPSocket                       *       sock,
914         const mDNSAddr          *       inDstIP, 
915         mDNSOpaque16                    inDstPort, 
916         mDNSInterfaceID                 inInterfaceID,
917         TCPConnectionCallback   inCallback, 
918         void *                                  inContext
919         )
920 {
921         struct sockaddr_in      saddr;
922         mStatus                         err             = mStatus_NoError;
923
924         DEBUG_UNUSED( inInterfaceID );
925
926         if ( inDstIP->type != mDNSAddrType_IPv4 )
927         {
928                 LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: operation not supported");
929                 return mStatus_UnknownErr;
930         }
931
932         // Setup connection data object
933
934         sock->readEventHandler  = TCPCanRead;
935         sock->userCallback              = inCallback;
936         sock->userContext               = inContext;
937
938         mDNSPlatformMemZero(&saddr, sizeof(saddr));
939         saddr.sin_family        = AF_INET;
940         saddr.sin_port          = inDstPort.NotAnInteger;
941         memcpy(&saddr.sin_addr, &inDstIP->ip.v4.NotAnInteger, sizeof(saddr.sin_addr));
942
943         // Try and do connect
944
945         err = connect( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr ) );
946         require_action( !err || ( WSAGetLastError() == WSAEWOULDBLOCK ), exit, err = mStatus_ConnFailed );
947         sock->connected = !err ? TRUE : FALSE;
948
949         if ( sock->connected )
950         {
951                 err = TCPAddSocket( sock->m, sock );
952                 require_noerr( err, exit );
953         }
954         else
955         {
956                 require_action( sock->m->p->registerWaitableEventFunc != NULL, exit, err = mStatus_ConnFailed );
957
958                 sock->connectEvent      = CreateEvent( NULL, FALSE, FALSE, NULL );
959                 err = translate_errno( sock->connectEvent, GetLastError(), mStatus_UnknownErr );
960                 require_noerr( err, exit );
961
962                 err = WSAEventSelect( sock->fd, sock->connectEvent, FD_CONNECT );
963                 require_noerr( err, exit );
964
965                 err = sock->m->p->registerWaitableEventFunc( sock->m, sock->connectEvent, sock, TCPDidConnect );
966                 require_noerr( err, exit );
967         }
968
969 exit:
970
971         if ( !err )
972         {
973                 err = sock->connected ? mStatus_ConnEstablished : mStatus_ConnPending;
974         }
975
976         return err;
977 }
978
979 //===========================================================================================================================
980 //      mDNSPlatformTCPAccept
981 //===========================================================================================================================
982
983 mDNSexport 
984 mDNSexport TCPSocket *mDNSPlatformTCPAccept( TCPSocketFlags flags, int fd )
985         {
986         TCPSocket       *       sock = NULL;
987         mStatus                                                 err = mStatus_NoError;
988
989         require_action( !flags, exit, err = mStatus_UnsupportedErr );
990
991         sock = malloc( sizeof( TCPSocket ) );
992         require_action( sock, exit, err = mStatus_NoMemoryErr );
993         
994         mDNSPlatformMemZero( sock, sizeof( *sock ) );
995
996         sock->fd        = fd;
997         sock->flags = flags;
998
999 exit:
1000
1001         if ( err && sock )
1002         {
1003                 free( sock );
1004                 sock = NULL;
1005         }
1006
1007         return sock;
1008         }
1009
1010
1011 //===========================================================================================================================
1012 //      mDNSPlatformTCPCloseConnection
1013 //===========================================================================================================================
1014
1015 mDNSexport void mDNSPlatformTCPCloseConnection( TCPSocket *sock )
1016 {
1017         check( sock );
1018
1019         if ( sock->connectEvent && sock->m->p->unregisterWaitableEventFunc )
1020         {
1021                 sock->m->p->unregisterWaitableEventFunc( sock->m, sock->connectEvent );
1022         }
1023
1024         if ( sock->fd != INVALID_SOCKET )
1025         {
1026                 closesocket( sock->fd );
1027                 sock->fd = INVALID_SOCKET;
1028
1029                 QueueUserAPC( ( PAPCFUNC ) TCPFreeSocket, sock->m->p->mainThread, ( ULONG_PTR ) sock );
1030         }
1031 }
1032
1033 //===========================================================================================================================
1034 //      mDNSPlatformReadTCP
1035 //===========================================================================================================================
1036
1037 mDNSexport long mDNSPlatformReadTCP( TCPSocket *sock, void *inBuffer, unsigned long inBufferSize, mDNSBool * closed )
1038 {
1039         unsigned long   bytesLeft;
1040         int                             wsaError;
1041         long                    ret;
1042
1043         *closed = sock->closed;
1044         wsaError = sock->lastError;
1045         ret = -1;
1046
1047         if ( *closed )
1048         {
1049                 ret = 0;
1050         }
1051         else if ( sock->lastError == 0 )
1052         {
1053                 // First check to see if we have any data left in our buffer
1054
1055                 bytesLeft = ( DWORD ) ( sock->eptr - sock->bptr );
1056
1057                 if ( bytesLeft )
1058                 {
1059                         unsigned long bytesToCopy = ( bytesLeft < inBufferSize ) ? bytesLeft : inBufferSize;
1060
1061                         memcpy( inBuffer, sock->bptr, bytesToCopy );
1062                         sock->bptr += bytesToCopy;
1063
1064                         ret = bytesToCopy;
1065
1066                         if ( bytesLeft == bytesToCopy )
1067                         {
1068                                 sock->lastError = TCPBeginRecv( sock );
1069                                 
1070                                 // If we can't immediately queue up another read, abort the connection
1071                                 // now, even if we successfully wrote bytes to the buffer.
1072                                 // We don't expect this to happen unless something is seriously borked.
1073                                 // If we run into this in the real world, we should consider queuing up
1074                                 // a user APC function to defer an explicit callback to the read event handler
1075                                 // to inform the consumer of the problem.
1076
1077                                 if ( sock->lastError )
1078                                 {
1079                                         dlog( kDebugLevelError, DEBUG_NAME "TCPBeginRecv failed with error %d\n", sock->lastError );
1080                                         wsaError = sock->lastError;
1081                                         ret = -1;
1082                                 }
1083                         }
1084                 }
1085                 else
1086                 {
1087                         wsaError = WSAEWOULDBLOCK;
1088                 }
1089         }
1090
1091         // Always set the last winsock error, so that we don't inadvertently use a previous one         
1092         
1093         WSASetLastError( wsaError );
1094
1095         return ret;
1096 }
1097
1098
1099 //===========================================================================================================================
1100 //      mDNSPlatformWriteTCP
1101 //===========================================================================================================================
1102
1103 mDNSexport long mDNSPlatformWriteTCP( TCPSocket *sock, const char *inMsg, unsigned long inMsgSize )
1104 {
1105         int                     nsent;
1106         OSStatus        err;
1107
1108         nsent = send( sock->fd, inMsg, inMsgSize, 0 );
1109
1110         err = translate_errno( ( nsent >= 0 ) || ( WSAGetLastError() == WSAEWOULDBLOCK ), WSAGetLastError(), mStatus_UnknownErr );
1111         require_noerr( err, exit );
1112
1113         if ( nsent < 0)
1114         {
1115                 nsent = 0;
1116         }
1117                 
1118 exit:
1119
1120         return nsent;
1121 }
1122
1123 //===========================================================================================================================
1124 //      mDNSPlatformTCPGetFD
1125 //===========================================================================================================================
1126
1127 mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock )
1128 {
1129         return ( int ) sock->fd;
1130 }
1131
1132
1133 //===========================================================================================================================
1134 //      TCPAddConnection
1135 //===========================================================================================================================
1136
1137 mStatus TCPAddSocket( mDNS * const inMDNS, TCPSocket *sock )
1138 {
1139         mStatus err;
1140
1141         ( void ) inMDNS;
1142
1143         dlog( kDebugLevelChatty, DEBUG_NAME "adding TCPSocket 0x%x:%d\n", sock, sock->fd );
1144         err = TCPBeginRecv( sock );
1145         require_noerr( err, exit );
1146
1147 exit:
1148
1149         return err;
1150 }
1151
1152
1153 //===========================================================================================================================
1154 //      TCPDidConnect
1155 //===========================================================================================================================
1156
1157 mDNSlocal void TCPDidConnect( mDNS * const inMDNS, HANDLE event, void * context )\r
1158 {\r
1159         TCPSocket * sock = ( TCPSocket* ) context;\r
1160         TCPConnectionCallback callback = NULL;\r
1161         WSANETWORKEVENTS sockEvent;\r
1162         int err = kNoErr;\r
1163 \r
1164         if ( inMDNS->p->unregisterWaitableEventFunc )\r
1165         {\r
1166                 inMDNS->p->unregisterWaitableEventFunc( inMDNS, event );\r
1167         }\r
1168 \r
1169         if ( sock )\r
1170         {\r
1171                 callback = ( TCPConnectionCallback ) sock->userCallback;\r
1172                 err = WSAEnumNetworkEvents( sock->fd, sock->connectEvent, &sockEvent );\r
1173                 require_noerr( err, exit );\r
1174                 require_action( sockEvent.lNetworkEvents & FD_CONNECT, exit, err = mStatus_UnknownErr );\r
1175                 require_action( sockEvent.iErrorCode[ FD_CONNECT_BIT ] == 0, exit, err = sockEvent.iErrorCode[ FD_CONNECT_BIT ] );\r
1176 \r
1177                 sock->connected = mDNStrue;\r
1178 \r
1179                 if ( sock->fd != INVALID_SOCKET )\r
1180                 {\r
1181                         err = TCPAddSocket( sock->m, sock );\r
1182                         require_noerr( err, exit );\r
1183                 }\r
1184 \r
1185                 if ( callback )\r
1186                 {\r
1187                         callback( sock, sock->userContext, TRUE, 0 );\r
1188                 }\r
1189         }\r
1190 \r
1191 exit:\r
1192 \r
1193         if ( err && callback )\r
1194         {\r
1195                 callback( sock, sock->userContext, TRUE, err );\r
1196         }\r
1197 }
1198
1199
1200
1201 //===========================================================================================================================
1202 //      TCPCanRead
1203 //===========================================================================================================================
1204
1205 mDNSlocal void TCPCanRead( TCPSocket * sock )
1206 {
1207         TCPConnectionCallback callback = ( TCPConnectionCallback ) sock->userCallback;
1208
1209         if ( callback )
1210         {
1211                 callback( sock, sock->userContext, mDNSfalse, sock->lastError );
1212         }
1213 }
1214
1215
1216 //===========================================================================================================================
1217 //      TCPBeginRecv
1218 //===========================================================================================================================
1219
1220 mDNSlocal mStatus TCPBeginRecv( TCPSocket * sock )
1221 {
1222         DWORD   bytesReceived   = 0;
1223         DWORD   flags                   = 0;
1224         mStatus err;
1225
1226         ZeroMemory( &sock->overlapped, sizeof( sock->overlapped ) );
1227         sock->overlapped.hEvent = sock;
1228
1229         sock->wbuf.buf = ( char* ) sock->buf;
1230         sock->wbuf.len = sizeof( sock->buf );
1231
1232         err = WSARecv( sock->fd, &sock->wbuf, 1, &bytesReceived, &flags, &sock->overlapped, ( LPWSAOVERLAPPED_COMPLETION_ROUTINE ) TCPEndRecv );
1233         err = translate_errno( ( err == 0 ) || ( WSAGetLastError() == WSA_IO_PENDING ), WSAGetLastError(), kUnknownErr );
1234         require_noerr( err, exit );
1235
1236 exit:
1237
1238         return err;
1239 }
1240
1241
1242 //===========================================================================================================================
1243 //      TCPEndRecv
1244 //===========================================================================================================================
1245
1246 mDNSlocal void CALLBACK TCPEndRecv( DWORD error, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags )
1247 {
1248         TCPSocket * sock;\r
1249 \r
1250         ( void ) flags;\r
1251 \r
1252         sock = ( overlapped != NULL ) ? overlapped->hEvent : NULL;
1253
1254         if ( sock && ( sock->fd != INVALID_SOCKET ) )
1255         {
1256                 sock->lastError = error;
1257
1258                 if ( !error )
1259                 {
1260                         if ( bytesTransferred )
1261                         {
1262                                 sock->bptr = sock->buf;
1263                                 sock->eptr = sock->buf + bytesTransferred;
1264                         }
1265                         else
1266                         {
1267                                 sock->closed = TRUE;
1268                         }
1269                 }
1270
1271                 if ( sock->readEventHandler != NULL )
1272                 {
1273                         sock->readEventHandler( sock );
1274                 }
1275         }
1276 }
1277
1278         
1279 //===========================================================================================================================
1280 //      mDNSPlatformUDPSocket
1281 //===========================================================================================================================
1282
1283 mDNSexport UDPSocket* mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
1284 {
1285         UDPSocket*      sock    = NULL;
1286         mDNSIPPort      port    = requestedport;
1287         mStatus         err             = mStatus_NoError;
1288         unsigned        i;
1289
1290         // Setup connection data object
1291
1292         sock = ( UDPSocket* ) malloc(sizeof( UDPSocket ) );
1293         require_action( sock, exit, err = mStatus_NoMemoryErr );
1294         memset( sock, 0, sizeof( UDPSocket ) );
1295
1296         // Create the socket
1297
1298         sock->fd                        = INVALID_SOCKET;
1299         sock->recvMsgPtr        = m->p->unicastSock4.recvMsgPtr;
1300         sock->addr                      = m->p->unicastSock4.addr;
1301         sock->ifd                       = NULL;
1302         sock->m                         = m;
1303
1304         // Try at most 10000 times to get a unique random port
1305
1306         for (i=0; i<10000; i++)
1307         {
1308                 struct sockaddr_in saddr;
1309
1310                 saddr.sin_family                = AF_INET;
1311                 saddr.sin_addr.s_addr   = 0;
1312
1313                 // The kernel doesn't do cryptographically strong random port
1314                 // allocation, so we do it ourselves here
1315
1316         if (mDNSIPPortIsZero(requestedport))
1317                 {
1318                         port = mDNSOpaque16fromIntVal( ( mDNSu16 ) ( 0xC000 + mDNSRandom(0x3FFF) ) );
1319                 }
1320
1321                 saddr.sin_port = port.NotAnInteger;
1322
1323         err = SetupSocket(m, ( struct sockaddr* ) &saddr, port, &sock->fd );
1324         if (!err) break;
1325         }
1326
1327         require_noerr( err, exit );
1328
1329         // Set the port
1330
1331         sock->port = port;
1332
1333         // Arm the completion routine
1334
1335         err = UDPBeginRecv( sock );
1336         require_noerr( err, exit ); 
1337
1338         // Bookkeeping
1339
1340         sock->next                      = gUDPSocketList;
1341         gUDPSocketList          = sock;
1342         gUDPSockets++;
1343
1344 exit:
1345
1346         if ( err && sock )
1347         {
1348                 UDPFreeSocket( sock );
1349                 sock = NULL;
1350         }
1351
1352         return sock;
1353 }
1354         
1355 //===========================================================================================================================
1356 //      mDNSPlatformUDPClose
1357 //===========================================================================================================================
1358         
1359 mDNSexport void mDNSPlatformUDPClose( UDPSocket *sock )
1360 {
1361         UDPSocket       *       current  = gUDPSocketList;
1362         UDPSocket       *       last = NULL;
1363
1364         while ( current )
1365         {
1366                 if ( current == sock )
1367                 {
1368                         if ( last == NULL )
1369                         {
1370                                 gUDPSocketList = sock->next;
1371                         }
1372                         else
1373                         {
1374                                 last->next = sock->next;
1375                         }
1376
1377                         // Alertable I/O is great, except not so much when it comes to closing
1378                         // the socket.  Anything that has been previously queued for this socket
1379                         // will stay in the queue after you close the socket.  This is problematic
1380                         // for obvious reasons. So we'll attempt to workaround this by closing
1381                         // the socket which will prevent any further queued packets and then not calling
1382                         // UDPFreeSocket directly, but by queueing it using QueueUserAPC.  The queues
1383                         // are FIFO, so that will execute *after* any other previous items in the queue
1384                         //
1385                         // UDPEndRecv will check if the socket is valid, and if not, it will ignore
1386                         // the packet
1387
1388                         closesocket( sock->fd );
1389                         sock->fd = INVALID_SOCKET;
1390
1391                         QueueUserAPC( ( PAPCFUNC ) UDPFreeSocket, sock->m->p->mainThread, ( ULONG_PTR ) sock );
1392
1393                         gUDPSockets--;
1394
1395                         break;
1396                 }
1397
1398                 last    = current;
1399                 current = current->next;
1400         }
1401 }
1402
1403
1404 //===========================================================================================================================
1405 //      mDNSPlatformSendUDP
1406 //===========================================================================================================================
1407
1408 mDNSexport mStatus
1409         mDNSPlatformSendUDP( 
1410                 const mDNS * const                      inMDNS, 
1411                 const void * const              inMsg, 
1412                 const mDNSu8 * const            inMsgEnd, 
1413                 mDNSInterfaceID                         inInterfaceID, 
1414                 UDPSocket *                                     inSrcSocket,
1415                 const mDNSAddr *                        inDstIP, 
1416                 mDNSIPPort                                      inDstPort )
1417 {
1418         SOCKET                                          sendingsocket = INVALID_SOCKET;
1419         mStatus                                         err = mStatus_NoError;
1420         mDNSInterfaceData *                     ifd = (mDNSInterfaceData*) inInterfaceID;
1421         struct sockaddr_storage         addr;
1422         int                                                     n;
1423         
1424         DEBUG_USE_ONLY( inMDNS );
1425         
1426         n = (int)( inMsgEnd - ( (const mDNSu8 * const) inMsg ) );
1427         check( inMDNS );
1428         check( inMsg );
1429         check( inMsgEnd );
1430         check( inDstIP );
1431         
1432         dlog( kDebugLevelChatty, DEBUG_NAME "platform send %d bytes to %#a:%u\n", n, inDstIP, ntohs( inDstPort.NotAnInteger ) );
1433         
1434         if( inDstIP->type == mDNSAddrType_IPv4 )
1435         {
1436                 struct sockaddr_in *            sa4;
1437                 
1438                 sa4                                             = (struct sockaddr_in *) &addr;
1439                 sa4->sin_family                 = AF_INET;
1440                 sa4->sin_port                   = inDstPort.NotAnInteger;
1441                 sa4->sin_addr.s_addr    = inDstIP->ip.v4.NotAnInteger;
1442                 sendingsocket           = ifd ? ifd->sock.fd : inMDNS->p->unicastSock4.fd;
1443
1444                 if (inSrcSocket) { sendingsocket = inSrcSocket->fd; debugf("mDNSPlatformSendUDP using port %d, static port %d, sock %d", mDNSVal16(inSrcSocket->port), inMDNS->p->unicastSock4.fd, sendingsocket); }
1445         }
1446         else if( inDstIP->type == mDNSAddrType_IPv6 )
1447         {
1448                 struct sockaddr_in6 *           sa6;
1449                 
1450                 sa6                                     = (struct sockaddr_in6 *) &addr;
1451                 sa6->sin6_family        = AF_INET6;
1452                 sa6->sin6_port          = inDstPort.NotAnInteger;
1453                 sa6->sin6_flowinfo      = 0;
1454                 sa6->sin6_addr          = *( (struct in6_addr *) &inDstIP->ip.v6 );
1455                 sa6->sin6_scope_id      = 0;    // Windows requires the scope ID to be zero. IPV6_MULTICAST_IF specifies interface.
1456                 sendingsocket           = ifd ? ifd->sock.fd : inMDNS->p->unicastSock6.fd;
1457         }
1458         else
1459         {
1460                 dlog( kDebugLevelError, DEBUG_NAME "%s: dst is not an IPv4 or IPv6 address (type=%d)\n", __ROUTINE__, inDstIP->type );
1461                 err = mStatus_BadParamErr;
1462                 goto exit;
1463         }
1464         
1465         if (IsValidSocket(sendingsocket))
1466         {
1467                 n = sendto( sendingsocket, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
1468                 err = translate_errno( n > 0, errno_compat(), kWriteErr );
1469
1470                 if ( err )
1471                 {
1472                         // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
1473
1474                         if ( !mDNSAddressIsAllDNSLinkGroup( inDstIP ) && ( WSAGetLastError() == WSAEHOSTDOWN || WSAGetLastError() == WSAENETDOWN || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAENETUNREACH ) )
1475                         {
1476                                 err = mStatus_TransientErr;
1477                         }
1478                         else
1479                         {
1480                                 require_noerr( err, exit );
1481                         }
1482                 }
1483         }
1484         
1485 exit:
1486         return( err );
1487 }
1488
1489
1490 mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
1491         {
1492         DEBUG_UNUSED( m );
1493         DEBUG_UNUSED( InterfaceID );
1494         }
1495
1496 //===========================================================================================================================
1497 //      mDNSPlatformSendRawPacket
1498 //===========================================================================================================================
1499         
1500 mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
1501         {
1502         DEBUG_UNUSED( msg );
1503         DEBUG_UNUSED( end );
1504         DEBUG_UNUSED( InterfaceID );
1505         }
1506
1507 mDNSexport void mDNSPlatformReceiveRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
1508         {
1509         DEBUG_UNUSED( msg );
1510         DEBUG_UNUSED( end );
1511         DEBUG_UNUSED( InterfaceID );
1512         }
1513
1514 mDNSexport void mDNSPlatformSetLocalARP( const mDNSv4Addr * const tpa, const mDNSEthAddr * const tha, mDNSInterfaceID InterfaceID )
1515         {
1516         DEBUG_UNUSED( tpa );
1517         DEBUG_UNUSED( tha );
1518         DEBUG_UNUSED( InterfaceID );
1519         }
1520
1521 mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
1522         {
1523         dlog( kDebugLevelInfo, "%s\n", msg );
1524         }
1525
1526 mDNSexport void mDNSPlatformWriteLogMsg( const char * ident, const char * msg, int flags )
1527         {
1528         DEBUG_UNUSED( ident );
1529         DEBUG_UNUSED( flags );
1530         dlog( kDebugLevelInfo, "%s\n", msg );
1531         }
1532
1533 mDNSexport void mDNSPlatformSourceAddrForDest( mDNSAddr * const src, const mDNSAddr * const dst )
1534         {
1535         DEBUG_UNUSED( src );
1536         DEBUG_UNUSED( dst );
1537         }
1538
1539 //===========================================================================================================================
1540 //      mDNSPlatformTLSSetupCerts
1541 //===========================================================================================================================
1542
1543 mDNSexport mStatus
1544 mDNSPlatformTLSSetupCerts(void)
1545 {
1546         return mStatus_UnsupportedErr;
1547 }
1548
1549 //===========================================================================================================================
1550 //      mDNSPlatformTLSTearDownCerts
1551 //===========================================================================================================================
1552
1553 mDNSexport void
1554 mDNSPlatformTLSTearDownCerts(void)
1555 {
1556 }
1557
1558 //===========================================================================================================================
1559 //      mDNSPlatformSetDNSConfig
1560 //===========================================================================================================================
1561
1562 mDNSlocal void SetDNSServers( mDNS *const m );
1563 mDNSlocal void SetSearchDomainList( void );
1564
1565 mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **regDomains, DNameListElem **browseDomains)
1566 {
1567         if (setservers) SetDNSServers(m);
1568         if (setsearch) SetSearchDomainList();
1569         
1570         if ( fqdn )
1571         {
1572                 GetDDNSFQDN( fqdn );
1573         }
1574
1575         if ( browseDomains )
1576         {
1577                 GetDDNSDomains( browseDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains );
1578         }
1579
1580         if ( regDomains )
1581         {
1582                 GetDDNSDomains( regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
1583         }
1584 }
1585
1586
1587 //===========================================================================================================================
1588 //      mDNSPlatformDynDNSHostNameStatusChanged
1589 //===========================================================================================================================
1590
1591 mDNSexport void
1592 mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
1593 {
1594         char            uname[MAX_ESCAPED_DOMAIN_NAME];
1595         BYTE            bStatus;
1596         LPCTSTR         name;
1597         HKEY            key = NULL;
1598         mStatus         err;
1599         char    *       p;
1600         
1601         ConvertDomainNameToCString(dname, uname);
1602         
1603         p = uname;
1604
1605         while (*p)
1606         {
1607                 *p = (char) tolower(*p);
1608                 if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
1609                 p++;
1610         }
1611
1612         check( strlen( p ) <= MAX_ESCAPED_DOMAIN_NAME );
1613         name = kServiceParametersNode TEXT("\\DynDNS\\State\\HostNames");
1614         err = RegCreateKey( HKEY_LOCAL_MACHINE, name, &key );
1615         require_noerr( err, exit );
1616
1617         bStatus = ( status ) ? 0 : 1;
1618         err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &bStatus, sizeof(DWORD) );
1619         require_noerr( err, exit );
1620
1621 exit:
1622
1623         if ( key )
1624         {
1625                 RegCloseKey( key );
1626         }
1627
1628         return;
1629 }
1630
1631
1632 //===========================================================================================================================
1633 //      SetDomainSecrets
1634 //===========================================================================================================================
1635
1636 // This routine needs to be called whenever the system secrets database changes.
1637 // We call it from DynDNSConfigDidChange and mDNSPlatformInit
1638
1639 void
1640 SetDomainSecrets( mDNS * const m )
1641 {
1642         DomainAuthInfo *ptr;
1643         domainname              fqdn;
1644         DNameListElem * regDomains = NULL;
1645
1646         // Rather than immediately deleting all keys now, we mark them for deletion in ten seconds.
1647         // In the case where the user simultaneously removes their DDNS host name and the key
1648         // for it, this gives mDNSResponder ten seconds to gracefully delete the name from the
1649         // server before it loses access to the necessary key. Otherwise, we'd leave orphaned
1650         // address records behind that we no longer have permission to delete.
1651         
1652         for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
1653                 ptr->deltime = NonZeroTime(m->timenow + mDNSPlatformOneSecond*10);
1654
1655         GetDDNSFQDN( &fqdn );
1656
1657         if ( fqdn.c[ 0 ] )
1658         {
1659                 SetDomainSecret( m, &fqdn );
1660         }
1661
1662         GetDDNSDomains( &regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
1663
1664         while ( regDomains )
1665         {
1666                 DNameListElem * current = regDomains;
1667                 SetDomainSecret( m, &current->name );
1668                 regDomains = regDomains->next;
1669                 free( current );
1670         }
1671 }
1672
1673
1674 //===========================================================================================================================
1675 //      SetSearchDomainList
1676 //===========================================================================================================================
1677
1678 mDNSlocal void SetDomainFromDHCP( void );
1679 mDNSlocal void SetReverseMapSearchDomainList( void );
1680
1681 mDNSlocal void
1682 SetSearchDomainList( void )
1683 {
1684         char                    *       searchList      = NULL;
1685         DWORD                           searchListLen;
1686         //DNameListElem *       head = NULL;
1687         //DNameListElem *       current = NULL;
1688         char                    *       tok;
1689         HKEY                            key;
1690         mStatus                         err;
1691
1692         err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &key );
1693         require_noerr( err, exit );
1694
1695         err = RegQueryString( key, "SearchList", &searchList, &searchListLen, NULL );
1696         require_noerr( err, exit );
1697
1698         // Windows separates the search domains with ','
1699
1700         tok = strtok( searchList, "," );
1701         while ( tok )
1702         {
1703                 if ( ( strcmp( tok, "" ) != 0 ) && ( strcmp( tok, "." ) != 0 ) )
1704                         mDNS_AddSearchDomain_CString(tok);
1705                 tok = strtok( NULL, "," );
1706         }
1707
1708 exit:
1709
1710         if ( searchList ) 
1711         {
1712                 free( searchList );
1713         }
1714
1715         if ( key )
1716         {
1717                 RegCloseKey( key );
1718         }
1719
1720         SetDomainFromDHCP();
1721         SetReverseMapSearchDomainList();
1722 }
1723
1724
1725 //===========================================================================================================================
1726 //      SetReverseMapSearchDomainList
1727 //===========================================================================================================================
1728
1729 mDNSlocal void
1730 SetReverseMapSearchDomainList( void )
1731 {
1732         struct ifaddrs  *       ifa;
1733
1734         ifa = myGetIfAddrs( 1 );
1735         while (ifa)
1736         {
1737                 mDNSAddr addr;
1738                 
1739                 if (ifa->ifa_addr->sa_family == AF_INET && !SetupAddr(&addr, ifa->ifa_addr) && !(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_netmask)
1740                 {
1741                         mDNSAddr        netmask;
1742                         char            buffer[256];
1743                         
1744                         if (!SetupAddr(&netmask, ifa->ifa_netmask))
1745                         {
1746                                 sprintf(buffer, "%d.%d.%d.%d.in-addr.arpa.", addr.ip.v4.b[3] & netmask.ip.v4.b[3],
1747                                                              addr.ip.v4.b[2] & netmask.ip.v4.b[2],
1748                                                              addr.ip.v4.b[1] & netmask.ip.v4.b[1],
1749                                                              addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
1750                                 mDNS_AddSearchDomain_CString(buffer);
1751                         }
1752                 }
1753         
1754                 ifa = ifa->ifa_next;
1755         }
1756
1757         return;
1758 }
1759
1760
1761 //===========================================================================================================================
1762 //      SetDNSServers
1763 //===========================================================================================================================
1764
1765 mDNSlocal void
1766 SetDNSServers( mDNS *const m )
1767 {
1768         PIP_PER_ADAPTER_INFO    pAdapterInfo    =       NULL;
1769         FIXED_INFO                      *       fixedInfo       = NULL;
1770         ULONG                                   bufLen          = 0;    
1771         IP_ADDR_STRING          *       dnsServerList;
1772         IP_ADDR_STRING          *       ipAddr;
1773         DWORD                                   index;
1774         int                                             i                       = 0;
1775         mStatus                                 err                     = kUnknownErr;
1776
1777         // Get the primary interface.
1778
1779         index = GetPrimaryInterface();
1780
1781         // This should have the interface index of the primary index.  Fall back in cases where
1782         // it can't be determined.
1783
1784         if ( index )
1785         {
1786                 bufLen = 0;
1787
1788                 for ( i = 0; i < 100; i++ )
1789                 {
1790                         err = GetPerAdapterInfo( index, pAdapterInfo, &bufLen );
1791
1792                         if ( err != ERROR_BUFFER_OVERFLOW )
1793                         {
1794                                 break;
1795                         }
1796
1797                         pAdapterInfo = (PIP_PER_ADAPTER_INFO) realloc( pAdapterInfo, bufLen );
1798                         require_action( pAdapterInfo, exit, err = mStatus_NoMemoryErr );
1799                 }
1800
1801                 require_noerr( err, exit );
1802
1803                 dnsServerList = &pAdapterInfo->DnsServerList;
1804         }
1805         else
1806         {
1807                 bufLen = sizeof( FIXED_INFO );
1808
1809                 for ( i = 0; i < 100; i++ )
1810                 {
1811                         if ( fixedInfo )
1812                         {
1813                                 GlobalFree( fixedInfo );
1814                                 fixedInfo = NULL;
1815                         }
1816
1817                         fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
1818                         require_action( fixedInfo, exit, err = mStatus_NoMemoryErr );
1819            
1820                         err = GetNetworkParams( fixedInfo, &bufLen );
1821
1822                         if ( err != ERROR_BUFFER_OVERFLOW )
1823                         {
1824                                 break;
1825                         }
1826                 }
1827
1828                 require_noerr( err, exit );
1829
1830                 dnsServerList = &fixedInfo->DnsServerList;
1831         }
1832
1833         for ( ipAddr = dnsServerList; ipAddr; ipAddr = ipAddr->Next )
1834         {
1835                 mDNSAddr addr;
1836                 err = StringToAddress( &addr, ipAddr->IpAddress.String );
1837                 if ( !err ) mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, &addr, UnicastDNSPort);
1838         }
1839
1840 exit:
1841
1842         if ( pAdapterInfo )
1843         {
1844                 free( pAdapterInfo );
1845         }
1846
1847         if ( fixedInfo )
1848         {
1849                 GlobalFree( fixedInfo );
1850         }
1851 }
1852
1853
1854 //===========================================================================================================================
1855 //      SetDomainFromDHCP
1856 //===========================================================================================================================
1857
1858 mDNSlocal void
1859 SetDomainFromDHCP( void )
1860 {
1861         int                                     i                       = 0;
1862         IP_ADAPTER_INFO *       pAdapterInfo;
1863         IP_ADAPTER_INFO *       pAdapter;
1864         DWORD                           bufLen;
1865         DWORD                           index;
1866         HKEY                            key = NULL;
1867         LPSTR                           domain = NULL;
1868         DWORD                           dwSize;
1869         mStatus                         err = mStatus_NoError;
1870
1871         pAdapterInfo    = NULL;
1872         
1873         for ( i = 0; i < 100; i++ )
1874         {
1875                 err = GetAdaptersInfo( pAdapterInfo, &bufLen);
1876
1877                 if ( err != ERROR_BUFFER_OVERFLOW )
1878                 {
1879                         break;
1880                 }
1881
1882                 pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
1883                 require_action( pAdapterInfo, exit, err = kNoMemoryErr );
1884         }
1885
1886         require_noerr( err, exit );
1887
1888         index = GetPrimaryInterface();
1889
1890         for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
1891         {
1892                 if ( pAdapter->IpAddressList.IpAddress.String &&
1893                      pAdapter->IpAddressList.IpAddress.String[0] &&
1894                      pAdapter->GatewayList.IpAddress.String &&
1895                      pAdapter->GatewayList.IpAddress.String[0] &&
1896                      ( !index || ( pAdapter->Index == index ) ) )
1897                 {
1898                         // Found one that will work
1899
1900                         char keyName[1024];
1901
1902                         _snprintf( keyName, 1024, "%s%s", "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\", pAdapter->AdapterName );
1903
1904                         err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyName, &key );
1905                         require_noerr( err, exit );
1906
1907                         err = RegQueryString( key, "Domain", &domain, &dwSize, NULL );
1908                         check_noerr( err );
1909
1910                         if ( !domain || !domain[0] )
1911                         {
1912                                 if ( domain )
1913                                 {
1914                                         free( domain );
1915                                         domain = NULL;
1916                                 }
1917
1918                                 err = RegQueryString( key, "DhcpDomain", &domain, &dwSize, NULL );
1919                                 check_noerr( err );
1920                         }
1921
1922                         if ( domain && domain[0] ) mDNS_AddSearchDomain_CString(domain);
1923
1924                         break;
1925                 }
1926         }
1927
1928 exit:
1929
1930         if ( pAdapterInfo )
1931         {
1932                 free( pAdapterInfo );
1933         }
1934
1935         if ( domain )
1936         {
1937                 free( domain );
1938         }
1939
1940         if ( key )
1941         {
1942                 RegCloseKey( key );
1943         }
1944 }
1945
1946
1947 //===========================================================================================================================
1948 //      mDNSPlatformGetPrimaryInterface
1949 //===========================================================================================================================
1950
1951 mDNSexport mStatus
1952 mDNSPlatformGetPrimaryInterface( mDNS * const m, mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router )
1953 {
1954         IP_ADAPTER_INFO *       pAdapterInfo;
1955         IP_ADAPTER_INFO *       pAdapter;
1956         DWORD                           bufLen;
1957         int                                     i;
1958         BOOL                            found;
1959         DWORD                           index;
1960         mStatus                         err = mStatus_NoError;
1961
1962         DEBUG_UNUSED( m );
1963
1964         *v6 = zeroAddr;
1965
1966         pAdapterInfo    = NULL;
1967         bufLen                  = 0;
1968         found                   = FALSE;
1969
1970         for ( i = 0; i < 100; i++ )
1971         {
1972                 err = GetAdaptersInfo( pAdapterInfo, &bufLen);
1973
1974                 if ( err != ERROR_BUFFER_OVERFLOW )
1975                 {
1976                         break;
1977                 }
1978
1979                 pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
1980                 require_action( pAdapterInfo, exit, err = kNoMemoryErr );
1981         }
1982
1983         require_noerr( err, exit );
1984
1985         index = GetPrimaryInterface();
1986
1987         for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
1988         {
1989                 if ( pAdapter->IpAddressList.IpAddress.String &&
1990                      pAdapter->IpAddressList.IpAddress.String[0] &&
1991                      pAdapter->GatewayList.IpAddress.String &&
1992                      pAdapter->GatewayList.IpAddress.String[0] &&
1993                      ( StringToAddress( v4, pAdapter->IpAddressList.IpAddress.String ) == mStatus_NoError ) &&
1994                      ( StringToAddress( router, pAdapter->GatewayList.IpAddress.String ) == mStatus_NoError ) &&
1995                      ( !index || ( pAdapter->Index == index ) ) )
1996                 {
1997                         // Found one that will work
1998
1999                         found = TRUE;
2000                         break;
2001                 }
2002         }
2003
2004 exit:
2005
2006         if ( pAdapterInfo )
2007         {
2008                 free( pAdapterInfo );
2009         }
2010
2011         return err;
2012 }
2013
2014
2015 #if 0
2016 #pragma mark -
2017 #endif
2018
2019 //===========================================================================================================================
2020 //      debugf_
2021 //===========================================================================================================================
2022 #if( MDNS_DEBUGMSGS )
2023 mDNSexport void debugf_( const char *inFormat, ... )
2024 {
2025         char            buffer[ 512 ];
2026     va_list             args;
2027     mDNSu32             length;
2028         
2029         va_start( args, inFormat );
2030         length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
2031         va_end( args );
2032         
2033         dlog( kDebugLevelInfo, "%s\n", buffer );
2034 }
2035 #endif
2036
2037 //===========================================================================================================================
2038 //      verbosedebugf_
2039 //===========================================================================================================================
2040
2041 #if( MDNS_DEBUGMSGS > 1 )
2042 mDNSexport void verbosedebugf_( const char *inFormat, ... )
2043 {
2044         char            buffer[ 512 ];
2045     va_list             args;
2046     mDNSu32             length;
2047         
2048         va_start( args, inFormat );
2049         length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
2050         va_end( args );
2051         
2052         dlog( kDebugLevelVerbose, "%s\n", buffer );
2053 }
2054 #endif
2055
2056 //===========================================================================================================================
2057 //      LogMsg
2058 //===========================================================================================================================
2059
2060 /*
2061 mDNSexport void LogMsg( const char *inFormat, ... )
2062 {
2063         char            buffer[ 512 ];
2064     va_list             args;
2065     mDNSu32             length;
2066         
2067         va_start( args, inFormat );
2068         length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
2069         va_end( args );
2070         
2071         dlog( kDebugLevelWarning, "%s\n", buffer );
2072 }
2073 */
2074
2075 #if 0
2076 #pragma mark -
2077 #pragma mark == Platform Internals  ==
2078 #endif
2079
2080
2081 //===========================================================================================================================
2082 //      SetupNiceName
2083 //===========================================================================================================================
2084
2085 mStatus SetupNiceName( mDNS * const inMDNS )
2086 {
2087         HKEY            descKey = NULL;
2088         char            utf8[ 256 ];
2089         LPCTSTR         s;
2090         LPWSTR          joinName;
2091         NETSETUP_JOIN_STATUS joinStatus;
2092         mStatus         err = 0;
2093         DWORD           namelen;
2094         BOOL            ok;
2095         
2096         check( inMDNS );
2097         
2098         // Set up the nice name.
2099         utf8[0] = '\0';
2100
2101         // First try and open the registry key that contains the computer description value
2102         s = TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters");
2103         err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &descKey);
2104         check_translated_errno( err == 0, errno_compat(), kNameErr );
2105
2106         if ( !err )
2107         {
2108                 TCHAR   desc[256];
2109                 DWORD   descSize = sizeof( desc );
2110
2111                 // look for the computer description
2112                 err = RegQueryValueEx( descKey, TEXT("srvcomment"), 0, NULL, (LPBYTE) &desc, &descSize);
2113                 
2114                 if ( !err )
2115                 {
2116                         err = TCHARtoUTF8( desc, utf8, sizeof( utf8 ) );
2117                 }
2118
2119                 if ( err )
2120                 {
2121                         utf8[ 0 ] = '\0';
2122                 }
2123         }
2124
2125         // if we can't find it in the registry, then use the hostname of the machine
2126         if ( err || ( utf8[ 0 ] == '\0' ) )
2127         {
2128                 TCHAR hostname[256];
2129                 
2130                 namelen = sizeof( hostname ) / sizeof( TCHAR );
2131
2132                 ok = GetComputerNameExW( ComputerNamePhysicalDnsHostname, hostname, &namelen );
2133                 err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
2134                 check_noerr( err );
2135                 
2136                 if( !err )
2137                 {
2138                         err = TCHARtoUTF8( hostname, utf8, sizeof( utf8 ) );
2139                 }
2140
2141                 if ( err )
2142                 {
2143                         utf8[ 0 ] = '\0';
2144                 }
2145         }
2146
2147         // if we can't get the hostname
2148         if ( err || ( utf8[ 0 ] == '\0' ) )
2149         {
2150                 // Invalidate name so fall back to a default name.
2151                 
2152                 strcpy( utf8, kMDNSDefaultName );
2153         }
2154
2155         utf8[ sizeof( utf8 ) - 1 ]      = '\0'; 
2156         inMDNS->nicelabel.c[ 0 ]        = (mDNSu8) (strlen( utf8 ) < MAX_DOMAIN_LABEL ? strlen( utf8 ) : MAX_DOMAIN_LABEL);
2157         memcpy( &inMDNS->nicelabel.c[ 1 ], utf8, inMDNS->nicelabel.c[ 0 ] );
2158         
2159         dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] );
2160         
2161         if ( descKey )
2162         {
2163                 RegCloseKey( descKey );
2164         }
2165
2166         ZeroMemory( inMDNS->p->nbname, sizeof( inMDNS->p->nbname ) );
2167         ZeroMemory( inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
2168
2169         namelen = sizeof( inMDNS->p->nbname );
2170         ok = GetComputerNameExA( ComputerNamePhysicalNetBIOS, inMDNS->p->nbname, &namelen );
2171         check( ok );
2172         if ( ok ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios name \"%s\"\n", inMDNS->p->nbname );
2173
2174         err = NetGetJoinInformation( NULL, &joinName, &joinStatus );
2175         check ( err == NERR_Success );
2176         if ( err == NERR_Success )
2177         {
2178                 if ( ( joinStatus == NetSetupWorkgroupName ) || ( joinStatus == NetSetupDomainName ) )
2179                 {
2180                         err = TCHARtoUTF8( joinName, inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
2181                         check( !err );
2182                         if ( !err ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios domain/workgroup \"%s\"\n", inMDNS->p->nbdomain );
2183                 }
2184
2185                 NetApiBufferFree( joinName );
2186                 joinName = NULL;
2187         }
2188
2189         err = 0;
2190
2191         return( err );
2192 }
2193
2194 //===========================================================================================================================
2195 //      SetupHostName
2196 //===========================================================================================================================
2197
2198 mDNSlocal mStatus       SetupHostName( mDNS * const inMDNS )
2199 {
2200         mStatus         err = 0;
2201         char            tempString[ 256 ];
2202         DWORD           tempStringLen;
2203         domainlabel tempLabel;
2204         BOOL            ok;
2205         
2206         check( inMDNS );
2207
2208         // Set up the nice name.
2209         tempString[ 0 ] = '\0';
2210
2211         // use the hostname of the machine
2212         tempStringLen = sizeof( tempString );
2213         ok = GetComputerNameExA( ComputerNamePhysicalDnsHostname, tempString, &tempStringLen );
2214         err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
2215         check_noerr( err );
2216
2217         // if we can't get the hostname
2218         if( err || ( tempString[ 0 ] == '\0' ) )
2219         {
2220                 // Invalidate name so fall back to a default name.
2221                 
2222                 strcpy( tempString, kMDNSDefaultName );
2223         }
2224
2225         tempString[ sizeof( tempString ) - 1 ] = '\0';
2226         tempLabel.c[ 0 ] = (mDNSu8) (strlen( tempString ) < MAX_DOMAIN_LABEL ? strlen( tempString ) : MAX_DOMAIN_LABEL );
2227         memcpy( &tempLabel.c[ 1 ], tempString, tempLabel.c[ 0 ] );
2228         
2229         // Set up the host name.
2230         
2231         ConvertUTF8PstringToRFC1034HostLabel( tempLabel.c, &inMDNS->hostlabel );
2232         if( inMDNS->hostlabel.c[ 0 ] == 0 )
2233         {
2234                 // Nice name has no characters that are representable as an RFC1034 name (e.g. Japanese) so use the default.
2235                 
2236                 MakeDomainLabelFromLiteralString( &inMDNS->hostlabel, kMDNSDefaultName );
2237         }
2238
2239         check( inMDNS->hostlabel.c[ 0 ] != 0 );
2240         
2241         mDNS_SetFQDN( inMDNS );
2242         
2243         dlog( kDebugLevelInfo, DEBUG_NAME "host name \"%.*s\"\n", inMDNS->hostlabel.c[ 0 ], &inMDNS->hostlabel.c[ 1 ] );
2244         
2245         return( err );
2246 }
2247
2248 //===========================================================================================================================
2249 //      SetupName
2250 //===========================================================================================================================
2251
2252 mDNSlocal mStatus       SetupName( mDNS * const inMDNS )
2253 {
2254         mStatus         err = 0;
2255         
2256         check( inMDNS );
2257         
2258         err = SetupNiceName( inMDNS );
2259         check_noerr( err );
2260
2261         err = SetupHostName( inMDNS );
2262         check_noerr( err );
2263
2264         return err;
2265 }
2266
2267
2268 //===========================================================================================================================
2269 //      SetupInterfaceList
2270 //===========================================================================================================================
2271
2272 mStatus SetupInterfaceList( mDNS * const inMDNS )
2273 {
2274         mStatus                                         err;
2275         mDNSInterfaceData **            next;
2276         mDNSInterfaceData *                     ifd;
2277         struct ifaddrs *                        addrs;
2278         struct ifaddrs *                        p;
2279         struct ifaddrs *                        loopbackv4;
2280         struct ifaddrs *                        loopbackv6;
2281         u_int                                           flagMask;
2282         u_int                                           flagTest;
2283         mDNSBool                                        foundv4;
2284         mDNSBool                                        foundv6;
2285         mDNSBool                                        foundUnicastSock4DestAddr;
2286         mDNSBool                                        foundUnicastSock6DestAddr;
2287         
2288         dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list\n" );
2289         check( inMDNS );
2290         check( inMDNS->p );
2291         
2292         inMDNS->p->registeredLoopback4  = mDNSfalse;
2293         inMDNS->p->nextDHCPLeaseExpires = 0x7FFFFFFF;
2294         addrs                                                   = NULL;
2295         foundv4                                                 = mDNSfalse;
2296         foundv6                                                 = mDNSfalse;
2297         foundUnicastSock4DestAddr               = mDNSfalse;
2298         foundUnicastSock6DestAddr               = mDNSfalse;
2299         
2300         // Tear down any existing interfaces that may be set up.
2301         
2302         TearDownInterfaceList( inMDNS );
2303
2304         // Set up the name of this machine.
2305         
2306         err = SetupName( inMDNS );
2307         check_noerr( err );
2308
2309         // Set up IPv4 interface(s). We have to set up IPv4 first so any IPv6 interface with an IPv4-routable address
2310         // can refer to the IPv4 interface when it registers to allow DNS AAAA records over the IPv4 interface.
2311         
2312         err = getifaddrs( &addrs );
2313         require_noerr( err, exit );
2314         
2315         loopbackv4      = NULL;
2316         loopbackv6      = NULL;
2317         next            = &inMDNS->p->interfaceList;
2318
2319         flagMask = IFF_UP | IFF_MULTICAST;
2320         flagTest = IFF_UP | IFF_MULTICAST;
2321         
2322 #if( MDNS_WINDOWS_ENABLE_IPV4 )
2323         for( p = addrs; p; p = p->ifa_next )
2324         {
2325                 if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
2326                 {
2327                         continue;
2328                 }
2329                 if( p->ifa_flags & IFF_LOOPBACK )
2330                 {
2331                         if( !loopbackv4 )
2332                         {
2333                                 loopbackv4 = p;
2334                         }
2335                         continue;
2336                 }
2337                 dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
2338                         p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
2339                 
2340                 err = SetupInterface( inMDNS, p, &ifd );
2341                 require_noerr( err, exit );
2342
2343                 // If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
2344                 // register him, but we also want to note that we haven't found a v4 interface
2345                 // so that we register loopback so same host operations work
2346                 
2347                 if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
2348                 {
2349                         foundv4 = mDNStrue;
2350                 }
2351
2352                 if ( p->ifa_dhcpEnabled && ( p->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
2353                 {
2354                         inMDNS->p->nextDHCPLeaseExpires = p->ifa_dhcpLeaseExpires;
2355                 }
2356
2357                 // If we're on a platform that doesn't have WSARecvMsg(), there's no way
2358                 // of determing the destination address of a packet that is sent to us.
2359                 // For multicast packets, that's easy to determine.  But for the unicast
2360                 // sockets, we'll fake it by taking the address of the first interface
2361                 // that is successfully setup.
2362
2363                 if ( !foundUnicastSock4DestAddr )
2364                 {
2365                         inMDNS->p->unicastSock4.addr = ifd->interfaceInfo.ip;
2366                         foundUnicastSock4DestAddr = TRUE;
2367                 }
2368                         
2369                 *next = ifd;
2370                 next  = &ifd->next;
2371                 ++inMDNS->p->interfaceCount;
2372         }
2373 #endif
2374         
2375         // Set up IPv6 interface(s) after IPv4 is set up (see IPv4 notes above for reasoning).
2376         
2377 #if( MDNS_WINDOWS_ENABLE_IPV6 )
2378         for( p = addrs; p; p = p->ifa_next )
2379         {
2380                 if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET6 ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
2381                 {
2382                         continue;
2383                 }
2384                 if( p->ifa_flags & IFF_LOOPBACK )
2385                 {
2386                         if( !loopbackv6 )
2387                         {
2388                                 loopbackv6 = p;
2389                         }
2390                         continue;
2391                 }
2392                 dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
2393                         p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
2394                 
2395                 err = SetupInterface( inMDNS, p, &ifd );
2396                 require_noerr( err, exit );
2397                                 
2398                 // If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
2399                 // register him, but we also want to note that we haven't found a v4 interface
2400                 // so that we register loopback so same host operations work
2401                 
2402                 if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
2403                 {
2404                         foundv6 = mDNStrue;
2405                 }
2406
2407                 // If we're on a platform that doesn't have WSARecvMsg(), there's no way
2408                 // of determing the destination address of a packet that is sent to us.
2409                 // For multicast packets, that's easy to determine.  But for the unicast
2410                 // sockets, we'll fake it by taking the address of the first interface
2411                 // that is successfully setup.
2412
2413                 if ( !foundUnicastSock6DestAddr )
2414                 {
2415                         inMDNS->p->unicastSock6.addr = ifd->interfaceInfo.ip;
2416                         foundUnicastSock6DestAddr = TRUE;
2417                 }
2418
2419                 *next = ifd;
2420                 next  = &ifd->next;
2421                 ++inMDNS->p->interfaceCount;
2422         }
2423 #endif
2424
2425         // If there are no real interfaces, but there is a loopback interface, use that so same-machine operations work.
2426
2427 #if( !MDNS_WINDOWS_ENABLE_IPV4 && !MDNS_WINDOWS_ENABLE_IPV6 )
2428         
2429         flagMask |= IFF_LOOPBACK;
2430         flagTest |= IFF_LOOPBACK;
2431         
2432         for( p = addrs; p; p = p->ifa_next )
2433         {
2434                 if( !p->ifa_addr || ( ( p->ifa_flags & flagMask ) != flagTest ) )
2435                 {
2436                         continue;
2437                 }
2438                 if( ( p->ifa_addr->sa_family != AF_INET ) && ( p->ifa_addr->sa_family != AF_INET6 ) )
2439                 {
2440                         continue;
2441                 }
2442                 
2443                 v4loopback = p;
2444                 break;
2445         }
2446         
2447 #endif
2448         
2449         if ( !foundv4 && loopbackv4 )
2450         {
2451                 dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
2452                         loopbackv4->ifa_name ? loopbackv4->ifa_name : "<null>", loopbackv4->ifa_extra.index, loopbackv4->ifa_addr );
2453                 
2454                 err = SetupInterface( inMDNS, loopbackv4, &ifd );
2455                 require_noerr( err, exit );
2456
2457                 inMDNS->p->registeredLoopback4 = mDNStrue;
2458                 
2459 #if( MDNS_WINDOWS_ENABLE_IPV4 )
2460
2461                 // If we're on a platform that doesn't have WSARecvMsg(), there's no way
2462                 // of determing the destination address of a packet that is sent to us.
2463                 // For multicast packets, that's easy to determine.  But for the unicast
2464                 // sockets, we'll fake it by taking the address of the first interface
2465                 // that is successfully setup.
2466
2467                 if ( !foundUnicastSock4DestAddr )
2468                 {
2469                         inMDNS->p->unicastSock4.addr = ifd->sock.addr;
2470                         foundUnicastSock4DestAddr = TRUE;
2471                 }
2472 #endif
2473
2474                 *next = ifd;
2475                 next  = &ifd->next;
2476                 ++inMDNS->p->interfaceCount;
2477         }
2478
2479         if ( !foundv6 && loopbackv6 )
2480         {
2481                 dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
2482                         loopbackv6->ifa_name ? loopbackv6->ifa_name : "<null>", loopbackv6->ifa_extra.index, loopbackv6->ifa_addr );
2483                 
2484                 err = SetupInterface( inMDNS, loopbackv6, &ifd );
2485                 require_noerr( err, exit );
2486                 
2487 #if( MDNS_WINDOWS_ENABLE_IPV6 )
2488
2489                 // If we're on a platform that doesn't have WSARecvMsg(), there's no way
2490                 // of determing the destination address of a packet that is sent to us.
2491                 // For multicast packets, that's easy to determine.  But for the unicast
2492                 // sockets, we'll fake it by taking the address of the first interface
2493                 // that is successfully setup.
2494
2495                 if ( !foundUnicastSock6DestAddr )
2496                 {
2497                         inMDNS->p->unicastSock6.addr = ifd->sock.addr;
2498                         foundUnicastSock6DestAddr = TRUE;
2499                 }
2500 #endif
2501
2502                 *next = ifd;
2503                 next  = &ifd->next;
2504                 ++inMDNS->p->interfaceCount;
2505         }
2506
2507         CheckFileShares( inMDNS );
2508
2509 exit:
2510         if( err )
2511         {
2512                 TearDownInterfaceList( inMDNS );
2513         }
2514         if( addrs )
2515         {
2516                 freeifaddrs( addrs );
2517         }
2518         dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list done (err=%d %m)\n", err, err );
2519         return( err );
2520 }
2521
2522 //===========================================================================================================================
2523 //      TearDownInterfaceList
2524 //===========================================================================================================================
2525
2526 mStatus TearDownInterfaceList( mDNS * const inMDNS )
2527 {
2528         mDNSInterfaceData **            p;
2529         mDNSInterfaceData *             ifd;
2530         
2531         dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list\n" );
2532         check( inMDNS );
2533         check( inMDNS->p );
2534         
2535         // Free any interfaces that were previously marked inactive and are no longer referenced by the mDNS cache.
2536         // Interfaces are marked inactive, but not deleted immediately if they were still referenced by the mDNS cache
2537         // so that remove events that occur after an interface goes away can still report the correct interface.
2538
2539         p = &inMDNS->p->inactiveInterfaceList;
2540         while( *p )
2541         {
2542                 ifd = *p;
2543                 if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) ifd ) > 0 )
2544                 {
2545                         p = &ifd->next;
2546                         continue;
2547                 }
2548                 
2549                 dlog( kDebugLevelInfo, DEBUG_NAME "freeing unreferenced, inactive interface %#p %#a\n", ifd, &ifd->interfaceInfo.ip );
2550                 *p = ifd->next;
2551
2552                 QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) ifd );
2553         }
2554
2555         // Tear down all the interfaces.
2556         
2557         while( inMDNS->p->interfaceList )
2558         {
2559                 ifd = inMDNS->p->interfaceList;
2560                 inMDNS->p->interfaceList = ifd->next;
2561                 
2562                 TearDownInterface( inMDNS, ifd );
2563         }
2564         inMDNS->p->interfaceCount = 0;
2565         
2566         dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list done\n" );
2567         return( mStatus_NoError );
2568 }
2569
2570 //===========================================================================================================================
2571 //      SetupInterface
2572 //===========================================================================================================================
2573
2574 mDNSlocal mStatus       SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD )
2575 {
2576         mDNSInterfaceData       *       ifd;
2577         mDNSInterfaceData       *       p;
2578         mStatus                                 err;
2579         
2580         ifd = NULL;
2581         dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface\n" );
2582         check( inMDNS );
2583         check( inMDNS->p );
2584         check( inIFA );
2585         check( inIFA->ifa_addr );
2586         check( outIFD );
2587         
2588         // Allocate memory for the interface and initialize it.
2589         
2590         ifd = (mDNSInterfaceData *) calloc( 1, sizeof( *ifd ) );
2591         require_action( ifd, exit, err = mStatus_NoMemoryErr );
2592         ifd->sock.fd    = kInvalidSocketRef;
2593         ifd->sock.ifd   = ifd;
2594         ifd->sock.next  = NULL;
2595         ifd->sock.m             = inMDNS;
2596         ifd->index              = inIFA->ifa_extra.index;
2597         ifd->scopeID    = inIFA->ifa_extra.index;
2598         check( strlen( inIFA->ifa_name ) < sizeof( ifd->name ) );
2599         strncpy( ifd->name, inIFA->ifa_name, sizeof( ifd->name ) - 1 );
2600         ifd->name[ sizeof( ifd->name ) - 1 ] = '\0';
2601         
2602         strncpy(ifd->interfaceInfo.ifname, inIFA->ifa_name, sizeof(ifd->interfaceInfo.ifname));
2603         ifd->interfaceInfo.ifname[sizeof(ifd->interfaceInfo.ifname)-1] = 0;
2604         
2605         // We always send and receive using IPv4, but to reduce traffic, we send and receive using IPv6 only on interfaces 
2606         // that have no routable IPv4 address. Having a routable IPv4 address assigned is a reasonable indicator of being 
2607         // on a large configured network, which means there's a good chance that most or all the other devices on that 
2608         // network should also have v4. By doing this we lose the ability to talk to true v6-only devices on that link, 
2609         // but we cut the packet rate in half. At this time, reducing the packet rate is more important than v6-only 
2610         // devices on a large configured network, so we are willing to make that sacrifice.
2611         
2612         ifd->interfaceInfo.McastTxRx   = ( ( inIFA->ifa_flags & IFF_MULTICAST ) && !( inIFA->ifa_flags & IFF_POINTTOPOINT ) ) ? mDNStrue : mDNSfalse;
2613         ifd->interfaceInfo.InterfaceID = NULL;
2614
2615         for( p = inMDNS->p->interfaceList; p; p = p->next )
2616         {
2617                 if ( strcmp( p->name, ifd->name ) == 0 )
2618                 {
2619                         if (!ifd->interfaceInfo.InterfaceID)
2620                         {
2621                                 ifd->interfaceInfo.InterfaceID  = (mDNSInterfaceID) p;
2622                         }
2623
2624                         if ( ( inIFA->ifa_addr->sa_family != AF_INET ) &&
2625                              ( p->interfaceInfo.ip.type == mDNSAddrType_IPv4 ) &&
2626                              ( p->interfaceInfo.ip.ip.v4.b[ 0 ] != 169 || p->interfaceInfo.ip.ip.v4.b[ 1 ] != 254 ) )
2627                         {
2628                                 ifd->interfaceInfo.McastTxRx = mDNSfalse;
2629                         }
2630
2631                         break;
2632                 }
2633         }
2634
2635         if ( !ifd->interfaceInfo.InterfaceID )
2636         {
2637                 ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ifd;
2638         }
2639
2640         // Set up a socket for this interface (if needed).
2641         
2642         if( ifd->interfaceInfo.McastTxRx )
2643         {
2644                 DWORD size;
2645                         
2646                 err = SetupSocket( inMDNS, inIFA->ifa_addr, MulticastDNSPort, &ifd->sock.fd );
2647                 require_noerr( err, exit );
2648                 ifd->sock.addr = ( inIFA->ifa_addr->sa_family == AF_INET6 ) ? AllDNSLinkGroup_v6 : AllDNSLinkGroup_v4;
2649                 ifd->sock.port = MulticastDNSPort;
2650                 
2651                 // Get a ptr to the WSARecvMsg function, if supported. Otherwise, we'll fallback to recvfrom.
2652
2653                 err = WSAIoctl( ifd->sock.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &ifd->sock.recvMsgPtr, sizeof( ifd->sock.recvMsgPtr ), &size, NULL, NULL );
2654
2655                 if ( err )
2656                 {
2657                         ifd->sock.recvMsgPtr = NULL;
2658                 }
2659         }
2660
2661         if ( inIFA->ifa_dhcpEnabled && ( inIFA->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
2662         {
2663                 inMDNS->p->nextDHCPLeaseExpires = inIFA->ifa_dhcpLeaseExpires;
2664         }
2665
2666         ifd->interfaceInfo.NetWake = inIFA->ifa_womp;
2667
2668         // Register this interface with mDNS.
2669         
2670         err = SockAddrToMDNSAddr( inIFA->ifa_addr, &ifd->interfaceInfo.ip, NULL );
2671         require_noerr( err, exit );
2672         
2673         err = SockAddrToMDNSAddr( inIFA->ifa_netmask, &ifd->interfaceInfo.mask, NULL );
2674         require_noerr( err, exit );
2675         
2676         ifd->interfaceInfo.Advertise = ( mDNSu8 ) inMDNS->AdvertiseLocalAddresses;
2677
2678         if ( ifd->sock.fd != kInvalidSocketRef )
2679         {
2680                 err = UDPBeginRecv( &ifd->sock );
2681                 require_noerr( err, exit );
2682         }
2683
2684         err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, mDNSfalse );
2685         require_noerr( err, exit );
2686         ifd->hostRegistered = mDNStrue;
2687         
2688         dlog( kDebugLevelInfo, DEBUG_NAME "Registered interface %##a with mDNS\n", inIFA->ifa_addr );
2689         
2690         // Success!
2691         
2692         *outIFD = ifd;
2693         ifd = NULL;
2694         
2695 exit:
2696
2697         if( ifd )
2698         {
2699                 TearDownInterface( inMDNS, ifd );
2700         }
2701         dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface done (err=%d %m)\n", err, err );
2702         return( err );
2703 }
2704
2705 //===========================================================================================================================
2706 //      TearDownInterface
2707 //===========================================================================================================================
2708
2709 mDNSlocal mStatus       TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD )
2710 {       
2711         check( inMDNS );
2712         check( inIFD );
2713         
2714         // Deregister this interface with mDNS.
2715         
2716         dlog( kDebugLevelInfo, DEBUG_NAME "Deregistering interface %#a with mDNS\n", &inIFD->interfaceInfo.ip );
2717         
2718         if( inIFD->hostRegistered )
2719         {
2720                 inIFD->hostRegistered = mDNSfalse;
2721                 mDNS_DeregisterInterface( inMDNS, &inIFD->interfaceInfo, mDNSfalse );
2722         }
2723         
2724         // Tear down the multicast socket.
2725         
2726         if ( inIFD->sock.fd != INVALID_SOCKET )
2727         {
2728                 closesocket( inIFD->sock.fd );
2729                 inIFD->sock.fd = INVALID_SOCKET;
2730         }
2731         
2732         // If the interface is still referenced by items in the mDNS cache then put it on the inactive list. This keeps 
2733         // the InterfaceID valid so remove events report the correct interface. If it is no longer referenced, free it.
2734
2735         if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) inIFD ) > 0 )
2736         {
2737                 inIFD->next = inMDNS->p->inactiveInterfaceList;
2738                 inMDNS->p->inactiveInterfaceList = inIFD;
2739                 dlog( kDebugLevelInfo, DEBUG_NAME "deferring free of interface %#p %#a\n", inIFD, &inIFD->interfaceInfo.ip );
2740         }
2741         else
2742         {
2743                 dlog( kDebugLevelInfo, DEBUG_NAME "freeing interface %#p %#a immediately\n", inIFD, &inIFD->interfaceInfo.ip );
2744                 QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) inIFD );
2745         }
2746
2747         return( mStatus_NoError );
2748 }
2749
2750 mDNSlocal void CALLBACK FreeInterface( mDNSInterfaceData *inIFD )
2751 {
2752         free( inIFD );
2753 }
2754
2755 //===========================================================================================================================
2756 //      SetupSocket
2757 //===========================================================================================================================
2758
2759 mDNSlocal mStatus       SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef  )
2760 {
2761         mStatus                 err;
2762         SocketRef               sock;
2763         int                             option;
2764         
2765         DEBUG_UNUSED( inMDNS );
2766         
2767         dlog( kDebugLevelTrace, DEBUG_NAME "setting up socket %##a\n", inAddr );
2768         check( inMDNS );
2769         check( outSocketRef );
2770         
2771         // Set up an IPv4 or IPv6 UDP socket.
2772         
2773         sock = socket( inAddr->sa_family, SOCK_DGRAM, IPPROTO_UDP );
2774         err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
2775         require_noerr( err, exit );
2776                 
2777         // Turn on reuse address option so multiple servers can listen for Multicast DNS packets,
2778         // if we're creating a multicast socket
2779         
2780         if ( port.NotAnInteger )
2781         {
2782                 option = 1;
2783                 err = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
2784                 check_translated_errno( err == 0, errno_compat(), kOptionErr );
2785         }
2786         
2787         if( inAddr->sa_family == AF_INET )
2788         {
2789                 mDNSv4Addr                              ipv4;
2790                 struct sockaddr_in              sa4;
2791                 struct ip_mreq                  mreqv4;
2792                 
2793                 // Bind the socket to the desired port
2794                 
2795                 ipv4.NotAnInteger       = ( (const struct sockaddr_in *) inAddr )->sin_addr.s_addr;
2796                 mDNSPlatformMemZero( &sa4, sizeof( sa4 ) );
2797                 sa4.sin_family          = AF_INET;
2798                 sa4.sin_port            = port.NotAnInteger;
2799                 sa4.sin_addr.s_addr     = ipv4.NotAnInteger;
2800                 
2801                 err = bind( sock, (struct sockaddr *) &sa4, sizeof( sa4 ) );
2802                 check_translated_errno( err == 0, errno_compat(), kUnknownErr );
2803                 
2804                 // Turn on option to receive destination addresses and receiving interface.
2805                 
2806                 option = 1;
2807                 err = setsockopt( sock, IPPROTO_IP, IP_PKTINFO, (char *) &option, sizeof( option ) );
2808                 check_translated_errno( err == 0, errno_compat(), kOptionErr );
2809                 
2810                 if (port.NotAnInteger)
2811                 {
2812                         // Join the all-DNS multicast group so we receive Multicast DNS packets
2813
2814                         mreqv4.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
2815                         mreqv4.imr_interface.s_addr = ipv4.NotAnInteger;
2816                         err = setsockopt( sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreqv4, sizeof( mreqv4 ) );
2817                         check_translated_errno( err == 0, errno_compat(), kOptionErr );
2818                 
2819                         // Specify the interface to send multicast packets on this socket.
2820                 
2821                         sa4.sin_addr.s_addr = ipv4.NotAnInteger;
2822                         err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_IF, (char *) &sa4.sin_addr, sizeof( sa4.sin_addr ) );
2823                         check_translated_errno( err == 0, errno_compat(), kOptionErr );
2824                 
2825                         // Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
2826                 
2827                         option = 1;
2828                         err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
2829                         check_translated_errno( err == 0, errno_compat(), kOptionErr );
2830                 }
2831
2832                 // Send unicast packets with TTL 255 (helps against spoofing).
2833                 
2834                 option = 255;
2835                 err = setsockopt( sock, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) );
2836                 check_translated_errno( err == 0, errno_compat(), kOptionErr );
2837
2838                 // Send multicast packets with TTL 255 (helps against spoofing).
2839                 
2840                 option = 255;
2841                 err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &option, sizeof( option ) );
2842                 check_translated_errno( err == 0, errno_compat(), kOptionErr );
2843
2844         }
2845         else if( inAddr->sa_family == AF_INET6 )
2846         {
2847                 struct sockaddr_in6 *           sa6p;
2848                 struct sockaddr_in6                     sa6;
2849                 struct ipv6_mreq                        mreqv6;
2850                 
2851                 sa6p = (struct sockaddr_in6 *) inAddr;
2852                 
2853                 // Bind the socket to the desired port
2854                 
2855                 mDNSPlatformMemZero( &sa6, sizeof( sa6 ) );
2856                 sa6.sin6_family         = AF_INET6;
2857                 sa6.sin6_port           = port.NotAnInteger;
2858                 sa6.sin6_flowinfo       = 0;
2859                 sa6.sin6_addr           = sa6p->sin6_addr;
2860                 sa6.sin6_scope_id       = sa6p->sin6_scope_id;
2861                 
2862                 err = bind( sock, (struct sockaddr *) &sa6, sizeof( sa6 ) );
2863                 check_translated_errno( err == 0, errno_compat(), kUnknownErr );
2864                 
2865                 // Turn on option to receive destination addresses and receiving interface.
2866                 
2867                 option = 1;
2868                 err = setsockopt( sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *) &option, sizeof( option ) );
2869                 check_translated_errno( err == 0, errno_compat(), kOptionErr );
2870                 
2871                 // We only want to receive IPv6 packets (not IPv4-mapped IPv6 addresses) because we have a separate socket 
2872                 // for IPv4, but the IPv6 stack in Windows currently doesn't support IPv4-mapped IPv6 addresses and doesn't
2873                 // support the IPV6_V6ONLY socket option so the following code would typically not be executed (or needed).
2874                 
2875                 #if( defined( IPV6_V6ONLY ) )
2876                         option = 1;
2877                         err = setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &option, sizeof( option ) );
2878                         check_translated_errno( err == 0, errno_compat(), kOptionErr );         
2879                 #endif
2880                 
2881                 if ( port.NotAnInteger )
2882                 {
2883                         // Join the all-DNS multicast group so we receive Multicast DNS packets.
2884                 
2885                         mreqv6.ipv6mr_multiaddr = *( (struct in6_addr *) &AllDNSLinkGroup_v6.ip.v6 );
2886                         mreqv6.ipv6mr_interface = sa6p->sin6_scope_id;
2887                         err = setsockopt( sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreqv6, sizeof( mreqv6 ) );
2888                         check_translated_errno( err == 0, errno_compat(), kOptionErr );
2889                 
2890                         // Specify the interface to send multicast packets on this socket.
2891                 
2892                         option = (int) sa6p->sin6_scope_id;
2893                         err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &option, sizeof( option ) );
2894                         check_translated_errno( err == 0, errno_compat(), kOptionErr );
2895                 
2896                         // Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
2897                         
2898                         option = 1;
2899                         err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
2900                         check_translated_errno( err == 0, errno_compat(), kOptionErr );
2901                 }
2902
2903                 // Send unicast packets with TTL 255 (helps against spoofing).
2904                 
2905                 option = 255;
2906                 err = setsockopt( sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *) &option, sizeof( option ) );
2907                 check_translated_errno( err == 0, errno_compat(), kOptionErr );
2908
2909                 // Send multicast packets with TTL 255 (helps against spoofing).
2910                         
2911                 option = 255;
2912                 err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &option, sizeof( option ) );
2913                 check_translated_errno( err == 0, errno_compat(), kOptionErr );
2914         }
2915         else
2916         {
2917                 dlog( kDebugLevelError, DEBUG_NAME "%s: unsupport socket family (%d)\n", __ROUTINE__, inAddr->sa_family );
2918                 err = kUnsupportedErr;
2919                 goto exit;
2920         }
2921         
2922         // Success!
2923         
2924         *outSocketRef = sock;
2925         sock = kInvalidSocketRef;
2926         err = mStatus_NoError;
2927         
2928 exit:
2929         if( IsValidSocket( sock ) )
2930         {
2931                 close_compat( sock );
2932         }
2933         return( err );
2934 }
2935
2936 //===========================================================================================================================
2937 //      SetupSocket
2938 //===========================================================================================================================
2939
2940 mDNSlocal mStatus       SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort )
2941 {
2942         mStatus         err;
2943         
2944         check( inSA );
2945         check( outIP );
2946         
2947         if( inSA->sa_family == AF_INET )
2948         {
2949                 struct sockaddr_in *            sa4;
2950                 
2951                 sa4                                             = (struct sockaddr_in *) inSA;
2952                 outIP->type                             = mDNSAddrType_IPv4;
2953                 outIP->ip.v4.NotAnInteger       = sa4->sin_addr.s_addr;
2954                 if( outPort )
2955                 {
2956                         outPort->NotAnInteger   = sa4->sin_port;
2957                 }
2958                 err = mStatus_NoError;
2959         }
2960         else if( inSA->sa_family == AF_INET6 )
2961         {
2962                 struct sockaddr_in6 *           sa6;
2963                 
2964                 sa6                     = (struct sockaddr_in6 *) inSA;
2965                 outIP->type     = mDNSAddrType_IPv6;
2966                 outIP->ip.v6    = *( (mDNSv6Addr *) &sa6->sin6_addr );
2967                 if( IN6_IS_ADDR_LINKLOCAL( &sa6->sin6_addr ) )
2968                 {
2969                         outIP->ip.v6.w[ 1 ] = 0;
2970                 }
2971                 if( outPort )
2972                 {
2973                         outPort->NotAnInteger = sa6->sin6_port;
2974                 }
2975                 err = mStatus_NoError;
2976         }
2977         else
2978         {
2979                 dlog( kDebugLevelError, DEBUG_NAME "%s: invalid sa_family %d", __ROUTINE__, inSA->sa_family );
2980                 err = mStatus_BadParamErr;
2981         }
2982         return( err );
2983 }
2984
2985
2986 #if 0
2987 #pragma mark -
2988 #endif
2989
2990 //===========================================================================================================================
2991 //      UDPBeginRecv
2992 //===========================================================================================================================
2993
2994 mDNSlocal OSStatus UDPBeginRecv( UDPSocket * sock )
2995 {
2996         DWORD           size;
2997         OSStatus        err;
2998
2999         require_action( socket != NULL, exit, err = kUnknownErr );
3000
3001         // Initialize the buffer structure
3002
3003         sock->wbuf.buf          = (char *) &sock->packet;
3004         sock->wbuf.len          = (u_long) sizeof( sock->packet );
3005         sock->srcAddrLen        = sizeof( sock->srcAddr );
3006
3007         // Initialize the overlapped structure
3008
3009         ZeroMemory( &sock->overlapped, sizeof( OVERLAPPED ) );
3010         sock->overlapped.hEvent = sock;
3011
3012         if ( sock->recvMsgPtr )
3013         {
3014                 sock->wmsg.name                         = ( LPSOCKADDR ) &sock->srcAddr;
3015                 sock->wmsg.namelen                      = sock->srcAddrLen;
3016                 sock->wmsg.lpBuffers            = &sock->wbuf;
3017                 sock->wmsg.dwBufferCount        = 1;
3018                 sock->wmsg.Control.buf          = ( CHAR* ) sock->controlBuffer;
3019                 sock->wmsg.Control.len          = sizeof( sock->controlBuffer );
3020                 sock->wmsg.dwFlags                      = 0;
3021
3022                 err = sock->recvMsgPtr( sock->fd, &sock->wmsg, &size, &sock->overlapped, ( LPWSAOVERLAPPED_COMPLETION_ROUTINE ) UDPEndRecv );
3023                 err = translate_errno( ( err == 0 ) || ( WSAGetLastError() == WSA_IO_PENDING ), (OSStatus) WSAGetLastError(), kUnknownErr );
3024                 require_noerr( err, exit );
3025         }
3026         else
3027         {
3028                 DWORD flags = 0;
3029
3030                 err = WSARecvFrom( sock->fd, &sock->wbuf, 1, NULL, &flags, ( LPSOCKADDR ) &sock->srcAddr, &sock->srcAddrLen, &sock->overlapped, ( LPWSAOVERLAPPED_COMPLETION_ROUTINE ) UDPEndRecv );
3031                 err = translate_errno( ( err == 0 ) || ( WSAGetLastError() == WSA_IO_PENDING ), ( OSStatus ) WSAGetLastError(), kUnknownErr );
3032                 require_noerr( err, exit );
3033         }
3034
3035 exit:
3036
3037         return err;
3038 }
3039
3040
3041 //===========================================================================================================================
3042 //      UDPEndRecv
3043 //===========================================================================================================================
3044
3045 mDNSlocal void CALLBACK UDPEndRecv( DWORD err, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags )
3046 {
3047         UDPSocket * sock = NULL;
3048
3049         ( void ) flags;
3050
3051         require_action_quiet( err != WSA_OPERATION_ABORTED, exit, err = ( DWORD ) kUnknownErr );
3052         require_noerr( err, exit );
3053         sock = ( overlapped != NULL ) ? overlapped->hEvent : NULL;
3054         require_action( sock != NULL, exit, err = ( DWORD ) kUnknownErr );
3055
3056         // If we've closed the socket, then we want to ignore
3057         // this read.  The packet might have been queued before
3058         // the socket was closed.
3059
3060         if ( sock->fd != INVALID_SOCKET )
3061         {
3062                 const mDNSInterfaceID   iid = sock->ifd ? sock->ifd->interfaceInfo.InterfaceID : NULL;
3063                 mDNSAddr                                srcAddr;
3064                 mDNSIPPort                              srcPort;
3065                 mDNSAddr                                dstAddr;
3066                 mDNSIPPort                              dstPort;
3067                 mDNSu8                          *       end;
3068         
3069                 // Translate the source of this packet into mDNS data types
3070
3071                 SockAddrToMDNSAddr( (struct sockaddr *) &sock->srcAddr, &srcAddr, &srcPort );
3072         
3073                 // Initialize the destination of this packet. Just in case
3074                 // we can't determine this info because we couldn't call
3075                 // WSARecvMsg (recvMsgPtr)
3076
3077                 dstAddr = sock->addr;
3078                 dstPort = sock->port;
3079
3080                 if ( sock->recvMsgPtr )
3081                 {
3082                         LPWSACMSGHDR header;
3083                 
3084                         // Parse the control information. Reject packets received on the wrong interface.
3085                 
3086                         for( header = WSA_CMSG_FIRSTHDR( &sock->wmsg ); header; header = WSA_CMSG_NXTHDR( &sock->wmsg, header ) )
3087                         {
3088                                 if( ( header->cmsg_level == IPPROTO_IP ) && ( header->cmsg_type == IP_PKTINFO ) )
3089                                 {
3090                                         IN_PKTINFO * ipv4PacketInfo;
3091                                 
3092                                         ipv4PacketInfo = (IN_PKTINFO *) WSA_CMSG_DATA( header );
3093
3094                                         if ( sock->ifd != NULL )
3095                                         {
3096                                                 require_action( ipv4PacketInfo->ipi_ifindex == sock->ifd->index, exit, err = ( DWORD ) kMismatchErr );
3097                                         }
3098
3099                                         dstAddr.type                            = mDNSAddrType_IPv4;
3100                                         dstAddr.ip.v4.NotAnInteger      = ipv4PacketInfo->ipi_addr.s_addr;
3101                                 }
3102                                 else if( ( header->cmsg_level == IPPROTO_IPV6 ) && ( header->cmsg_type == IPV6_PKTINFO ) )
3103                                 {
3104                                         IN6_PKTINFO * ipv6PacketInfo;
3105                                         
3106                                         ipv6PacketInfo = (IN6_PKTINFO *) WSA_CMSG_DATA( header );
3107         
3108                                         if ( sock->ifd != NULL )
3109                                         {
3110                                                 require_action( ipv6PacketInfo->ipi6_ifindex == ( sock->ifd->index - kIPv6IfIndexBase ), exit, err = ( DWORD ) kMismatchErr );
3111                                         }
3112
3113                                         dstAddr.type    = mDNSAddrType_IPv6;
3114                                         dstAddr.ip.v6   = *( (mDNSv6Addr *) &ipv6PacketInfo->ipi6_addr );
3115                                 }
3116                         }
3117                 }
3118
3119                 // Dispatch the packet to mDNS.
3120         
3121                 dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" );
3122                 dlog( kDebugLevelChatty, DEBUG_NAME "    size      = %d\n", bytesTransferred );
3123                 dlog( kDebugLevelChatty, DEBUG_NAME "    src       = %#a:%u\n", &srcAddr, ntohs( srcPort.NotAnInteger ) );
3124                 dlog( kDebugLevelChatty, DEBUG_NAME "    dst       = %#a:%u\n", &dstAddr, ntohs( dstPort.NotAnInteger ) );
3125         
3126                 if ( sock->ifd != NULL )
3127                 {
3128                         dlog( kDebugLevelChatty, DEBUG_NAME "    interface = %#a (index=0x%08X)\n", sock->ifd->interfaceInfo.ip, sock->ifd->index );
3129                 }
3130
3131                 dlog( kDebugLevelChatty, DEBUG_NAME "\n" );
3132         
3133                 end = ( (mDNSu8 *) &sock->packet ) + bytesTransferred;
3134                 mDNSCoreReceive( sock->m, &sock->packet, end, &srcAddr, srcPort, &dstAddr, dstPort, iid );
3135         }
3136
3137 exit:
3138
3139         // If the socket is still good, then start up another asynchronous read
3140
3141         if ( sock && ( sock->fd != INVALID_SOCKET ) )
3142         {
3143                 err = UDPBeginRecv( sock );
3144                 check_noerr( err );
3145         }
3146 }
3147
3148
3149 //===========================================================================================================================
3150 //      InterfaceListDidChange
3151 //===========================================================================================================================
3152 void InterfaceListDidChange( mDNS * const inMDNS )
3153 {
3154         mStatus err;
3155         
3156         dlog( kDebugLevelInfo, DEBUG_NAME "interface list changed\n" );
3157         check( inMDNS );
3158         
3159         // Tear down the existing interfaces and set up new ones using the new IP info.
3160         
3161         err = TearDownInterfaceList( inMDNS );
3162         check_noerr( err );
3163         
3164         err = SetupInterfaceList( inMDNS );
3165         check_noerr( err );
3166                 
3167         err = uDNS_SetupDNSConfig( inMDNS );
3168         check_noerr( err );
3169         
3170         // Inform clients of the change.
3171         
3172         mDNS_ConfigChanged(inMDNS);
3173         
3174         // Force mDNS to update.
3175         
3176         mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this
3177 }
3178
3179
3180 //===========================================================================================================================
3181 //      ComputerDescriptionDidChange
3182 //===========================================================================================================================
3183 void ComputerDescriptionDidChange( mDNS * const inMDNS )
3184 {       
3185         dlog( kDebugLevelInfo, DEBUG_NAME "computer description has changed\n" );
3186         check( inMDNS );
3187
3188         // redo the names
3189         SetupNiceName( inMDNS );
3190 }
3191
3192
3193 //===========================================================================================================================
3194 //      TCPIPConfigDidChange
3195 //===========================================================================================================================
3196 void TCPIPConfigDidChange( mDNS * const inMDNS )
3197 {
3198         mStatus         err;
3199         
3200         dlog( kDebugLevelInfo, DEBUG_NAME "TCP/IP config has changed\n" );
3201         check( inMDNS );
3202
3203         err = uDNS_SetupDNSConfig( inMDNS );
3204         check_noerr( err );
3205 }
3206
3207
3208 //===========================================================================================================================
3209 //      DynDNSConfigDidChange
3210 //===========================================================================================================================
3211 void DynDNSConfigDidChange( mDNS * const inMDNS )
3212 {
3213         mStatus         err;
3214         
3215         dlog( kDebugLevelInfo, DEBUG_NAME "DynDNS config has changed\n" );
3216         check( inMDNS );
3217
3218         SetDomainSecrets( inMDNS );
3219
3220         err = uDNS_SetupDNSConfig( inMDNS );
3221         check_noerr( err );
3222 }
3223
3224
3225 //===========================================================================================================================
3226 //      FileSharingDidChange
3227 //===========================================================================================================================
3228 void FileSharingDidChange( mDNS * const inMDNS )
3229 {       
3230         dlog( kDebugLevelInfo, DEBUG_NAME "File shares has changed\n" );
3231         check( inMDNS );
3232
3233         CheckFileShares( inMDNS );
3234 }
3235
3236
3237 //===========================================================================================================================
3238 //      FilewallDidChange
3239 //===========================================================================================================================
3240 void FirewallDidChange( mDNS * const inMDNS )
3241 {       
3242         dlog( kDebugLevelInfo, DEBUG_NAME "Firewall has changed\n" );
3243         check( inMDNS );
3244
3245         CheckFileShares( inMDNS );
3246 }
3247
3248
3249 #if 0
3250 #pragma mark -
3251 #pragma mark == Utilities ==
3252 #endif
3253
3254 //===========================================================================================================================
3255 //      getifaddrs
3256 //===========================================================================================================================
3257
3258 mDNSlocal int   getifaddrs( struct ifaddrs **outAddrs )
3259 {
3260         int             err;
3261         
3262 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
3263         
3264         // Try to the load the GetAdaptersAddresses function from the IP Helpers DLL. This API is only available on Windows
3265         // XP or later. Looking up the symbol at runtime allows the code to still work on older systems without that API.
3266         
3267         if( !gIPHelperLibraryInstance )
3268         {
3269                 gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
3270                 if( gIPHelperLibraryInstance )
3271                 {
3272                         gGetAdaptersAddressesFunctionPtr = 
3273                                 (GetAdaptersAddressesFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetAdaptersAddresses" );
3274                         if( !gGetAdaptersAddressesFunctionPtr )
3275                         {
3276                                 BOOL            ok;
3277                                 
3278                                 ok = FreeLibrary( gIPHelperLibraryInstance );
3279                                 check_translated_errno( ok, GetLastError(), kUnknownErr );
3280                                 gIPHelperLibraryInstance = NULL;
3281                         }
3282                 }
3283         }
3284         
3285         // Use the new IPv6-capable routine if supported. Otherwise, fall back to the old and compatible IPv4-only code.
3286         // <rdar://problem/4278934>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 fails
3287         // <rdar://problem/6145913>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 returns no addrs
3288
3289         if( !gGetAdaptersAddressesFunctionPtr || ( ( ( err = getifaddrs_ipv6( outAddrs ) ) != mStatus_NoError ) || ( ( outAddrs != NULL ) && ( *outAddrs == NULL ) ) ) )
3290         {
3291                 err = getifaddrs_ipv4( outAddrs );
3292                 require_noerr( err, exit );
3293         }
3294         
3295 #else
3296
3297         err = getifaddrs_ipv4( outAddrs );
3298         require_noerr( err, exit );
3299
3300 #endif
3301
3302 exit:
3303         return( err );
3304 }
3305
3306 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
3307 //===========================================================================================================================
3308 //      getifaddrs_ipv6
3309 //===========================================================================================================================
3310
3311 mDNSlocal int   getifaddrs_ipv6( struct ifaddrs **outAddrs )
3312 {
3313         DWORD                                           err;
3314         int                                                     i;
3315         DWORD                                           flags;
3316         struct ifaddrs *                        head;
3317         struct ifaddrs **                       next;
3318         IP_ADAPTER_ADDRESSES *          iaaList;
3319         ULONG                                           iaaListSize;
3320         IP_ADAPTER_ADDRESSES *          iaa;
3321         size_t                                          size;
3322         struct ifaddrs *                        ifa;
3323         
3324         check( gGetAdaptersAddressesFunctionPtr );
3325         
3326         head    = NULL;
3327         next    = &head;
3328         iaaList = NULL;
3329         
3330         // Get the list of interfaces. The first call gets the size and the second call gets the actual data.
3331         // This loops to handle the case where the interface changes in the window after getting the size, but before the
3332         // second call completes. A limit of 100 retries is enforced to prevent infinite loops if something else is wrong.
3333         
3334         flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
3335         i = 0;
3336         for( ;; )
3337         {
3338                 iaaListSize = 0;
3339                 err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, NULL, &iaaListSize );
3340                 check( err == ERROR_BUFFER_OVERFLOW );
3341                 check( iaaListSize >= sizeof( IP_ADAPTER_ADDRESSES ) );
3342                 
3343                 iaaList = (IP_ADAPTER_ADDRESSES *) malloc( iaaListSize );
3344                 require_action( iaaList, exit, err = ERROR_NOT_ENOUGH_MEMORY );
3345                 
3346                 err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, iaaList, &iaaListSize );
3347                 if( err == ERROR_SUCCESS ) break;
3348                 
3349                 free( iaaList );
3350                 iaaList = NULL;
3351                 ++i;
3352                 require( i < 100, exit );
3353                 dlog( kDebugLevelWarning, "%s: retrying GetAdaptersAddresses after %d failure(s) (%d %m)\n", __ROUTINE__, i, err, err );
3354         }
3355         
3356         for( iaa = iaaList; iaa; iaa = iaa->Next )
3357         {
3358                 int                                                             addrIndex;
3359                 IP_ADAPTER_UNICAST_ADDRESS      *       addr;
3360                 DWORD                                                   ipv6IfIndex;
3361                 IP_ADAPTER_PREFIX                       *       firstPrefix;
3362
3363                 if( iaa->IfIndex > 0xFFFFFF )
3364                 {
3365                         dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv4 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->IfIndex );
3366                 }
3367                 if( iaa->Ipv6IfIndex > 0xFF )
3368                 {
3369                         dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv6 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->Ipv6IfIndex );
3370                 }
3371
3372                 // For IPv4 interfaces, there seems to be a bug in iphlpapi.dll that causes the 
3373                 // following code to crash when iterating through the prefix list.  This seems
3374                 // to occur when iaa->Ipv6IfIndex != 0 when IPv6 is not installed on the host.
3375                 // This shouldn't happen according to Microsoft docs which states:
3376                 //
3377                 //     "Ipv6IfIndex contains 0 if IPv6 is not available on the interface."
3378                 //
3379                 // So the data structure seems to be corrupted when we return from
3380                 // GetAdaptersAddresses(). The bug seems to occur when iaa->Length <
3381                 // sizeof(IP_ADAPTER_ADDRESSES), so when that happens, we'll manually
3382                 // modify iaa to have the correct values.
3383
3384                 if ( iaa->Length >= sizeof( IP_ADAPTER_ADDRESSES ) )
3385                 {
3386                         ipv6IfIndex = iaa->Ipv6IfIndex;
3387                         firstPrefix = iaa->FirstPrefix;
3388                 }
3389                 else
3390                 {
3391                         ipv6IfIndex     = 0;
3392                         firstPrefix = NULL;
3393                 }
3394
3395                 // Skip pseudo and tunnel interfaces.
3396                 
3397 &nb