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