Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4710 lines
133 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: SPAddress.cpp
  6. * Content: Winsock address base class
  7. *
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 01/20/1999 jtk Created
  13. * 05/12/1999 jtk Derived from modem endpoint class
  14. ***************************************************************************/
  15. #include "dnwsocki.h"
  16. //**********************************************************************
  17. // Constant definitions
  18. //**********************************************************************
  19. //
  20. // maximum allowed hostname string size, in bytes, including NULL termination
  21. //
  22. #define MAX_HOSTNAME_SIZE 512
  23. //
  24. // broadcast address as a string
  25. //
  26. const WCHAR g_IPBroadcastAddress[] = L"255.255.255.255";
  27. const DWORD g_dwIPBroadcastAddressSize = sizeof( g_IPBroadcastAddress );
  28. //
  29. // string for IP helper API
  30. //
  31. static const TCHAR c_tszIPHelperDLLName[] = TEXT("IPHLPAPI.DLL");
  32. static const char c_szAdapterNameTemplate[] = "%s - %s";
  33. #ifndef DPNBUILD_NOIPX
  34. //
  35. // length of IPX host names 'xxxxxxxx,xxxxxxxxxxxx' including NULL
  36. //
  37. #define IPX_ADDRESS_STRING_LENGTH 22
  38. //
  39. // default broadcast and listen addresses
  40. //
  41. static const WCHAR g_IPXBroadcastAddress[] = L"00000000,FFFFFFFFFFFF";
  42. static const WCHAR g_IPXListenAddress[] = L"00000000,000000000000";
  43. //
  44. // string used for single IPX adapter
  45. //
  46. static const WCHAR g_IPXAdapterString[] = L"Local IPX Adapter";
  47. #endif // ! DPNBUILD_NOIPX
  48. #ifndef DPNBUILD_NOIPV6
  49. static const WCHAR c_wszIPv6AdapterNameTemplate[] = L"%s - IPv6 - %s";
  50. static const WCHAR c_wszIPv4AdapterNameTemplate[] = L"%s - IPv4 - %s";
  51. static const WCHAR c_wszIPv6AdapterNameNoDescTemplate[] = L"IPv6 - %s";
  52. static const WCHAR c_wszIPv4AdapterNameNoDescTemplate[] = L"IPv4 - %s";
  53. //
  54. // string used for IPv4 loopback adapter
  55. //
  56. static const WCHAR c_wszIPv4LoopbackAdapterString[] = L"IPv4 Loopback Adapter";
  57. #endif // ! DPNBUILD_NOIPV6
  58. #ifndef DPNBUILD_NOMULTICAST
  59. //
  60. // 238.1.1.1 in network byte order
  61. //
  62. #define SAMPLE_MULTICAST_ADDRESS 0x010101EE
  63. #define INVALID_INTERFACE_INDEX -1
  64. static const WCHAR c_wszPrivateScopeString[] = L"Private Multicast Scope - TTL " MULTICAST_TTL_PRIVATE_AS_STRING;
  65. static const WCHAR c_wszLocalScopeString[] = L"Local Multicast Scope - TTL " MULTICAST_TTL_LOCAL_AS_STRING;
  66. static const WCHAR c_wszGlobalScopeString[] = L"Global Multicast Scope - TTL " MULTICAST_TTL_GLOBAL_AS_STRING;
  67. #endif // ! DPNBUILD_NOMULTICAST
  68. //**********************************************************************
  69. // Macro definitions
  70. //**********************************************************************
  71. //**********************************************************************
  72. // Structure definitions
  73. //**********************************************************************
  74. #ifndef DPNBUILD_NOIPV6
  75. typedef struct _SORTADAPTERADDRESS
  76. {
  77. SOCKADDR * psockaddr;
  78. WCHAR * pwszDescription;
  79. } SORTADAPTERADDRESS;
  80. #endif // ! DPNBUILD_NOIPV6
  81. //**********************************************************************
  82. // Variable definitions
  83. //**********************************************************************
  84. //**********************************************************************
  85. // Function prototypes
  86. //**********************************************************************
  87. #ifndef DPNBUILD_ONLYONEADAPTER
  88. #ifndef DPNBUILD_NOWINSOCK2
  89. typedef DWORD (WINAPI *PFNGETADAPTERSINFO)(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen);
  90. #ifndef DPNBUILD_NOMULTICAST
  91. typedef DWORD (WINAPI *PFNGETBESTINTERFACE)(IPAddr dwDestAddr, PDWORD pdwBestIfIndex);
  92. #endif // ! DPNBUILD_NOMULTICAST
  93. #ifndef DPNBUILD_NOIPV6
  94. typedef DWORD (WINAPI *PFNGETADAPTERSADDRESSES)(ULONG ulFamily, DWORD dwFlags, PVOID pvReserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pulOutBufLen);
  95. #endif // ! DPNBUILD_NOIPV6
  96. #endif // ! DPNBUILD_NOWINSOCK2
  97. #endif // ! DPNBUILD_ONLYONEADAPTER
  98. //**********************************************************************
  99. // Function definitions
  100. //**********************************************************************
  101. //**********************************************************************
  102. // ------------------------------
  103. // CSocketAddress::InitializeWithBroadcastAddress - initialize with the IP broadcast address
  104. //
  105. // Entry: Nothing
  106. //
  107. // Exit: Nothing
  108. // ------------------------------
  109. #undef DPF_MODNAME
  110. #define DPF_MODNAME "CSocketAddress::InitializeWithBroadcastAddress"
  111. void CSocketAddress::InitializeWithBroadcastAddress( void )
  112. {
  113. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  114. switch (GetFamily())
  115. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  116. {
  117. #ifndef DPNBUILD_NOIPX
  118. case AF_IPX:
  119. {
  120. DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_netnum ) == sizeof( DWORD ) );
  121. *reinterpret_cast<DWORD*>( m_SocketAddress.IPXSocketAddress.sa_netnum ) = 0x00000000;
  122. DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 6 );
  123. DBG_CASSERT( sizeof( DWORD ) == 4 );
  124. *reinterpret_cast<DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum ) = 0xFFFFFFFF;
  125. *reinterpret_cast<DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum[ 2 ] ) = 0xFFFFFFFF;
  126. break;
  127. }
  128. #endif // ! DPNBUILD_NOIPX
  129. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  130. case AF_INET:
  131. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  132. {
  133. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = INADDR_BROADCAST;
  134. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  135. break;
  136. }
  137. default:
  138. {
  139. //
  140. // We should never try to initialize an IPv6 address with the broadcast
  141. // address. We use IPv4 broadcast addresses, and then convert to the
  142. // IPv6 enum multicast address on the fly.
  143. //
  144. DNASSERT(FALSE);
  145. break;
  146. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  147. }
  148. }
  149. }
  150. //**********************************************************************
  151. //**********************************************************************
  152. // ------------------------------
  153. // CSocketAddress::SetAddressFromSOCKADDR - set address from a socket address
  154. //
  155. // Entry: Reference to address
  156. // Size of address
  157. //
  158. // Exit: Nothing
  159. // ------------------------------
  160. #undef DPF_MODNAME
  161. #define DPF_MODNAME "CSocketAddress::SetAddressFromSOCKADDR"
  162. void CSocketAddress::SetAddressFromSOCKADDR( const SOCKADDR *pAddress, const INT_PTR iAddressSize )
  163. {
  164. DNASSERT( iAddressSize == GetAddressSize() );
  165. memcpy( &m_SocketAddress.SocketAddress, pAddress, iAddressSize );
  166. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  167. switch (GetFamily())
  168. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  169. {
  170. #ifndef DPNBUILD_NOIPV6
  171. case AF_INET6:
  172. {
  173. //
  174. // We don't validate anything in the address.
  175. //
  176. break;
  177. }
  178. #endif // ! DPNBUILD_NOIPV6
  179. #ifndef DPNBUILD_NOIPX
  180. case AF_IPX:
  181. {
  182. //
  183. // IPX addresses are only 14 of the 16 bytes in the socket address structure,
  184. // make sure the extra bytes are zero!
  185. //
  186. DNASSERT( m_SocketAddress.SocketAddress.sa_data[ 12 ] == 0 );
  187. DNASSERT( m_SocketAddress.SocketAddress.sa_data[ 13 ] == 0 );
  188. break;
  189. }
  190. #endif // ! DPNBUILD_NOIPX
  191. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  192. default:
  193. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  194. {
  195. //
  196. // Since Winsock won't guarantee that the sin_zero part of an IP address is
  197. // really zero, we need to do it ourself. If we don't, it'll make a mess out
  198. // of the Guid<-->Address code.
  199. //
  200. DBG_CASSERT( sizeof( &m_SocketAddress.IPSocketAddress.sin_zero[ 0 ] ) == sizeof( DWORD* ) );
  201. DBG_CASSERT( sizeof( &m_SocketAddress.IPSocketAddress.sin_zero[ sizeof( DWORD ) ] ) == sizeof( DWORD* ) );
  202. *reinterpret_cast<DWORD*>( &m_SocketAddress.IPSocketAddress.sin_zero[ 0 ] ) = 0;
  203. *reinterpret_cast<DWORD*>( &m_SocketAddress.IPSocketAddress.sin_zero[ sizeof( DWORD ) ] ) = 0;
  204. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  205. break;
  206. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  207. }
  208. }
  209. }
  210. //**********************************************************************
  211. //**********************************************************************
  212. // ------------------------------
  213. // CSocketAddress::SocketAddressFromDP8Address - convert a DP8Address into a socket address
  214. // NOTE: The address object may be modified
  215. //
  216. // Entry: Pointer to DP8Address
  217. // Secure transport key ID, or NULL if none.
  218. // Whether name resoultion (potentially blocking) is allowed.
  219. // Address type
  220. //
  221. // Exit: Error code
  222. // ------------------------------
  223. #undef DPF_MODNAME
  224. #define DPF_MODNAME "CSocketAddress::SocketAddressFromDP8Address"
  225. HRESULT CSocketAddress::SocketAddressFromDP8Address( IDirectPlay8Address *const pDP8Address,
  226. #ifdef DPNBUILD_XNETSECURITY
  227. ULONGLONG * const pullKeyID,
  228. #endif // DPNBUILD_XNETSECURITY
  229. #ifndef DPNBUILD_ONLYONETHREAD
  230. const BOOL fAllowNameResolution,
  231. #endif // ! DPNBUILD_ONLYONETHREAD
  232. const SP_ADDRESS_TYPE AddressType )
  233. {
  234. HRESULT hr;
  235. HRESULT hTempResult;
  236. BYTE abBuffer[MAX_HOSTNAME_SIZE];
  237. DWORD dwPort;
  238. DWORD dwTempSize;
  239. DWORD dwDataType;
  240. #ifndef DPNBUILD_ONLYONEADAPTER
  241. GUID AdapterGuid;
  242. #endif // ! DPNBUILD_ONLYONEADAPTER
  243. DPFX(DPFPREP, 8, "(0x%p) Parameters: (0x%p, %u)", this, pDP8Address, AddressType);
  244. //
  245. // initialize
  246. //
  247. hr = DPN_OK;
  248. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  249. switch (GetFamily())
  250. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  251. {
  252. #ifndef DPNBUILD_NOIPX
  253. case AF_IPX:
  254. {
  255. DNASSERT( pDP8Address != NULL );
  256. #ifdef DPNBUILD_XNETSECURITY
  257. DNASSERT( pullKeyID == NULL );
  258. #endif // DPNBUILD_XNETSECURITY
  259. //
  260. // the address type will determine how the address is handled
  261. //
  262. switch ( AddressType )
  263. {
  264. //
  265. // local device address, ask for the device guid and port to build a socket
  266. // address
  267. //
  268. case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
  269. case SP_ADDRESS_TYPE_DEVICE:
  270. {
  271. union
  272. {
  273. SOCKADDR SocketAddress;
  274. SOCKADDR_IPX IPXSocketAddress;
  275. #ifndef DPNBUILD_NOIPV6
  276. SOCKADDR_STORAGE SocketAddressStorage;
  277. #endif // ! DPNBUILD_NOIPV6
  278. } NetAddress;
  279. //
  280. // Ask for the adapter guid. If none is found, fail.
  281. //
  282. dwTempSize = sizeof( AdapterGuid );
  283. hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_DEVICE, &AdapterGuid, &dwTempSize, &dwDataType );
  284. switch ( hTempResult )
  285. {
  286. //
  287. // ok
  288. //
  289. case DPN_OK:
  290. {
  291. DNASSERT( dwDataType == DPNA_DATATYPE_GUID );
  292. break;
  293. }
  294. //
  295. // remap missing component to 'addressing' error
  296. //
  297. case DPNERR_DOESNOTEXIST:
  298. {
  299. hr = DPNERR_ADDRESSING;
  300. goto Failure;
  301. break;
  302. }
  303. default:
  304. {
  305. hr = hTempResult;
  306. goto Failure;
  307. break;
  308. }
  309. }
  310. DNASSERT( sizeof( AdapterGuid ) == dwTempSize );
  311. //
  312. // Ask for the port. If none is found, choose a default.
  313. //
  314. dwTempSize = sizeof( dwPort );
  315. hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_PORT, &dwPort, &dwTempSize, &dwDataType );
  316. switch ( hTempResult )
  317. {
  318. //
  319. // port present, nothing to do
  320. //
  321. case DPN_OK:
  322. {
  323. DNASSERT( dwDataType == DPNA_DATATYPE_DWORD );
  324. break;
  325. }
  326. //
  327. // port not present, fill in the appropriate default
  328. //
  329. case DPNERR_DOESNOTEXIST:
  330. {
  331. DNASSERT( hr == DPN_OK );
  332. switch ( AddressType )
  333. {
  334. case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
  335. {
  336. dwPort = ANY_PORT;
  337. break;
  338. }
  339. default:
  340. {
  341. DNASSERT( FALSE );
  342. break;
  343. }
  344. }
  345. break;
  346. }
  347. //
  348. // other error, fail
  349. //
  350. default:
  351. {
  352. hr = hTempResult;
  353. goto Failure;
  354. break;
  355. }
  356. }
  357. DNASSERT( sizeof( dwPort ) == dwTempSize );
  358. //
  359. // convert the GUID to an address in temp space because the GUID contains ALL address information (port, etc)
  360. // and we don't want to blindly wail on any information that might have already been set. Verify data
  361. // integrity and then only copy the raw address.
  362. //
  363. #ifndef DPNBUILD_NOIPV6
  364. AddressFromGuid( &AdapterGuid, &NetAddress.SocketAddressStorage );
  365. #else // ! DPNBUILD_NOIPV6
  366. AddressFromGuid( &AdapterGuid, &NetAddress.SocketAddress );
  367. #endif // ! DPNBUILD_NOIPV6
  368. if ( NetAddress.IPXSocketAddress.sa_family != m_SocketAddress.IPXSocketAddress.sa_family )
  369. {
  370. DNASSERT( FALSE );
  371. hr = DPNERR_ADDRESSING;
  372. DPFX(DPFPREP, 0, "Invalid device guid!" );
  373. goto Failure;
  374. }
  375. DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress ) == sizeof( NetAddress.IPXSocketAddress ) );
  376. memcpy( &m_SocketAddress.IPXSocketAddress, &NetAddress.IPXSocketAddress, sizeof( m_SocketAddress.IPXSocketAddress ) );
  377. m_SocketAddress.IPXSocketAddress.sa_socket = HTONS( static_cast<WORD>( dwPort ) );
  378. break;
  379. }
  380. //
  381. // hostname
  382. //
  383. case SP_ADDRESS_TYPE_HOST:
  384. {
  385. //
  386. // Ask for the port. If none is found, choose a default.
  387. //
  388. dwTempSize = sizeof( dwPort );
  389. hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_PORT, &dwPort, &dwTempSize, &dwDataType );
  390. switch ( hTempResult )
  391. {
  392. //
  393. // port present, nothing to do
  394. //
  395. case DPN_OK:
  396. {
  397. DNASSERT( dwDataType == DPNA_DATATYPE_DWORD );
  398. m_SocketAddress.IPXSocketAddress.sa_socket = HTONS( static_cast<WORD>( dwPort ) );
  399. break;
  400. }
  401. //
  402. // port not present, fill in the appropriate default
  403. //
  404. case DPNERR_DOESNOTEXIST:
  405. {
  406. #ifdef DPNBUILD_SINGLEPROCESS
  407. const DWORD dwTempPort = BASE_DPLAY8_PORT;
  408. #else // ! DPNBUILD_SINGLEPROCESS
  409. const DWORD dwTempPort = DPNA_DPNSVR_PORT;
  410. #endif // ! DPNBUILD_SINGLEPROCESS
  411. m_SocketAddress.IPXSocketAddress.sa_socket = HTONS( static_cast<const WORD>( dwTempPort ) );
  412. hTempResult = IDirectPlay8Address_AddComponent( pDP8Address,
  413. DPNA_KEY_PORT,
  414. &dwTempPort,
  415. sizeof( dwTempPort ),
  416. DPNA_DATATYPE_DWORD
  417. );
  418. if ( hTempResult != DPN_OK )
  419. {
  420. hr = hTempResult;
  421. goto Failure;
  422. }
  423. break;
  424. }
  425. //
  426. // remap everything else to an addressing failure
  427. //
  428. default:
  429. {
  430. hr = DPNERR_ADDRESSING;
  431. goto Failure;
  432. }
  433. }
  434. //
  435. // attempt to determine host name
  436. //
  437. dwTempSize = sizeof(abBuffer);
  438. hr = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_HOSTNAME, abBuffer, &dwTempSize, &dwDataType );
  439. switch ( hr )
  440. {
  441. //
  442. // keep the following codes and fail
  443. //
  444. case DPNERR_OUTOFMEMORY:
  445. case DPNERR_INCOMPLETEADDRESS:
  446. {
  447. goto Failure;
  448. break;
  449. }
  450. //
  451. // no problem
  452. //
  453. case DPN_OK:
  454. {
  455. switch (dwDataType)
  456. {
  457. case DPNA_DATATYPE_STRING:
  458. {
  459. BYTE abBuffer2[MAX_HOSTNAME_SIZE];
  460. //
  461. // Unicode string, convert it to ANSI.
  462. //
  463. dwTempSize /= sizeof(WCHAR);
  464. hr = STR_jkWideToAnsi( (char*) abBuffer2, (WCHAR*) abBuffer, dwTempSize );
  465. if ( hr != DPN_OK )
  466. {
  467. DPFX(DPFPREP, 0, "Failed to convert hostname to ANSI!" );
  468. DisplayDNError( 0, hr );
  469. goto Failure;
  470. }
  471. strncpy((char*) abBuffer, (char*) abBuffer2, dwTempSize);
  472. //
  473. // Fall through...
  474. //
  475. }
  476. case DPNA_DATATYPE_STRING_ANSI:
  477. {
  478. long val;
  479. char temp[3];
  480. char *a, *b;
  481. UINT_PTR uIndex;
  482. //
  483. // convert the text host name into the SOCKADDR structure
  484. //
  485. if ( dwTempSize != IPX_ADDRESS_STRING_LENGTH )
  486. {
  487. DPFX(DPFPREP, 0, "Invalid IPX net/node. Must be %d bytes of ASCII hex (net,node:socket)", ( IPX_ADDRESS_STRING_LENGTH - 1 ) );
  488. DPFX(DPFPREP, 0, "IPXAddressFromDP8Address: Failed to parse IPX host name!" );
  489. goto Failure;
  490. }
  491. // we convert the string for the hostname field into the components
  492. temp[ 2 ] = 0;
  493. a = (char*) abBuffer;
  494. // the net number is 4 bytes
  495. for ( uIndex = 0; uIndex < 4; uIndex++ )
  496. {
  497. strncpy( temp, a, 2 );
  498. val = strtol( temp, &b, 16 );
  499. m_SocketAddress.IPXSocketAddress.sa_netnum[ uIndex ] = (char) val;
  500. a += 2;
  501. }
  502. // followed by a dot
  503. a++;
  504. // the node is 6 bytes
  505. for ( uIndex = 0; uIndex < 6; uIndex++ )
  506. {
  507. strncpy( temp, a, 2 );
  508. val = strtol( temp, &b, 16 );
  509. m_SocketAddress.IPXSocketAddress.sa_nodenum[ uIndex ] = (char) val;
  510. a += 2;
  511. }
  512. break;
  513. }
  514. default:
  515. {
  516. DPFX(DPFPREP, 0, "Hostname component wasn't a string (%u)!", dwDataType );
  517. hr = DPNERR_ADDRESSING;
  518. goto Failure;
  519. break;
  520. }
  521. }
  522. break;
  523. }
  524. //
  525. // hostname does not exist, treat as an incomplete address
  526. //
  527. case DPNERR_DOESNOTEXIST:
  528. {
  529. hr = DPNERR_INCOMPLETEADDRESS;
  530. break;
  531. }
  532. //
  533. // remap other errors to an addressing error
  534. //
  535. default:
  536. {
  537. DNASSERT( FALSE );
  538. hr = DPNERR_ADDRESSING;
  539. goto Failure;
  540. break;
  541. }
  542. }
  543. break;
  544. }
  545. //
  546. // unknown address type
  547. //
  548. default:
  549. {
  550. DNASSERT( FALSE );
  551. break;
  552. }
  553. }
  554. break;
  555. }
  556. #endif // ! DPNBUILD_NOIPX
  557. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  558. #ifndef DPNBUILD_NOIPV6
  559. case AF_INET6:
  560. #endif // ! DPNBUILD_NOIPV6
  561. default:
  562. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  563. {
  564. DNASSERT( pDP8Address != NULL );
  565. switch ( AddressType )
  566. {
  567. //
  568. // local device address, ask for the device guid and port to build a socket
  569. // address
  570. //
  571. case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
  572. case SP_ADDRESS_TYPE_DEVICE:
  573. {
  574. union
  575. {
  576. SOCKADDR SocketAddress;
  577. SOCKADDR_IN INetAddress;
  578. #ifndef DPNBUILD_NOIPV6
  579. SOCKADDR_IN6 INet6Address;
  580. SOCKADDR_STORAGE SocketAddressStorage;
  581. #endif // ! DPNBUILD_NOIPV6
  582. } INetSocketAddress;
  583. #ifdef DPNBUILD_ONLYONEADAPTER
  584. XNADDR xnaddr;
  585. DWORD dwStatus;
  586. #else // ! DPNBUILD_ONLYONEADAPTER
  587. //
  588. // Ask for the adapter guid. If none is found, fail.
  589. //
  590. hTempResult = IDirectPlay8Address_GetDevice( pDP8Address, &AdapterGuid );
  591. switch ( hTempResult )
  592. {
  593. //
  594. // ok
  595. //
  596. case DPN_OK:
  597. {
  598. break;
  599. }
  600. //
  601. // remap missing component to 'addressing' error
  602. //
  603. case DPNERR_DOESNOTEXIST:
  604. {
  605. DPFX(DPFPREP, 0, "Device GUID does not exist!" );
  606. DNASSERTX(! "Device GUID does not exist", 2);
  607. hr = DPNERR_ADDRESSING;
  608. goto Failure;
  609. break;
  610. }
  611. default:
  612. {
  613. DPFX(DPFPREP, 0, "Couldn't get device (0x%lx)!", hr );
  614. hr = hTempResult;
  615. goto Failure;
  616. break;
  617. }
  618. }
  619. #endif // ! DPNBUILD_ONLYONEADAPTER
  620. //
  621. // Ask for the port. If none is found, choose a default.
  622. //
  623. dwTempSize = sizeof( dwPort );
  624. hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_PORT, &dwPort, &dwTempSize, &dwDataType );
  625. switch ( hTempResult )
  626. {
  627. //
  628. // port present, nothing to do
  629. //
  630. case DPN_OK:
  631. {
  632. DNASSERT( dwDataType == DPNA_DATATYPE_DWORD );
  633. break;
  634. }
  635. //
  636. // port not present, fill in the appropriate default
  637. //
  638. case DPNERR_DOESNOTEXIST:
  639. {
  640. DPFX(DPFPREP, 6, "Port component does not exist in address 0x%p.", pDP8Address );
  641. DNASSERT( hr == DPN_OK );
  642. switch ( AddressType )
  643. {
  644. case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
  645. {
  646. dwPort = ANY_PORT;
  647. break;
  648. }
  649. default:
  650. {
  651. DNASSERT( FALSE );
  652. break;
  653. }
  654. }
  655. break;
  656. }
  657. //
  658. // other error, fail
  659. //
  660. default:
  661. {
  662. DPFX(DPFPREP, 0, "Couldn't get port component (0x%lx)!", hr );
  663. hr = hTempResult;
  664. goto Failure;
  665. break;
  666. }
  667. }
  668. DNASSERT( sizeof( dwPort ) == dwTempSize );
  669. #ifdef DPNBUILD_ONLYONEADAPTER
  670. DNASSERT( GetFamily() == AF_INET );
  671. //
  672. // Zero out the entire structure. This implies we use INADDR_ANY.
  673. //
  674. memset(&INetSocketAddress, 0, sizeof(INetSocketAddress));
  675. dwStatus = XNetGetTitleXnAddr(&xnaddr);
  676. if ((dwStatus != XNET_GET_XNADDR_PENDING) &&
  677. (dwStatus != XNET_GET_XNADDR_NONE))
  678. {
  679. DPFX(DPFPREP, 5, "Using device %u.%u.%u.%u.",
  680. xnaddr.ina.S_un.S_un_b.s_b1,
  681. xnaddr.ina.S_un.S_un_b.s_b2,
  682. xnaddr.ina.S_un.S_un_b.s_b3,
  683. xnaddr.ina.S_un.S_un_b.s_b4);
  684. INetSocketAddress.INetAddress.sin_addr.S_un.S_addr = xnaddr.ina.S_un.S_addr;
  685. }
  686. else
  687. {
  688. DPFX(DPFPREP, 1, "Couldn't get XNet address, status = %u.",
  689. dwStatus);
  690. }
  691. #else // ! DPNBUILD_ONLYONEADAPTER
  692. //
  693. // convert the GUID to an address in temp space because the GUID is large enough to potentially hold
  694. // ALL address information (port, etc) and we don't want to blindly wail on any information that might
  695. // have already been set. Verify data integrity and then only copy the raw address.
  696. //
  697. #ifdef DPNBUILD_NOIPV6
  698. AddressFromGuid( &AdapterGuid, &INetSocketAddress.SocketAddress );
  699. #else // ! DPNBUILD_NOIPV6
  700. AddressFromGuid( &AdapterGuid, &INetSocketAddress.SocketAddressStorage );
  701. #endif // ! DPNBUILD_NOIPV6
  702. if ( ( INetSocketAddress.INetAddress.sin_family != AF_INET ) ||
  703. ( reinterpret_cast<DWORD*>( &INetSocketAddress.INetAddress.sin_zero[ 0 ] )[ 0 ] != 0 ) ||
  704. ( reinterpret_cast<DWORD*>( &INetSocketAddress.INetAddress.sin_zero[ 0 ] )[ 1 ] != 0 ) )
  705. {
  706. #ifdef DPNBUILD_NOIPV6
  707. hr = DPNERR_ADDRESSING;
  708. DPFX(DPFPREP, 0, "Invalid device guid!" );
  709. goto Exit;
  710. #else // ! DPNBUILD_NOIPV6
  711. //
  712. // Assume it is an IPv6 address.
  713. //
  714. SetFamilyProtocolAndSize(AF_INET6);
  715. AddressFromGuid( &AdapterGuid, &INetSocketAddress.SocketAddressStorage );
  716. m_SocketAddress.IPv6SocketAddress.sin6_addr = INetSocketAddress.INet6Address.sin6_addr;
  717. m_SocketAddress.IPv6SocketAddress.sin6_port = HTONS( static_cast<WORD>( dwPort ) );
  718. m_SocketAddress.IPv6SocketAddress.sin6_scope_id = INetSocketAddress.INet6Address.sin6_scope_id;
  719. #endif // ! DPNBUILD_NOIPV6
  720. }
  721. else
  722. #endif // ! DPNBUILD_ONLYONEADAPTER
  723. {
  724. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = INetSocketAddress.INetAddress.sin_addr.S_un.S_addr;
  725. m_SocketAddress.IPSocketAddress.sin_port = HTONS( static_cast<WORD>( dwPort ) );
  726. }
  727. break;
  728. }
  729. //
  730. // hostname
  731. //
  732. case SP_ADDRESS_TYPE_HOST:
  733. {
  734. //
  735. // Ask for the port. If none is found, choose a default.
  736. //
  737. dwTempSize = sizeof( dwPort );
  738. hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_PORT, &dwPort, &dwTempSize, &dwDataType );
  739. switch ( hTempResult )
  740. {
  741. //
  742. // port present, nothing to do
  743. //
  744. case DPN_OK:
  745. {
  746. DNASSERT( dwDataType == DPNA_DATATYPE_DWORD );
  747. break;
  748. }
  749. //
  750. // port not present, fill in the appropriate default
  751. //
  752. case DPNERR_DOESNOTEXIST:
  753. {
  754. #ifdef DPNBUILD_SINGLEPROCESS
  755. dwPort = BASE_DPLAY8_PORT;
  756. #else // ! DPNBUILD_SINGLEPROCESS
  757. dwPort = DPNA_DPNSVR_PORT;
  758. #endif // ! DPNBUILD_SINGLEPROCESS
  759. DPFX(DPFPREP, 6, "Port component does not exist in address 0x%p, defaulting to %u.",
  760. pDP8Address, dwPort );
  761. break;
  762. }
  763. //
  764. // remap everything else to an addressing failure
  765. //
  766. default:
  767. {
  768. DPFX(DPFPREP, 0, "Couldn't get port component (0x%lx)!", hr );
  769. hr = DPNERR_ADDRESSING;
  770. goto Failure;
  771. }
  772. }
  773. m_SocketAddress.IPSocketAddress.sin_port = HTONS( static_cast<WORD>( dwPort ) );
  774. //
  775. // get the host name
  776. //
  777. dwTempSize = sizeof(abBuffer);
  778. hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_HOSTNAME, abBuffer, &dwTempSize, &dwDataType );
  779. switch ( hTempResult )
  780. {
  781. //
  782. // host name present, convert from string to valid binary value
  783. //
  784. case DPN_OK:
  785. {
  786. switch (dwDataType)
  787. {
  788. case DPNA_DATATYPE_STRING:
  789. {
  790. BYTE abBuffer2[MAX_HOSTNAME_SIZE];
  791. #ifdef DPNBUILD_XNETSECURITY
  792. //
  793. // The buffer should be large enough to hold an XNet address.
  794. //
  795. DBG_CASSERT(MAX_HOSTNAME_SIZE > ((sizeof(XNADDR) * 2) + 1) * sizeof(WCHAR));
  796. #endif // DPNBUILD_XNETSECURITY
  797. //
  798. // Unicode string, convert it to ANSI.
  799. //
  800. dwTempSize /= sizeof(WCHAR);
  801. hr = STR_jkWideToAnsi( (char*) abBuffer2, (WCHAR*) abBuffer, dwTempSize );
  802. if ( hr != DPN_OK )
  803. {
  804. DPFX(DPFPREP, 0, "Failed to convert hostname to ANSI!" );
  805. DisplayDNError( 0, hr );
  806. goto Failure;
  807. }
  808. strncpy((char*) abBuffer, (char*) abBuffer2, dwTempSize);
  809. //
  810. // Fall through...
  811. //
  812. }
  813. case DPNA_DATATYPE_STRING_ANSI:
  814. {
  815. #ifdef DPNBUILD_XNETSECURITY
  816. //
  817. // This may be an XNet address. If we're allowed to check, and
  818. // the string is the right size, convert it.
  819. //
  820. if ((pullKeyID != NULL) &&
  821. (dwTempSize == ((sizeof(XNADDR) * 2) + 1))) // 2 characters for every byte + NULL termination
  822. {
  823. char * pcCurrentSrc;
  824. XNADDR xnaddr;
  825. BYTE * pbCurrentDest;
  826. int iError;
  827. //
  828. // Convert all the hex characters into digits.
  829. //
  830. pcCurrentSrc = (char*) abBuffer;
  831. memset(&xnaddr, 0, sizeof(xnaddr));
  832. for (pbCurrentDest = (BYTE*) &xnaddr; pbCurrentDest < (BYTE*) (&xnaddr + 1); pbCurrentDest++)
  833. {
  834. if (((*pcCurrentSrc) >= '0') && ((*pcCurrentSrc) <= '9'))
  835. {
  836. *pbCurrentDest = (*pcCurrentSrc) - '0';
  837. }
  838. else if (((*pcCurrentSrc) >= 'a') && ((*pcCurrentSrc) <= 'f'))
  839. {
  840. *pbCurrentDest = (*pcCurrentSrc) - 'a' + 10;
  841. }
  842. else if (((*pcCurrentSrc) >= 'A') && ((*pcCurrentSrc) <= 'F'))
  843. {
  844. *pbCurrentDest = (*pcCurrentSrc) - 'A' + 10;
  845. }
  846. else
  847. {
  848. //
  849. // If the current character is not a valid hex digit
  850. // this is not a valid secure transport address.
  851. //
  852. break;
  853. }
  854. pcCurrentSrc++;
  855. *pbCurrentDest <<= 4;
  856. if (((*pcCurrentSrc) >= '0') && ((*pcCurrentSrc) <= '9'))
  857. {
  858. *pbCurrentDest += (*pcCurrentSrc) - '0';
  859. }
  860. else if (((*pcCurrentSrc) >= 'a') && ((*pcCurrentSrc) <= 'f'))
  861. {
  862. *pbCurrentDest += (*pcCurrentSrc) - 'a' + 10;
  863. }
  864. else if (((*pcCurrentSrc) >= 'A') && ((*pcCurrentSrc) <= 'F'))
  865. {
  866. *pbCurrentDest += (*pcCurrentSrc) - 'A' + 10;
  867. }
  868. else
  869. {
  870. //
  871. // If the current character is not a valid hex digit
  872. // this is not a valid secure transport address.
  873. //
  874. break;
  875. }
  876. pcCurrentSrc++;
  877. }
  878. iError = XNetXnAddrToInAddr(&xnaddr,
  879. (XNKID*) pullKeyID,
  880. &m_SocketAddress.IPSocketAddress.sin_addr);
  881. if (iError == 0)
  882. {
  883. DNASSERT(hr == DPN_OK);
  884. goto Exit;
  885. }
  886. DPFX(DPFPREP, 1, "Couldn't convert XNet address \"%hs\" to InAddr (err = %i).",
  887. (char*) abBuffer, iError);
  888. DNASSERTX(! "Address exactly matching XNet address size and format failed to be converted!", 2);
  889. //
  890. // Continue on to trying to decode it as a
  891. // host name.
  892. //
  893. }
  894. else
  895. {
  896. //
  897. // XNet addresses should not be recognized,
  898. // or the string wasn't the right size.
  899. //
  900. }
  901. #endif // ! DPNBUILD_XNETSECURITY
  902. //
  903. // If we're here, it wasn't an XNet address.
  904. //
  905. #ifdef DPNBUILD_NOIPV6
  906. //
  907. // Try to convert as a raw IPv4 address first.
  908. //
  909. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = inet_addr((char*) abBuffer);
  910. if ((m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_NONE) &&
  911. (strcmp((char*) abBuffer, "255.255.255.255") != 0))
  912. {
  913. #ifdef _XBOX
  914. #pragma TODO(vanceo, "Use Xbox specific name lookup if available")
  915. DPFX(DPFPREP, 0, "Unable to resolve IP address \"%hs\"!",
  916. (char*) abBuffer);
  917. DNASSERTX(! "Unable to resolve IP address!", 2);
  918. hr = DPNERR_INVALIDHOSTADDRESS;
  919. goto Failure;
  920. #else // ! _XBOX
  921. //
  922. // Converting raw IP failed, and it wasn't supposed to
  923. // be the broadcast address. Convert as a host name if
  924. // we're allowed.
  925. //
  926. #ifndef DPNBUILD_ONLYONETHREAD
  927. if (! fAllowNameResolution)
  928. {
  929. DPFX(DPFPREP, 2, "Couldn't convert \"%hs\" to IP address, not allowed to resolve as hostname.",
  930. (char*) abBuffer);
  931. hr = DPNERR_TIMEDOUT;
  932. }
  933. else
  934. #endif // ! DPNBUILD_ONLYONETHREAD
  935. {
  936. PHOSTENT phostent;
  937. phostent = gethostbyname((char*) abBuffer);
  938. if (phostent == NULL)
  939. {
  940. DPFX(DPFPREP, 0, "Couldn't get IP address from \"%hs\"!",
  941. (char*) abBuffer);
  942. DNASSERTX(! "Unable to resolve IP address!", 2);
  943. hr = DPNERR_INVALIDHOSTADDRESS;
  944. goto Failure;
  945. }
  946. //
  947. // Select the first IP address returned.
  948. //
  949. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = ((IN_ADDR*) (phostent->h_addr_list[0]))->S_un.S_addr;
  950. }
  951. #endif // ! _XBOX
  952. }
  953. else
  954. {
  955. DNASSERT(hr == DPN_OK);
  956. }
  957. #else // ! DPNBUILD_NOIPV6
  958. char szPort[32];
  959. addrinfo addrinfoHints;
  960. addrinfo * paddrinfoResult;
  961. addrinfo * paddrinfoCurrent;
  962. int iError;
  963. //
  964. // Try to convert the host name or raw address.
  965. //
  966. memset(&addrinfoHints, 0, sizeof(addrinfoHints));
  967. if (! fAllowNameResolution)
  968. {
  969. addrinfoHints.ai_flags |= AI_NUMERICHOST;
  970. }
  971. addrinfoHints.ai_family = g_iIPAddressFamily; // IPv4, IPv6, or both
  972. addrinfoHints.ai_socktype = SOCK_DGRAM;
  973. addrinfoHints.ai_protocol = IPPROTO_UDP;
  974. //addrinfoHints.ai_addrlen = 0;
  975. //addrinfoHints.ai_canonname = NULL;
  976. //addrinfoHints.ai_addr = NULL;
  977. //addrinfoHints.ai_next = NULL;
  978. wsprintfA(szPort, "%u", dwPort);
  979. iError = getaddrinfo((char*) abBuffer, szPort, &addrinfoHints, &paddrinfoResult);
  980. if (iError == 0)
  981. {
  982. //
  983. // Pick the first valid address returned.
  984. //
  985. #pragma BUGBUG(vanceo, "Should we implement some mechanism to try the other results?")
  986. paddrinfoCurrent = paddrinfoResult;
  987. while (paddrinfoCurrent != NULL)
  988. {
  989. DNASSERT(paddrinfoCurrent->ai_addr != NULL);
  990. if ((paddrinfoCurrent->ai_addr->sa_family == AF_INET) ||
  991. (paddrinfoCurrent->ai_addr->sa_family == AF_INET6))
  992. {
  993. DNASSERT(paddrinfoCurrent->ai_addrlen <= sizeof(m_SocketAddress));
  994. memcpy(&m_SocketAddress, paddrinfoCurrent->ai_addr, paddrinfoCurrent->ai_addrlen);
  995. m_iSocketAddressSize = paddrinfoCurrent->ai_addrlen;
  996. DNASSERT(GetPort() != 0);
  997. freeaddrinfo(paddrinfoResult);
  998. paddrinfoResult = NULL;
  999. DNASSERT(hr == DPN_OK);
  1000. goto Exit;
  1001. }
  1002. DPFX(DPFPREP, 1, "Ignoring address family %u.",
  1003. paddrinfoCurrent->ai_addr->sa_family);
  1004. paddrinfoCurrent = paddrinfoCurrent->ai_next;
  1005. }
  1006. //
  1007. // We didn't find any valid addresses.
  1008. //
  1009. DPFX(DPFPREP, 0, "Got address(es) from \"%hs\", but none were IP!",
  1010. (char*) abBuffer);
  1011. freeaddrinfo(paddrinfoResult);
  1012. paddrinfoResult = NULL;
  1013. hr = DPNERR_INVALIDHOSTADDRESS;
  1014. goto Failure;
  1015. }
  1016. else
  1017. {
  1018. #ifndef DPNBUILD_ONLYONETHREAD
  1019. if (! fAllowNameResolution)
  1020. {
  1021. DPFX(DPFPREP, 2, "Couldn't convert \"%hs\" to IP address (err = %i), not allowed to resolve as hostname.",
  1022. (char*) abBuffer, iError);
  1023. hr = DPNERR_TIMEDOUT;
  1024. }
  1025. else
  1026. #endif // ! DPNBUILD_ONLYONETHREAD
  1027. {
  1028. DPFX(DPFPREP, 0, "Couldn't get IP address from \"%hs\" (err = %i)!",
  1029. (char*) abBuffer, iError);
  1030. DNASSERTX(! "Unable to resolve IP address!", 2);
  1031. hr = DPNERR_INVALIDHOSTADDRESS;
  1032. goto Failure;
  1033. }
  1034. }
  1035. #endif // ! DPNBUILD_NOIPV6
  1036. break;
  1037. }
  1038. default:
  1039. {
  1040. DPFX(DPFPREP, 0, "Hostname component wasn't a string (%u)!", dwDataType );
  1041. hr = DPNERR_ADDRESSING;
  1042. goto Failure;
  1043. break;
  1044. }
  1045. }
  1046. break;
  1047. }
  1048. //
  1049. // return DPNERR_INCOMPLETEADDRESS if the host name didn't exist
  1050. //
  1051. case DPNERR_DOESNOTEXIST:
  1052. {
  1053. DPFX(DPFPREP, 6, "Hostname component does not exist in address 0x%p.", pDP8Address );
  1054. hr = DPNERR_INCOMPLETEADDRESS;
  1055. goto Failure;
  1056. }
  1057. //
  1058. // remap everything else to an addressing failure
  1059. //
  1060. default:
  1061. {
  1062. DPFX(DPFPREP, 0, "Couldn't get hostname component (0x%lx)!", hr );
  1063. hr = DPNERR_ADDRESSING;
  1064. goto Failure;
  1065. }
  1066. }
  1067. break;
  1068. }
  1069. //
  1070. // unknown address type
  1071. //
  1072. default:
  1073. {
  1074. DNASSERT( FALSE );
  1075. break;
  1076. }
  1077. }
  1078. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  1079. break;
  1080. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  1081. }
  1082. }
  1083. Exit:
  1084. DPFX(DPFPREP, 8, "(0x%p) Returning [0x%lx]", this, hr);
  1085. return hr;
  1086. Failure:
  1087. goto Exit;
  1088. }
  1089. //**********************************************************************
  1090. //**********************************************************************
  1091. // ------------------------------
  1092. // CSocketAddress::DP8AddressFromSocketAddress - convert a socket address to a DP8Address
  1093. //
  1094. // Entry: Address type
  1095. //
  1096. // Exit: Pointer to DP8Address
  1097. // ------------------------------
  1098. #undef DPF_MODNAME
  1099. #define DPF_MODNAME "CSocketAddress::DP8AddressFromSocketAddress"
  1100. #ifdef DPNBUILD_XNETSECURITY
  1101. IDirectPlay8Address *CSocketAddress::DP8AddressFromSocketAddress( ULONGLONG * const pullKeyID,
  1102. const XNADDR * const pxnaddr,
  1103. const SP_ADDRESS_TYPE AddressType ) const
  1104. #else // ! DPNBUILD_XNETSECURITY
  1105. IDirectPlay8Address *CSocketAddress::DP8AddressFromSocketAddress( const SP_ADDRESS_TYPE AddressType ) const
  1106. #endif // ! DPNBUILD_XNETSECURITY
  1107. {
  1108. HRESULT hr;
  1109. IDirectPlay8Address * pDP8Address;
  1110. DWORD dwPort;
  1111. //
  1112. // initialize
  1113. //
  1114. hr = DPN_OK;
  1115. pDP8Address = NULL;
  1116. //
  1117. // create and initialize the address
  1118. //
  1119. #ifdef DPNBUILD_LIBINTERFACE
  1120. hr = DP8ACF_CreateInstance( IID_IDirectPlay8Address,
  1121. reinterpret_cast<void**>( &pDP8Address ) );
  1122. #else // ! DPNBUILD_LIBINTERFACE
  1123. hr = COM_CoCreateInstance( CLSID_DirectPlay8Address,
  1124. NULL,
  1125. CLSCTX_INPROC_SERVER,
  1126. IID_IDirectPlay8Address,
  1127. reinterpret_cast<void**>( &pDP8Address ),
  1128. FALSE );
  1129. #endif // ! DPNBUILD_LIBINTERFACE
  1130. if ( hr != S_OK )
  1131. {
  1132. DNASSERT( pDP8Address == NULL );
  1133. DPFX(DPFPREP, 0, "Failed to create DP8Address when converting socket address" );
  1134. return NULL;
  1135. }
  1136. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  1137. switch (GetFamily())
  1138. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  1139. {
  1140. #ifndef DPNBUILD_NOIPX
  1141. case AF_IPX:
  1142. {
  1143. #ifdef DPNBUILD_XNETSECURITY
  1144. DNASSERT(pullKeyID == NULL);
  1145. #endif // DPNBUILD_XNETSECURITY
  1146. //
  1147. // set SP
  1148. //
  1149. hr = IDirectPlay8Address_SetSP( pDP8Address, &CLSID_DP8SP_IPX );
  1150. if ( hr != DPN_OK )
  1151. {
  1152. DPFX(DPFPREP, 0, "Failed to set SP type!" );
  1153. DisplayDNError( 0, hr );
  1154. goto FailureIPX;
  1155. }
  1156. //
  1157. // add on the port because it's always set
  1158. //
  1159. dwPort = NTOHS( m_SocketAddress.IPXSocketAddress.sa_socket );
  1160. hr = IDirectPlay8Address_AddComponent( pDP8Address, DPNA_KEY_PORT, &dwPort, sizeof( dwPort ), DPNA_DATATYPE_DWORD );
  1161. if ( hr != DPN_OK )
  1162. {
  1163. DPFX(DPFPREP, 0, "Failed to set port!" );
  1164. DisplayDNError( 0, hr );
  1165. goto FailureIPX;
  1166. }
  1167. //
  1168. // add on the device or hostname depending on what type of address this is
  1169. //
  1170. switch ( AddressType )
  1171. {
  1172. case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
  1173. case SP_ADDRESS_TYPE_DEVICE:
  1174. {
  1175. GUID DeviceGuid;
  1176. GuidFromInternalAddressWithoutPort( &DeviceGuid );
  1177. hr = IDirectPlay8Address_AddComponent( pDP8Address,
  1178. DPNA_KEY_DEVICE,
  1179. &DeviceGuid,
  1180. sizeof( DeviceGuid ),
  1181. DPNA_DATATYPE_GUID );
  1182. if ( hr != DPN_OK )
  1183. {
  1184. DPFX(DPFPREP, 0, "Failed to add device!" );
  1185. DisplayDNError( 0, hr );
  1186. goto FailureIPX;
  1187. }
  1188. break;
  1189. }
  1190. //
  1191. // host address type
  1192. //
  1193. case SP_ADDRESS_TYPE_READ_HOST:
  1194. case SP_ADDRESS_TYPE_HOST:
  1195. {
  1196. char HostName[ 255 ];
  1197. WCHAR WCharHostName[ sizeof( HostName ) ];
  1198. DWORD dwHostNameLength;
  1199. DWORD dwWCharHostNameLength;
  1200. //
  1201. // remove constness of parameter for broken Socket API
  1202. //
  1203. dwHostNameLength = LENGTHOF( HostName );
  1204. if ( IPXAddressToStringNoSocket( const_cast<SOCKADDR*>( &m_SocketAddress.SocketAddress ),
  1205. sizeof( m_SocketAddress.IPXSocketAddress ),
  1206. HostName,
  1207. &dwHostNameLength
  1208. ) != 0 )
  1209. {
  1210. DPFERR("Error returned from IPXAddressToString");
  1211. hr = DPNERR_ADDRESSING;
  1212. goto ExitIPX;
  1213. }
  1214. //
  1215. // convert ANSI host name to WCHAR
  1216. //
  1217. dwWCharHostNameLength = LENGTHOF( WCharHostName );
  1218. hr = STR_AnsiToWide( HostName, -1, WCharHostName, &dwWCharHostNameLength );
  1219. if ( hr != DPN_OK )
  1220. {
  1221. DPFX(DPFPREP, 0, "Failed to convert hostname to WCHAR!" );
  1222. DisplayDNError( 0, hr );
  1223. goto FailureIPX;
  1224. }
  1225. hr = IDirectPlay8Address_AddComponent( pDP8Address,
  1226. DPNA_KEY_HOSTNAME,
  1227. WCharHostName,
  1228. dwWCharHostNameLength * sizeof( WCHAR ),
  1229. DPNA_DATATYPE_STRING );
  1230. if ( hr != DPN_OK )
  1231. {
  1232. DPFX(DPFPREP, 0, "Failed to add hostname!" );
  1233. DisplayDNError( 0, hr );
  1234. goto FailureIPX;
  1235. }
  1236. break;
  1237. }
  1238. //
  1239. // unknown address type
  1240. //
  1241. default:
  1242. {
  1243. DNASSERT( FALSE );
  1244. break;
  1245. }
  1246. }
  1247. ExitIPX:
  1248. return pDP8Address;
  1249. FailureIPX:
  1250. if ( pDP8Address != NULL )
  1251. {
  1252. IDirectPlay8Address_Release( pDP8Address );
  1253. pDP8Address = NULL;
  1254. }
  1255. goto ExitIPX;
  1256. break;
  1257. }
  1258. #endif // !DPNBUILD_NOIPX
  1259. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  1260. #ifndef DPNBUILD_NOIPV6
  1261. case AF_INET6:
  1262. #endif // ! DPNBUILD_NOIPV6
  1263. default:
  1264. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  1265. {
  1266. #ifndef DPNBUILD_ONLYONESP
  1267. //
  1268. // set SP
  1269. //
  1270. hr = IDirectPlay8Address_SetSP( pDP8Address, &CLSID_DP8SP_TCPIP );
  1271. if ( hr != DPN_OK )
  1272. {
  1273. DPFX(DPFPREP, 0, "Failed to set SP GUID!" );
  1274. DisplayDNError( 0, hr );
  1275. goto FailureIP;
  1276. }
  1277. #endif // ! DPNBUILD_ONLYONESP
  1278. switch ( AddressType )
  1279. {
  1280. case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
  1281. case SP_ADDRESS_TYPE_DEVICE:
  1282. {
  1283. #ifndef DPNBUILD_ONLYONEADAPTER
  1284. GUID DeviceGuid;
  1285. GuidFromInternalAddressWithoutPort( &DeviceGuid );
  1286. hr = IDirectPlay8Address_SetDevice( pDP8Address, &DeviceGuid );
  1287. if (hr != DPN_OK)
  1288. {
  1289. DPFX(DPFPREP, 0, "Couldn't add device GUID!");
  1290. goto FailureIP;
  1291. }
  1292. #endif // ! DPNBUILD_ONLYONEADAPTER
  1293. break;
  1294. }
  1295. case SP_ADDRESS_TYPE_PUBLIC_HOST_ADDRESS:
  1296. case SP_ADDRESS_TYPE_READ_HOST:
  1297. case SP_ADDRESS_TYPE_HOST:
  1298. #ifndef DPNBUILD_NOMULTICAST
  1299. case SP_ADDRESS_TYPE_MULTICAST_GROUP:
  1300. #endif // ! DPNBUILD_NOMULTICAST
  1301. {
  1302. TCHAR tszHostname[MAX_HOSTNAME_SIZE / sizeof(TCHAR)];
  1303. #ifdef DPNBUILD_XNETSECURITY
  1304. TCHAR * ptszCurrent;
  1305. BYTE * pbCurrent;
  1306. DWORD dwTemp;
  1307. //
  1308. // The buffer should be large enough to hold an XNet address.
  1309. //
  1310. DBG_CASSERT(MAX_HOSTNAME_SIZE > ((sizeof(XNADDR) * 2) + 1) * sizeof(WCHAR));
  1311. #endif // DPNBUILD_XNETSECURITY
  1312. #ifndef DPNBUILD_NOIPV6
  1313. if (GetFamily() == AF_INET6)
  1314. {
  1315. DBG_CASSERT((sizeof(tszHostname) / sizeof(TCHAR)) >= INET6_ADDRSTRLEN);
  1316. #ifdef UNICODE
  1317. DNIpv6AddressToStringW(&m_SocketAddress.IPv6SocketAddress.sin6_addr, tszHostname);
  1318. #else // ! UNICODE
  1319. Won't compile because we haven't implemented DNIpv6AddressToStringA
  1320. #endif // ! UNICODE
  1321. }
  1322. else
  1323. #endif // ! DPNBUILD_NOIPV6
  1324. {
  1325. #ifdef DPNBUILD_XNETSECURITY
  1326. if (pxnaddr != NULL)
  1327. {
  1328. ptszCurrent = tszHostname;
  1329. pbCurrent = (BYTE*) pxnaddr;
  1330. for(dwTemp = 0; dwTemp < sizeof(XNADDR); dwTemp++)
  1331. {
  1332. ptszCurrent += wsprintf(ptszCurrent, _T("%02X"), (*pbCurrent));
  1333. pbCurrent++;
  1334. }
  1335. }
  1336. else if ((pullKeyID != NULL) &&
  1337. (m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr != INADDR_BROADCAST))
  1338. {
  1339. int iError;
  1340. XNADDR xnaddr;
  1341. #ifdef DBG
  1342. XNKID xnkid;
  1343. #endif // DBG
  1344. DBG_CASSERT(sizeof(xnkid) == sizeof(*pullKeyID));
  1345. #ifdef DPNBUILD_ONLYONEADAPTER
  1346. IN_ADDR inaddrToUse;
  1347. //
  1348. // Special case 0.0.0.0, the XNet library expects the loopback address
  1349. // instead when retrieving the local address.
  1350. //
  1351. inaddrToUse = m_SocketAddress.IPSocketAddress.sin_addr;
  1352. if (inaddrToUse.S_un.S_addr == 0)
  1353. {
  1354. inaddrToUse.S_un.S_addr = IP_LOOPBACK_ADDRESS;
  1355. }
  1356. iError = XNetInAddrToXnAddr(inaddrToUse,
  1357. #else // ! DPNBUILD_ONLYONEADAPTER
  1358. iError = XNetInAddrToXnAddr(m_SocketAddress.IPSocketAddress.sin_addr,
  1359. #endif // ! DPNBUILD_ONLYONEADAPTER
  1360. &xnaddr,
  1361. #ifdef DBG
  1362. &xnkid);
  1363. #else // ! DBG
  1364. NULL);
  1365. #endif // ! DBG
  1366. if (iError != 0)
  1367. {
  1368. DPFX(DPFPREP, 0, "Converting XNet address to InAddr failed (err = %i)!",
  1369. iError);
  1370. DNASSERT(FALSE);
  1371. //hr = DPNERR_NOCONNECTION;
  1372. goto FailureIP;
  1373. }
  1374. #ifdef DPNBUILD_ONLYONEADAPTER
  1375. if (inaddrToUse.S_un.S_addr != IP_LOOPBACK_ADDRESS)
  1376. #endif // DPNBUILD_ONLYONEADAPTER
  1377. {
  1378. #ifdef DBG
  1379. DNASSERT(memcmp(&xnkid, pullKeyID, sizeof(xnkid)) == 0);
  1380. #endif // DBG
  1381. }
  1382. ptszCurrent = tszHostname;
  1383. pbCurrent = (BYTE*) (&xnaddr);
  1384. for(dwTemp = 0; dwTemp < sizeof(XNADDR); dwTemp++)
  1385. {
  1386. ptszCurrent += wsprintf(tszHostname, _T("%02X"), (*pbCurrent));
  1387. pbCurrent++;
  1388. }
  1389. }
  1390. else
  1391. #endif // DPNBUILD_XNETSECURITY
  1392. {
  1393. wsprintf(tszHostname, _T("%u.%u.%u.%u"),
  1394. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b1,
  1395. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b2,
  1396. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b3,
  1397. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b4);
  1398. }
  1399. }
  1400. #ifdef UNICODE
  1401. hr = IDirectPlay8Address_AddComponent( pDP8Address,
  1402. DPNA_KEY_HOSTNAME,
  1403. tszHostname,
  1404. (_tcslen(tszHostname) + 1) * sizeof (TCHAR),
  1405. DPNA_DATATYPE_STRING );
  1406. #else // ! UNICODE
  1407. hr = IDirectPlay8Address_AddComponent( pDP8Address,
  1408. DPNA_KEY_HOSTNAME,
  1409. tszHostname,
  1410. (_tcslen(tszHostname) + 1) * sizeof (TCHAR),
  1411. DPNA_DATATYPE_STRING_ANSI );
  1412. #endif // ! UNICODE
  1413. if (hr != DPN_OK)
  1414. {
  1415. DPFX(DPFPREP, 0, "Couldn't add hostname component!");
  1416. goto FailureIP;
  1417. }
  1418. break;
  1419. }
  1420. default:
  1421. {
  1422. DNASSERT( FALSE );
  1423. break;
  1424. }
  1425. }
  1426. dwPort = NTOHS( m_SocketAddress.IPSocketAddress.sin_port );
  1427. hr = IDirectPlay8Address_AddComponent( pDP8Address,
  1428. DPNA_KEY_PORT,
  1429. &dwPort,
  1430. (sizeof(dwPort)),
  1431. DPNA_DATATYPE_DWORD );
  1432. if (hr != DPN_OK)
  1433. {
  1434. DPFX(DPFPREP, 0, "Couldn't add port component!");
  1435. goto FailureIP;
  1436. }
  1437. ExitIP:
  1438. return pDP8Address;
  1439. FailureIP:
  1440. if ( pDP8Address != NULL )
  1441. {
  1442. IDirectPlay8Address_Release( pDP8Address );
  1443. pDP8Address = NULL;
  1444. }
  1445. goto ExitIP;
  1446. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  1447. break;
  1448. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  1449. }
  1450. }
  1451. }
  1452. //**********************************************************************
  1453. //**********************************************************************
  1454. // ------------------------------
  1455. // CSocketAddress::CompareToBaseAddress - compare this address to a 'base' address
  1456. // of this class
  1457. //
  1458. // Entry: Pointer to base address
  1459. //
  1460. // Exit: Integer indicating relative magnitude:
  1461. // 0 = items equal
  1462. // -1 = other item is of greater magnitude
  1463. // 1 = this item is of lesser magnitude
  1464. // ------------------------------
  1465. #undef DPF_MODNAME
  1466. #define DPF_MODNAME "CSocketAddress::CompareToBaseAddress"
  1467. INT_PTR CSocketAddress::CompareToBaseAddress( const SOCKADDR *const pBaseAddress ) const
  1468. {
  1469. DNASSERT( pBaseAddress != NULL );
  1470. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  1471. switch (GetFamily())
  1472. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  1473. {
  1474. #ifndef DPNBUILD_NOIPV6
  1475. case AF_INET6:
  1476. {
  1477. const SOCKADDR_IN6 *pBaseIPv6Address;
  1478. if ( pBaseAddress->sa_family != m_SocketAddress.SocketAddress.sa_family )
  1479. {
  1480. DNASSERT(pBaseAddress->sa_family == AF_INET);
  1481. return -1;
  1482. }
  1483. pBaseIPv6Address = reinterpret_cast<const SOCKADDR_IN6*>( pBaseAddress );
  1484. return (memcmp(&m_SocketAddress.IPv6SocketAddress.sin6_addr,
  1485. &pBaseIPv6Address->sin6_addr,
  1486. sizeof(m_SocketAddress.IPv6SocketAddress.sin6_addr)));
  1487. break;
  1488. }
  1489. #endif // ! DPNBUILD_NOIPV6
  1490. #ifndef DPNBUILD_NOIPX
  1491. case AF_IPX:
  1492. {
  1493. const SOCKADDR_IPX *pBaseIPXAddress;
  1494. DNASSERT( pBaseAddress->sa_family == m_SocketAddress.SocketAddress.sa_family );
  1495. pBaseIPXAddress = reinterpret_cast<const SOCKADDR_IPX *>( pBaseAddress );
  1496. DBG_CASSERT( OFFSETOF( SOCKADDR_IPX, sa_nodenum ) == OFFSETOF( SOCKADDR_IPX, sa_netnum ) + sizeof( pBaseIPXAddress->sa_netnum ) );
  1497. return memcmp( &m_SocketAddress.IPXSocketAddress.sa_nodenum,
  1498. &pBaseIPXAddress->sa_nodenum,
  1499. sizeof( pBaseIPXAddress->sa_nodenum ) );
  1500. break;
  1501. }
  1502. #endif // ! DPNBUILD_NOIPX
  1503. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  1504. default:
  1505. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  1506. {
  1507. const SOCKADDR_IN *pBaseIPAddress;
  1508. DNASSERT( GetFamily() == AF_INET );
  1509. #ifndef DPNBUILD_NOIPV6
  1510. if ( pBaseAddress->sa_family != m_SocketAddress.SocketAddress.sa_family )
  1511. {
  1512. DNASSERT(pBaseAddress->sa_family == AF_INET6);
  1513. return -1;
  1514. }
  1515. #endif // ! DPNBUILD_NOIPV6
  1516. pBaseIPAddress = reinterpret_cast<const SOCKADDR_IN*>( pBaseAddress );
  1517. if ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == pBaseIPAddress->sin_addr.S_un.S_addr )
  1518. {
  1519. return 0;
  1520. }
  1521. else
  1522. {
  1523. if ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr < pBaseIPAddress->sin_addr.S_un.S_addr )
  1524. {
  1525. return 1;
  1526. }
  1527. else
  1528. {
  1529. return -1;
  1530. }
  1531. }
  1532. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  1533. break;
  1534. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  1535. }
  1536. }
  1537. }
  1538. //**********************************************************************
  1539. #ifndef DPNBUILD_ONLYONEADAPTER
  1540. //**********************************************************************
  1541. // ------------------------------
  1542. // CSocketAddress::EnumAdapters - enumerate all of the adapters for this machine
  1543. //
  1544. // Entry: Pointer to enum adapters data
  1545. //
  1546. // Exit: Error code
  1547. // ------------------------------
  1548. #undef DPF_MODNAME
  1549. #define DPF_MODNAME "CSocketAddress::EnumAdapters"
  1550. HRESULT CSocketAddress::EnumAdapters( SPENUMADAPTERSDATA *const pEnumData ) const
  1551. {
  1552. #ifndef DPNBUILD_NOIPX
  1553. if (GetFamily() == AF_IPX)
  1554. {
  1555. return EnumIPXAdapters(pEnumData);
  1556. }
  1557. else
  1558. #endif // ! DPNBUILD_NOIPX
  1559. {
  1560. #ifdef DPNBUILD_NOIPV6
  1561. return EnumIPv4Adapters(pEnumData);
  1562. #else // ! DPNBUILD_NOIPV6
  1563. return EnumIPv6and4Adapters(pEnumData);
  1564. #endif // ! DPNBUILD_NOIPV6
  1565. }
  1566. }
  1567. //**********************************************************************
  1568. #ifndef DPNBUILD_NOIPX
  1569. //**********************************************************************
  1570. // ------------------------------
  1571. // CSocketAddress::EnumIPXAdapters - enumerate all of the adapters for this machine
  1572. //
  1573. // Entry: Pointer to enum adapters data
  1574. //
  1575. // Exit: Error code
  1576. // ------------------------------
  1577. #undef DPF_MODNAME
  1578. #define DPF_MODNAME "CSocketAddress::EnumIPXAdapters"
  1579. HRESULT CSocketAddress::EnumIPXAdapters( SPENUMADAPTERSDATA *const pEnumData ) const
  1580. {
  1581. HRESULT hr;
  1582. CPackedBuffer PackedBuffer;
  1583. SOCKET TestSocket;
  1584. INT iWSAReturn;
  1585. DWORD dwAddressCount;
  1586. union
  1587. {
  1588. SOCKADDR_IPX IPXSocketAddress;
  1589. SOCKADDR SocketAddress;
  1590. } SockAddr;
  1591. //
  1592. // initialize
  1593. //
  1594. hr = DPN_OK;
  1595. DNASSERT( pEnumData != NULL );
  1596. //
  1597. // initialize
  1598. //
  1599. DEBUG_ONLY( memset( pEnumData->pAdapterData, 0xAA, pEnumData->dwAdapterDataSize ) );
  1600. PackedBuffer.Initialize( pEnumData->pAdapterData, pEnumData->dwAdapterDataSize );
  1601. pEnumData->dwAdapterCount = 0;
  1602. TestSocket = INVALID_SOCKET;
  1603. dwAddressCount = 0;
  1604. //
  1605. // create a socket and attempt to query for all of the IPX addresses. If
  1606. // that fails, fall back to using just the address from 'getsockname'.
  1607. //
  1608. TestSocket = socket( GetFamily(), SOCK_DGRAM, NSPROTO_IPX );
  1609. if ( TestSocket == INVALID_SOCKET )
  1610. {
  1611. DWORD dwWSAError;
  1612. hr = DPNERR_UNSUPPORTED;
  1613. dwWSAError = WSAGetLastError();
  1614. DPFX(DPFPREP, 0, "Failed to create IPX socket when enumerating adapters!" );
  1615. DisplayWinsockError( 0, dwWSAError );
  1616. goto Failure;
  1617. }
  1618. memset( &SockAddr, 0x00, sizeof( SockAddr ) );
  1619. SockAddr.IPXSocketAddress.sa_family = GetFamily();
  1620. iWSAReturn = bind( TestSocket, &SockAddr.SocketAddress, sizeof( SockAddr.IPXSocketAddress ) );
  1621. if ( iWSAReturn == SOCKET_ERROR )
  1622. {
  1623. DWORD dwWSAError;
  1624. hr = DPNERR_OUTOFMEMORY;
  1625. dwWSAError = WSAGetLastError();
  1626. DPFX(DPFPREP, 0, "Failed to bind IPX socket when enumerating adapters!" );
  1627. DisplayWinsockError( 0, dwWSAError );
  1628. goto Failure;
  1629. }
  1630. //
  1631. // NOTE: THE CODE TO EXTRACT ALL IPX ADDRESSES ON NT HAS BEEN DISABLED BECAUSE
  1632. // NT TREATS ALL OF THEM AS THE SAME ONCE THEY ARE BOUND TO THE NETWORK. IF THE
  1633. // CORE IS ATTEMPTING TO BIND TO ALL ADAPTERS THIS WILL CAUSE ALL OF THE BINDS
  1634. // AFTER THE FIRST TO FAIL!
  1635. //
  1636. // iIPXAdapterCount = 0;
  1637. // iIPXAdapterCountSize = sizeof( iIPXAdapterCount );
  1638. // iWSAReturn = getsockopt( TestSocket,
  1639. // NSPROTO_IPX,
  1640. // IPX_MAX_ADAPTER_NUM,
  1641. // reinterpret_cast<char*>( &iIPXAdapterCount ),
  1642. // &iIPXAdapterCountSize );
  1643. // if ( iWSAReturn != 0 )
  1644. // {
  1645. // DWORD dwWSAError;
  1646. //
  1647. //
  1648. // dwWSAError = WSAGetLastError();
  1649. // switch ( dwWSAError )
  1650. // {
  1651. // //
  1652. // // can't enumerate adapters on this machine, fallback to getsockname()
  1653. // //
  1654. // case WSAENOPROTOOPT:
  1655. // {
  1656. INT iReturn;
  1657. INT iSocketNameSize;
  1658. union
  1659. {
  1660. SOCKADDR SocketAddress;
  1661. SOCKADDR_IPX SocketAddressIPX;
  1662. } SocketAddress;
  1663. memset( &SocketAddress, 0x00, sizeof( SocketAddress ) );
  1664. iSocketNameSize = sizeof( SocketAddress );
  1665. iReturn = getsockname( TestSocket, &SocketAddress.SocketAddress, &iSocketNameSize );
  1666. if ( iReturn != 0 )
  1667. {
  1668. DWORD dwWSAError;
  1669. hr = DPNERR_OUTOFMEMORY;
  1670. dwWSAError = WSAGetLastError();
  1671. DPFX(DPFPREP, 0, "Failed to get socket name enumerating IPX sockets!", dwWSAError );
  1672. goto Failure;
  1673. }
  1674. else
  1675. {
  1676. GUID SocketAddressGUID;
  1677. SocketAddress.SocketAddressIPX.sa_socket = 0;
  1678. GuidFromAddress( &SocketAddressGUID, &SocketAddress.SocketAddress );
  1679. DPFX(DPFPREP, 7, "Returning adapter 0: \"%ls\" {%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}, flags = 0x0.",
  1680. g_IPXAdapterString,
  1681. SocketAddressGUID.Data1,
  1682. SocketAddressGUID.Data2,
  1683. SocketAddressGUID.Data3,
  1684. SocketAddressGUID.Data4[0],
  1685. SocketAddressGUID.Data4[1],
  1686. SocketAddressGUID.Data4[2],
  1687. SocketAddressGUID.Data4[3],
  1688. SocketAddressGUID.Data4[4],
  1689. SocketAddressGUID.Data4[5],
  1690. SocketAddressGUID.Data4[6],
  1691. SocketAddressGUID.Data4[7]);
  1692. hr = AddInfoToBuffer( &PackedBuffer, g_IPXAdapterString, &SocketAddressGUID, 0 );
  1693. if ( ( hr != DPN_OK ) && ( hr != DPNERR_BUFFERTOOSMALL ) )
  1694. {
  1695. DPFX(DPFPREP, 0, "Failed to add adapter (getsockname)!" );
  1696. DisplayDNError( 0, hr );
  1697. goto Failure;
  1698. }
  1699. dwAddressCount++;
  1700. }
  1701. // break;
  1702. // }
  1703. //
  1704. // //
  1705. // // other Winsock error
  1706. // //
  1707. // default:
  1708. // {
  1709. // DWORD dwWSAError;
  1710. //
  1711. //
  1712. // hr = DPNERR_OUTOFMEMORY;
  1713. // dwWSAError = WSAGetLastError();
  1714. // DPFX(DPFPREP, 0, "Failed to get IPX adapter count!" );
  1715. // DisplayWinsockError( 0, dwWSAError );
  1716. // goto Failure;
  1717. //
  1718. // break;
  1719. // }
  1720. // }
  1721. // }
  1722. // else
  1723. // {
  1724. // while ( iIPXAdapterCount != 0 )
  1725. // {
  1726. // IPX_ADDRESS_DATA IPXData;
  1727. // int iIPXDataSize;
  1728. //
  1729. //
  1730. // iIPXAdapterCount--;
  1731. // memset( &IPXData, 0x00, sizeof( IPXData ) );
  1732. // iIPXDataSize = sizeof( IPXData );
  1733. // IPXData.adapternum = iIPXAdapterCount;
  1734. //
  1735. // iWSAReturn = p_getsockopt( TestSocket,
  1736. // NSPROTO_IPX,
  1737. // IPX_ADDRESS,
  1738. // reinterpret_cast<char*>( &IPXData ),
  1739. // &iIPXDataSize );
  1740. // if ( iWSAReturn != 0 )
  1741. // {
  1742. // DPFX(DPFPREP, 0, "Failed to get adapter information for adapter: 0x%x", ( iIPXAdapterCount + 1 ) );
  1743. // }
  1744. // else
  1745. // {
  1746. // char Buffer[ 500 ];
  1747. // GUID SocketAddressGUID;
  1748. // union
  1749. // {
  1750. // SOCKADDR_IPX IPXSocketAddress;
  1751. // SOCKADDR SocketAddress;
  1752. // } SocketAddress;
  1753. //
  1754. //
  1755. // wsprintf( Buffer,
  1756. // "IPX Adapter %d - (%02X%02X%02X%02X-%02X%02X%02X%02X%02X%02X)",
  1757. // ( iIPXAdapterCount + 1 ),
  1758. // IPXData.netnum[ 0 ],
  1759. // IPXData.netnum[ 1 ],
  1760. // IPXData.netnum[ 2 ],
  1761. // IPXData.netnum[ 3 ],
  1762. // IPXData.nodenum[ 0 ],
  1763. // IPXData.nodenum[ 1 ],
  1764. // IPXData.nodenum[ 2 ],
  1765. // IPXData.nodenum[ 3 ],
  1766. // IPXData.nodenum[ 4 ],
  1767. // IPXData.nodenum[ 5 ] );
  1768. //
  1769. // memset( &SocketAddress, 0x00, sizeof( SocketAddress ) );
  1770. // SocketAddress.IPXSocketAddress.sa_family = GetFamily();
  1771. // DBG_CASSERT( sizeof( SocketAddress.IPXSocketAddress.sa_netnum ) == sizeof( IPXData.netnum ) );
  1772. // memcpy( &SocketAddress.IPXSocketAddress.sa_netnum, IPXData.netnum, sizeof( SocketAddress.IPXSocketAddress.sa_netnum ) );
  1773. // DBG_CASSERT( sizeof( SocketAddress.IPXSocketAddress.sa_nodenum ) == sizeof( IPXData.nodenum ) );
  1774. // memcpy( &SocketAddress.IPXSocketAddress.sa_nodenum, IPXData.nodenum, sizeof( SocketAddress.IPXSocketAddress.sa_nodenum ) );
  1775. // GuidFromAddress( SocketAddressGUID, SocketAddress.SocketAddress );
  1776. //
  1777. // hr = AddInfoToBuffer( &PackedBuffer, Buffer, &SocketAddressGUID, 0 );
  1778. // if ( ( hr != DPN_OK ) && ( hr != DPNERR_BUFFERTOOSMALL ) )
  1779. // {
  1780. // DPFX(DPFPREP, 0, "Failed to add adapter (getsockname)!" );
  1781. // DisplayDNError( 0, hr );
  1782. // goto Failure;
  1783. // }
  1784. //
  1785. // dwAddressCount++;
  1786. // }
  1787. // }
  1788. // }
  1789. // //
  1790. // // if there was one adapter added, we can return 'All Adapters'
  1791. // //
  1792. // if ( dwAddressCount != 0 )
  1793. // {
  1794. // dwAddressCount++;
  1795. // hr = AddInfoToBuffer( &PackedBuffer, g_AllAdaptersString, &ALL_ADAPTERS_GUID, 0 );
  1796. // if ( ( hr != DPN_OK ) && ( hr != DPNERR_BUFFERTOOSMALL ) )
  1797. // {
  1798. // DPFX(DPFPREP, 0, "Failed to add 'All Adapters'" );
  1799. // DisplayDNError( 0, hr );
  1800. // goto Failure;
  1801. // }
  1802. // }
  1803. pEnumData->dwAdapterCount = dwAddressCount;
  1804. pEnumData->dwAdapterDataSize = PackedBuffer.GetSizeRequired();
  1805. Exit:
  1806. if ( TestSocket != INVALID_SOCKET )
  1807. {
  1808. closesocket( TestSocket );
  1809. TestSocket = INVALID_SOCKET;
  1810. }
  1811. return hr;
  1812. Failure:
  1813. goto Exit;
  1814. }
  1815. //**********************************************************************
  1816. #endif // ! DPNBUILD_NOIPX
  1817. //**********************************************************************
  1818. // ------------------------------
  1819. // CSocketAddress::EnumIPv4Adapters - enumerate all of the IPv4 adapters for this machine
  1820. //
  1821. // Entry: Pointer to enum adapters data
  1822. //
  1823. // Exit: Error code
  1824. // ------------------------------
  1825. #undef DPF_MODNAME
  1826. #define DPF_MODNAME "CSocketAddress::EnumIPv4Adapters"
  1827. HRESULT CSocketAddress::EnumIPv4Adapters( SPENUMADAPTERSDATA *const pEnumData ) const
  1828. {
  1829. HRESULT hr = DPN_OK;
  1830. #if !defined(DPNBUILD_NOWINSOCK2) || defined(DBG)
  1831. DWORD dwError;
  1832. #endif // !DPNBUILD_NOWINSOCK2 OR DBG
  1833. SOCKADDR_IN saddrinTemp;
  1834. const HOSTENT * pHostData;
  1835. IN_ADDR ** ppinaddrTemp;
  1836. DWORD dwAddressCount;
  1837. BOOL fFoundPrivateICS = FALSE;
  1838. IN_ADDR * pinaddrBuffer = NULL;
  1839. DWORD dwIndex;
  1840. ULONG ulAdapterInfoBufferSize = 0;
  1841. GUID guidAdapter;
  1842. DWORD dwDeviceFlags;
  1843. CPackedBuffer PackedBuffer;
  1844. char acBuffer[512];
  1845. WCHAR wszIPAddress[512];
  1846. #ifndef DPNBUILD_NOWINSOCK2
  1847. HMODULE hIpHlpApiDLL;
  1848. IP_ADAPTER_INFO * pCurrentAdapterInfo;
  1849. PIP_ADDR_STRING pIPAddrString;
  1850. PFNGETADAPTERSINFO pfnGetAdaptersInfo;
  1851. IP_ADAPTER_INFO * pAdapterInfoBuffer = NULL;
  1852. const char * pszIPAddress;
  1853. #ifndef DPNBUILD_NOMULTICAST
  1854. DWORD dwMcastInterfaceIndex;
  1855. #endif // ! DPNBUILD_NOMULTICAST
  1856. #endif // ! DPNBUILD_NOWINSOCK2
  1857. DPFX(DPFPREP, 6, "Parameters: (0x%p)", pEnumData);
  1858. PackedBuffer.Initialize( pEnumData->pAdapterData, pEnumData->dwAdapterDataSize );
  1859. ZeroMemory(&saddrinTemp, sizeof(saddrinTemp));
  1860. saddrinTemp.sin_family = GetFamily();
  1861. //
  1862. // Get the list of local IPs from WinSock. We use this method since it's
  1863. // available on all platforms and conveniently returns the loopback address
  1864. // when no valid adapters are currently available.
  1865. //
  1866. if (gethostname(acBuffer, sizeof(acBuffer)) == SOCKET_ERROR)
  1867. {
  1868. #ifdef DBG
  1869. dwError = WSAGetLastError();
  1870. DPFX(DPFPREP, 0, "Failed to get host name into fixed size buffer (err = %u)!", dwError);
  1871. DisplayWinsockError(0, dwError);
  1872. #endif // DBG
  1873. hr = DPNERR_GENERIC;
  1874. goto Failure;
  1875. }
  1876. pHostData = gethostbyname(acBuffer);
  1877. if (pHostData == NULL)
  1878. {
  1879. #ifdef DBG
  1880. dwError = WSAGetLastError();
  1881. DPFX(DPFPREP, 0, "Failed to get host data (err = %u)!", dwError);
  1882. DisplayWinsockError(0, dwError);
  1883. #endif // DBG
  1884. hr = DPNERR_GENERIC;
  1885. goto Failure;
  1886. }
  1887. //
  1888. // Count number of addresses.
  1889. //
  1890. dwAddressCount = 0;
  1891. ppinaddrTemp = (IN_ADDR**) (pHostData->h_addr_list);
  1892. while ((*ppinaddrTemp) != NULL)
  1893. {
  1894. //
  1895. // Remember if it's 192.168.0.1. See below
  1896. //
  1897. if ((*ppinaddrTemp)->S_un.S_addr == IP_PRIVATEICS_ADDRESS)
  1898. {
  1899. fFoundPrivateICS = TRUE;
  1900. }
  1901. dwAddressCount++;
  1902. ppinaddrTemp++;
  1903. }
  1904. if (dwAddressCount == 0)
  1905. {
  1906. DPFX(DPFPREP, 1, "No IP addresses, forcing loopback address.");
  1907. DNASSERTX(!" No IP addresses!", 2);
  1908. dwAddressCount++;
  1909. }
  1910. else
  1911. {
  1912. DPFX(DPFPREP, 3, "WinSock reported %u addresses.", dwAddressCount);
  1913. }
  1914. //
  1915. // Winsock says we should copy this data before any other Winsock calls.
  1916. //
  1917. // We also use this as an opportunity to ensure that the order returned to the caller is
  1918. // to our liking. In particular, we make sure the private address 192.168.0.1 appears
  1919. // first.
  1920. //
  1921. DNASSERT(pHostData->h_length == sizeof(IN_ADDR));
  1922. pinaddrBuffer = (IN_ADDR*) DNMalloc(dwAddressCount * sizeof(IN_ADDR));
  1923. if (pinaddrBuffer == NULL)
  1924. {
  1925. DPFX(DPFPREP, 0, "Failed to allocate memory to store copy of addresses!");
  1926. hr = DPNERR_OUTOFMEMORY;
  1927. goto Failure;
  1928. }
  1929. dwIndex = 0;
  1930. //
  1931. // First, store 192.168.0.1 if we found it.
  1932. //
  1933. if (fFoundPrivateICS)
  1934. {
  1935. pinaddrBuffer[dwIndex].S_un.S_addr = IP_PRIVATEICS_ADDRESS;
  1936. dwIndex++;
  1937. }
  1938. //
  1939. // Then copy the rest.
  1940. //
  1941. ppinaddrTemp = (IN_ADDR**) (pHostData->h_addr_list);
  1942. while ((*ppinaddrTemp) != NULL)
  1943. {
  1944. if ((*ppinaddrTemp)->S_un.S_addr != IP_PRIVATEICS_ADDRESS)
  1945. {
  1946. pinaddrBuffer[dwIndex].S_un.S_addr = (*ppinaddrTemp)->S_un.S_addr;
  1947. dwIndex++;
  1948. }
  1949. ppinaddrTemp++;
  1950. }
  1951. //
  1952. // If we didn't have any addresses, slap in the loopback address.
  1953. //
  1954. if (dwIndex == 0)
  1955. {
  1956. pinaddrBuffer[0].S_un.S_addr = IP_LOOPBACK_ADDRESS;
  1957. dwIndex++;
  1958. }
  1959. DNASSERT(dwIndex == dwAddressCount);
  1960. //
  1961. // Now we try to generate names and GUIDs for these IP addresses.
  1962. // We'll use what IPHLPAPI reports for a name if possible, and fall
  1963. // back to just using the IP address string as the name.
  1964. //
  1965. #ifndef DPNBUILD_NOWINSOCK2
  1966. //
  1967. // Load the IPHLPAPI module and get the adapter list if possible.
  1968. //
  1969. hIpHlpApiDLL = LoadLibrary(c_tszIPHelperDLLName);
  1970. if (hIpHlpApiDLL != NULL)
  1971. {
  1972. #ifndef DPNBUILD_NOMULTICAST
  1973. PFNGETBESTINTERFACE pfnGetBestInterface;
  1974. pfnGetBestInterface = (PFNGETBESTINTERFACE) GetProcAddress(hIpHlpApiDLL, _TWINCE("GetBestInterface"));
  1975. if (pfnGetBestInterface != NULL)
  1976. {
  1977. //
  1978. // Ask IPHLPAPI for its opinion on the best multicast interface.
  1979. // We use an arbitrary multicast address, and assume that the
  1980. // TCP/IP stack doesn't treat individual multicast addresses
  1981. // differently.
  1982. //
  1983. dwError = pfnGetBestInterface(SAMPLE_MULTICAST_ADDRESS, &dwMcastInterfaceIndex);
  1984. if (dwError != ERROR_SUCCESS)
  1985. {
  1986. DPFX(DPFPREP, 0, "Couldn't determine best multicast interface index (err = %u)! Continuing.",
  1987. dwError);
  1988. dwMcastInterfaceIndex = INVALID_INTERFACE_INDEX;
  1989. }
  1990. else
  1991. {
  1992. DPFX(DPFPREP, 7, "Best interface for multicasting is index 0x%x.",
  1993. dwMcastInterfaceIndex);
  1994. }
  1995. }
  1996. else
  1997. {
  1998. dwError = GetLastError();
  1999. DPFX(DPFPREP, 0, "Couldn't load \"GetBestInterface\" function (err = %u)! Continuing.",
  2000. dwError);
  2001. }
  2002. #endif // ! DPNBUILD_NOMULTICAST
  2003. pfnGetAdaptersInfo = (PFNGETADAPTERSINFO) GetProcAddress(hIpHlpApiDLL, _TWINCE("GetAdaptersInfo"));
  2004. if (pfnGetAdaptersInfo != NULL)
  2005. {
  2006. //
  2007. // Keep resizing the buffer until there's enough room.
  2008. //
  2009. do
  2010. {
  2011. dwError = pfnGetAdaptersInfo(pAdapterInfoBuffer,
  2012. &ulAdapterInfoBufferSize);
  2013. if (dwError == ERROR_SUCCESS)
  2014. {
  2015. //
  2016. // We got all the info we're going to get. Make sure it
  2017. // was something.
  2018. //
  2019. if (ulAdapterInfoBufferSize == 0)
  2020. {
  2021. DPFX(DPFPREP, 0, "GetAdaptersInfo returned 0 byte size requirement! Ignoring.");
  2022. //
  2023. // Get rid of the buffer if allocated.
  2024. //
  2025. if (pAdapterInfoBuffer != NULL)
  2026. {
  2027. DNFree(pAdapterInfoBuffer);
  2028. pAdapterInfoBuffer = NULL;
  2029. }
  2030. //
  2031. // Continue with exiting the loop.
  2032. //
  2033. }
  2034. #ifdef DBG
  2035. else
  2036. {
  2037. int iStrLen;
  2038. char szIPList[256];
  2039. char * pszCurrentIP;
  2040. //
  2041. // Print out all the adapters for debugging purposes.
  2042. //
  2043. pCurrentAdapterInfo = pAdapterInfoBuffer;
  2044. while (pCurrentAdapterInfo != NULL)
  2045. {
  2046. //
  2047. // Initialize IP address list string.
  2048. //
  2049. szIPList[0] = '\0';
  2050. pszCurrentIP = szIPList;
  2051. //
  2052. // Loop through all addresses for this adapter.
  2053. //
  2054. pIPAddrString = &pCurrentAdapterInfo->IpAddressList;
  2055. while (pIPAddrString != NULL)
  2056. {
  2057. //
  2058. // Copy the IP address string (if there's enough room),
  2059. // then tack on a space and NULL terminator.
  2060. //
  2061. iStrLen = strlen(pIPAddrString->IpAddress.String);
  2062. if ((pszCurrentIP + iStrLen + 2) < (szIPList + sizeof(szIPList)))
  2063. {
  2064. memcpy(pszCurrentIP, pIPAddrString->IpAddress.String, iStrLen);
  2065. pszCurrentIP += iStrLen;
  2066. (*pszCurrentIP) = ' ';
  2067. pszCurrentIP++;
  2068. (*pszCurrentIP) = '\0';
  2069. pszCurrentIP++;
  2070. }
  2071. pIPAddrString = pIPAddrString->Next;
  2072. }
  2073. DPFX(DPFPREP, 8, "Adapter index %u IPs = %hs, %hs, \"%hs\".",
  2074. pCurrentAdapterInfo->Index,
  2075. szIPList,
  2076. pCurrentAdapterInfo->AdapterName,
  2077. pCurrentAdapterInfo->Description);
  2078. //
  2079. // Go to next adapter.
  2080. //
  2081. pCurrentAdapterInfo = pCurrentAdapterInfo->Next;
  2082. }
  2083. } // end else (got valid buffer size)
  2084. #endif // DBG
  2085. break;
  2086. }
  2087. if ((dwError != ERROR_BUFFER_OVERFLOW) &&
  2088. (dwError != ERROR_INSUFFICIENT_BUFFER))
  2089. {
  2090. DPFX(DPFPREP, 0, "GetAdaptersInfo failed (err = 0x%lx)! Ignoring.", dwError);
  2091. //
  2092. // Get rid of the buffer if allocated, and then bail out of
  2093. // the loop.
  2094. //
  2095. if (pAdapterInfoBuffer != NULL)
  2096. {
  2097. DNFree(pAdapterInfoBuffer);
  2098. pAdapterInfoBuffer = NULL;
  2099. }
  2100. break;
  2101. }
  2102. //
  2103. // If we're here, then we need to reallocate the buffer.
  2104. //
  2105. if (pAdapterInfoBuffer != NULL)
  2106. {
  2107. DNFree(pAdapterInfoBuffer);
  2108. pAdapterInfoBuffer = NULL;
  2109. }
  2110. pAdapterInfoBuffer = (IP_ADAPTER_INFO*) DNMalloc(ulAdapterInfoBufferSize);
  2111. if (pAdapterInfoBuffer == NULL)
  2112. {
  2113. //
  2114. // Couldn't allocate memory. Bail out of the loop.
  2115. //
  2116. break;
  2117. }
  2118. //
  2119. // Successfully allocated buffer. Try again.
  2120. //
  2121. }
  2122. while (TRUE);
  2123. //
  2124. // We get here in all cases, so we may have failed to get an info
  2125. // buffer. That's fine, we'll use the fallback to generate the
  2126. // names.
  2127. //
  2128. }
  2129. else
  2130. {
  2131. #ifdef DBG
  2132. dwError = GetLastError();
  2133. DPFX(DPFPREP, 0, "Failed to get proc address for GetAdaptersInfo!");
  2134. DisplayErrorCode(0, dwError);
  2135. #endif // DBG
  2136. //
  2137. // Continue. We'll use the fallback to generate the names.
  2138. //
  2139. }
  2140. //
  2141. // We don't need the library anymore.
  2142. //
  2143. FreeLibrary(hIpHlpApiDLL);
  2144. hIpHlpApiDLL = NULL;
  2145. }
  2146. else
  2147. {
  2148. #ifdef DBG
  2149. dwError = GetLastError();
  2150. DPFX(DPFPREP, 0, "Failed to get proc address for GetAdaptersInfo!");
  2151. DisplayErrorCode(0, dwError);
  2152. #endif // DBG
  2153. //
  2154. // Continue. We'll use the fallback to generate the names.
  2155. //
  2156. }
  2157. #endif // !DPNBUILD_NOWINSOCK2
  2158. //
  2159. // Loop through all IP addresses, generating names and GUIDs.
  2160. //
  2161. for(dwIndex = 0; dwIndex < dwAddressCount; dwIndex++)
  2162. {
  2163. //
  2164. // Start off assuming this IP address won't have any special
  2165. // flags.
  2166. //
  2167. dwDeviceFlags = 0;
  2168. #ifndef DPNBUILD_NOMULTICAST
  2169. //
  2170. // If this is the first device and we couldn't use IPHLPAPI to
  2171. // determine the best multicast interface, then just say the
  2172. // default multicast interface is the first (for lack of a
  2173. // better idea).
  2174. //
  2175. #ifdef DPNBUILD_NOWINSOCK2
  2176. if (dwIndex == 0)
  2177. #else // ! DPNBUILD_NOWINSOCK2
  2178. if ((dwIndex == 0) && (dwMcastInterfaceIndex == INVALID_INTERFACE_INDEX))
  2179. #endif // ! DPNBUILD_NOWINSOCK2
  2180. {
  2181. dwDeviceFlags |= DPNSPINFO_DEFAULTMULTICASTDEVICE;
  2182. }
  2183. #endif // ! DPNBUILD_NOMULTICAST
  2184. #ifdef DPNBUILD_NOWINSOCK2
  2185. DNinet_ntow(pinaddrBuffer[dwIndex], wszIPAddress);
  2186. #else // ! DPNBUILD_NOWINSOCK2
  2187. //
  2188. // Get the IP address string. We don't make any other WinSock
  2189. // calls, so holding on to the pointer is OK. This pointer
  2190. // may be used as the device name string, too.
  2191. //
  2192. pszIPAddress = inet_ntoa(pinaddrBuffer[dwIndex]);
  2193. //
  2194. // Look for an adapter name from IPHLPAPI if possible.
  2195. //
  2196. if (pAdapterInfoBuffer != NULL)
  2197. {
  2198. pCurrentAdapterInfo = pAdapterInfoBuffer;
  2199. while (pCurrentAdapterInfo != NULL)
  2200. {
  2201. //
  2202. // Look for matching IP.
  2203. //
  2204. pIPAddrString = &pCurrentAdapterInfo->IpAddressList;
  2205. while (pIPAddrString != NULL)
  2206. {
  2207. if (strcmp(pIPAddrString->IpAddress.String, pszIPAddress) == 0)
  2208. {
  2209. #ifndef DPNBUILD_NOMULTICAST
  2210. //
  2211. // If it's the interface reported earlier as the best
  2212. // multicast interface, remember that fact.
  2213. //
  2214. if (pCurrentAdapterInfo->Index == dwMcastInterfaceIndex)
  2215. {
  2216. DPFX(DPFPREP, 7, "Found %hs under adapter index %u (\"%hs\"), and it's the best multicast interface.",
  2217. pszIPAddress, pCurrentAdapterInfo->Index,
  2218. pCurrentAdapterInfo->Description);
  2219. DNASSERT(pCurrentAdapterInfo->Index != INVALID_INTERFACE_INDEX);
  2220. dwDeviceFlags |= DPNSPINFO_DEFAULTMULTICASTDEVICE;
  2221. }
  2222. else
  2223. #endif // ! DPNBUILD_NOMULTICAST
  2224. {
  2225. DPFX(DPFPREP, 9, "Found %hs under adapter index %u (\"%hs\").",
  2226. pszIPAddress, pCurrentAdapterInfo->Index,
  2227. pCurrentAdapterInfo->Description);
  2228. }
  2229. //
  2230. // Build the name string.
  2231. //
  2232. DBG_CASSERT(sizeof(acBuffer) > MAX_ADAPTER_DESCRIPTION_LENGTH);
  2233. wsprintfA(acBuffer,
  2234. c_szAdapterNameTemplate,
  2235. pCurrentAdapterInfo->Description,
  2236. pszIPAddress);
  2237. //
  2238. // Point the name string to the buffer and drop out
  2239. // of the loop.
  2240. //
  2241. pszIPAddress = acBuffer;
  2242. break;
  2243. }
  2244. //
  2245. // Move to next IP address.
  2246. //
  2247. pIPAddrString = pIPAddrString->Next;
  2248. }
  2249. //
  2250. // If we found the address, stop looping through adapters,
  2251. // too.
  2252. //
  2253. if (pszIPAddress == acBuffer)
  2254. {
  2255. break;
  2256. }
  2257. //
  2258. // Otherwise, go to next adapter.
  2259. //
  2260. pCurrentAdapterInfo = pCurrentAdapterInfo->Next;
  2261. }
  2262. //
  2263. // If we never found the adapter, pszIPAddress will still point to
  2264. // the IP address string.
  2265. //
  2266. }
  2267. else
  2268. {
  2269. //
  2270. // Didn't successfully get IPHLPAPI adapter info. pszIPAddress will
  2271. // still point to the IP address string.
  2272. //
  2273. }
  2274. hr = STR_jkAnsiToWide(wszIPAddress, pszIPAddress, 512);
  2275. if (FAILED(hr))
  2276. {
  2277. DPFX(DPFPREP, 0, "Failed to convert adapter name to wide (err = 0x%lx)!", hr);
  2278. DisplayDNError( 0, hr );
  2279. goto Failure;
  2280. }
  2281. #endif // ! DPNBUILD_NOWINSOCK2
  2282. //
  2283. // Generate the GUID.
  2284. //
  2285. saddrinTemp.sin_addr = pinaddrBuffer[dwIndex];
  2286. GuidFromAddress(&guidAdapter, (SOCKADDR*) (&saddrinTemp));
  2287. DPFX(DPFPREP, 7, "Returning adapter %u: \"%ls\" {%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}, flags = 0x%lx.",
  2288. dwIndex,
  2289. wszIPAddress,
  2290. guidAdapter.Data1,
  2291. guidAdapter.Data2,
  2292. guidAdapter.Data3,
  2293. guidAdapter.Data4[0],
  2294. guidAdapter.Data4[1],
  2295. guidAdapter.Data4[2],
  2296. guidAdapter.Data4[3],
  2297. guidAdapter.Data4[4],
  2298. guidAdapter.Data4[5],
  2299. guidAdapter.Data4[6],
  2300. guidAdapter.Data4[7],
  2301. dwDeviceFlags);
  2302. //
  2303. // Add adapter to buffer.
  2304. //
  2305. hr = AddInfoToBuffer(&PackedBuffer, wszIPAddress, &guidAdapter, dwDeviceFlags);
  2306. if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
  2307. {
  2308. DPFX(DPFPREP, 0, "Failed to add adapter to buffer (err = 0x%lx)!", hr);
  2309. DisplayDNError( 0, hr );
  2310. goto Failure;
  2311. }
  2312. } // end for (each IP address)
  2313. //
  2314. // If we're here, we successfully built the list of adapters, although
  2315. // the caller may not have given us enough buffer space to store it.
  2316. //
  2317. pEnumData->dwAdapterCount = dwAddressCount;
  2318. pEnumData->dwAdapterDataSize = PackedBuffer.GetSizeRequired();
  2319. Exit:
  2320. #ifndef DPNBUILD_NOWINSOCK2
  2321. if (pAdapterInfoBuffer != NULL)
  2322. {
  2323. DNFree(pAdapterInfoBuffer);
  2324. pAdapterInfoBuffer = NULL;
  2325. }
  2326. #endif // !DPNBUILD_NOWINSOCK2
  2327. if (pinaddrBuffer != NULL)
  2328. {
  2329. DNFree(pinaddrBuffer);
  2330. pinaddrBuffer = NULL;
  2331. }
  2332. DPFX(DPFPREP, 6, "Return [0x%lx]", hr);
  2333. return hr;
  2334. Failure:
  2335. goto Exit;
  2336. }
  2337. //**********************************************************************
  2338. #ifndef DPNBUILD_NOIPV6
  2339. //**********************************************************************
  2340. // ------------------------------
  2341. // CSocketAddress::EnumIPv6and4Adapters - enumerate all of the IPv6 and IPv4 adapters for this machine
  2342. //
  2343. // Entry: Pointer to enum adapters data
  2344. //
  2345. // Exit: Error code
  2346. // ------------------------------
  2347. #undef DPF_MODNAME
  2348. #define DPF_MODNAME "CSocketAddress::EnumIPv6and4Adapters"
  2349. HRESULT CSocketAddress::EnumIPv6and4Adapters( SPENUMADAPTERSDATA *const pEnumData ) const
  2350. {
  2351. HRESULT hr;
  2352. DWORD dwError;
  2353. HMODULE hIpHlpApiDLL = NULL;
  2354. PFNGETADAPTERSADDRESSES pfnGetAdaptersAddresses;
  2355. CPackedBuffer PackedBuffer;
  2356. IP_ADAPTER_ADDRESSES * pIpAdapterAddresses = NULL;
  2357. ULONG ulIpAdapterAddressesLength = 0;
  2358. DWORD dwTotalNumIPv6Addresses = 0;
  2359. DWORD dwTotalNumIPv4Addresses = 0;
  2360. DWORD dwLongestDescription = 0;
  2361. WCHAR * pwszBuffer = NULL;
  2362. IP_ADAPTER_ADDRESSES * pIpAdapterAddressesCurrent;
  2363. IP_ADAPTER_UNICAST_ADDRESS * pIpAdapterUnicastAddressCurrent;
  2364. SORTADAPTERADDRESS * paSortAdapterAddress = NULL;
  2365. DWORD dwNumIPv6Addresses = 0;
  2366. DWORD dwNumIPv4Addresses = 0;
  2367. BOOL fSkipIPv4Loopback = FALSE;
  2368. BOOL fFoundIPv4Loopback = FALSE;
  2369. SOCKADDR_IN saddrinLoopback;
  2370. GUID guidAdapter;
  2371. DWORD dwTemp;
  2372. DWORD dwDeviceFlags;
  2373. WCHAR wszIPAddress[INET6_ADDRSTRLEN];
  2374. DPFX(DPFPREP, 6, "Parameters: (0x%p)", pEnumData);
  2375. PackedBuffer.Initialize( pEnumData->pAdapterData, pEnumData->dwAdapterDataSize );
  2376. //
  2377. // Load the IPHLPAPI module and get the adapter list if possible.
  2378. //
  2379. hIpHlpApiDLL = LoadLibrary(c_tszIPHelperDLLName);
  2380. if (hIpHlpApiDLL == NULL)
  2381. {
  2382. #ifdef DBG
  2383. dwError = GetLastError();
  2384. DPFX(DPFPREP, 1, "Couldn't load IPHLPAPI, unable to look for IPv6 adapters (err = %u).", dwError);
  2385. #endif // DBG
  2386. //
  2387. // Just enumerate IPv4 adapters.
  2388. //
  2389. hr = EnumIPv4Adapters(pEnumData);
  2390. goto Exit;
  2391. }
  2392. pfnGetAdaptersAddresses = (PFNGETADAPTERSADDRESSES) GetProcAddress(hIpHlpApiDLL, _TWINCE("GetAdaptersAddresses"));
  2393. if (pfnGetAdaptersAddresses == NULL)
  2394. {
  2395. #ifdef DBG
  2396. dwError = GetLastError();
  2397. DPFX(DPFPREP, 1, "Couldn't find \"GetAdaptersAddresses\" function, unable to look for IPv6 adapters (err = %u).", dwError);
  2398. #endif // DBG
  2399. //
  2400. // Just enumerate IPv4 adapters.
  2401. //
  2402. hr = EnumIPv4Adapters(pEnumData);
  2403. goto Exit;
  2404. }
  2405. //
  2406. // OK, we're on a platform where it's possible to look for both IPv6 & IPv4 adapters.
  2407. //
  2408. do
  2409. {
  2410. dwError = pfnGetAdaptersAddresses(g_iIPAddressFamily,
  2411. (GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER),
  2412. NULL,
  2413. pIpAdapterAddresses,
  2414. &ulIpAdapterAddressesLength);
  2415. if (dwError == ERROR_SUCCESS)
  2416. {
  2417. //
  2418. // We got all the info we're going to get. Make sure it was something.
  2419. //
  2420. if (ulIpAdapterAddressesLength < sizeof(IP_ADAPTER_ADDRESSES))
  2421. {
  2422. DPFX(DPFPREP, 0, "GetAdaptersAddresses returned invalid size %u!", ulIpAdapterAddressesLength);
  2423. //
  2424. // Get rid of the buffer if allocated.
  2425. //
  2426. if (pIpAdapterAddresses != NULL)
  2427. {
  2428. DNFree(pIpAdapterAddresses);
  2429. pIpAdapterAddresses = NULL;
  2430. ulIpAdapterAddressesLength = 0;
  2431. }
  2432. //
  2433. // Continue with exiting the loop.
  2434. //
  2435. }
  2436. break;
  2437. }
  2438. if ((dwError != ERROR_BUFFER_OVERFLOW) &&
  2439. (dwError != ERROR_INSUFFICIENT_BUFFER))
  2440. {
  2441. DPFX(DPFPREP, 0, "GetAdaptersAddresses failed (err = 0x%lx)!", dwError);
  2442. hr = DPNERR_OUTOFMEMORY; // assume it's a resource issue
  2443. goto Failure;
  2444. }
  2445. //
  2446. // If we're here, then we need to reallocate the buffer.
  2447. //
  2448. if (pIpAdapterAddresses != NULL)
  2449. {
  2450. DNFree(pIpAdapterAddresses);
  2451. pIpAdapterAddresses = NULL;
  2452. }
  2453. pIpAdapterAddresses = (IP_ADAPTER_ADDRESSES*) DNMalloc(ulIpAdapterAddressesLength);
  2454. if (pIpAdapterAddresses == NULL)
  2455. {
  2456. DPFX(DPFPREP, 0, "Couldn't allocate memory for adapter list!");
  2457. hr = DPNERR_OUTOFMEMORY;
  2458. goto Failure;
  2459. }
  2460. }
  2461. while (TRUE);
  2462. //
  2463. // If there aren't any addresses, throw in the IPv4 loopback address. We will assume that
  2464. // IPv4 is available because IPv6 should always report loopback/link local address and
  2465. // therefore cause pIpAdapterAddresses to be allocated. If IPv6 is not available, then IPv4
  2466. // must be available otherwise we wouldn't have allowed this SP to be loaded.
  2467. //
  2468. // If there are addresses, loop through all the adapters we found to count them and to
  2469. // figure out the longest description name.
  2470. //
  2471. if (pIpAdapterAddresses == NULL)
  2472. {
  2473. DNASSERT(pIpAdapterAddresses == NULL);
  2474. dwTotalNumIPv4Addresses++;
  2475. }
  2476. else
  2477. {
  2478. pIpAdapterAddressesCurrent = pIpAdapterAddresses;
  2479. while (pIpAdapterAddressesCurrent != NULL)
  2480. {
  2481. if (pIpAdapterAddressesCurrent->FriendlyName != NULL)
  2482. {
  2483. dwTemp = wcslen(pIpAdapterAddressesCurrent->FriendlyName);
  2484. if (dwTemp > dwLongestDescription)
  2485. {
  2486. dwLongestDescription = dwTemp;
  2487. }
  2488. }
  2489. else
  2490. {
  2491. if (pIpAdapterAddressesCurrent->Description != NULL)
  2492. {
  2493. dwTemp = wcslen(pIpAdapterAddressesCurrent->Description);
  2494. if (dwTemp > dwLongestDescription)
  2495. {
  2496. dwLongestDescription = dwTemp;
  2497. }
  2498. }
  2499. else
  2500. {
  2501. //
  2502. // No friendly name or description.
  2503. //
  2504. }
  2505. }
  2506. //
  2507. // Count the number of addresses.
  2508. //
  2509. pIpAdapterUnicastAddressCurrent = pIpAdapterAddressesCurrent->FirstUnicastAddress;
  2510. while (pIpAdapterUnicastAddressCurrent != NULL)
  2511. {
  2512. DumpSocketAddress(8, pIpAdapterUnicastAddressCurrent->Address.lpSockaddr, pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family);
  2513. #pragma TODO(vanceo, "Option to allow non-preferred addresses? See below, too.")
  2514. if (pIpAdapterUnicastAddressCurrent->DadState == IpDadStatePreferred)
  2515. {
  2516. if (pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family == AF_INET6)
  2517. {
  2518. //
  2519. // Skip the loopback pseudo-interface. Windows reports the true
  2520. // loopback address, and then a link-local-looking address. We
  2521. // don't care about the link-local one either because there should
  2522. // be real link-local addresses available under other interfaces.
  2523. // So completely jump out of the address loop when we see the
  2524. // IPv6 loopback address. See sorting loop below as well.
  2525. //
  2526. if (IN6_IS_ADDR_LOOPBACK(&(((SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin6_addr)))
  2527. {
  2528. DNASSERT(pIpAdapterUnicastAddressCurrent == pIpAdapterAddressesCurrent->FirstUnicastAddress);
  2529. #pragma TODO(vanceo, "Are we sure we want to depend on the order the addresses are reported? See below, too.")
  2530. break;
  2531. }
  2532. if ((IN6_IS_ADDR_LINKLOCAL(&(((SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin6_addr))) ||
  2533. (IN6_IS_ADDR_SITELOCAL(&(((SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin6_addr))))
  2534. {
  2535. DNASSERT(((SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin6_scope_id != 0);
  2536. }
  2537. dwTotalNumIPv6Addresses++;
  2538. fSkipIPv4Loopback = TRUE;
  2539. }
  2540. else
  2541. {
  2542. DNASSERT(pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family == AF_INET);
  2543. //
  2544. // Skip the IPv4 loopback address if there are other addresses.
  2545. //
  2546. if (((SOCKADDR_IN*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin_addr.S_un.S_addr != IP_LOOPBACK_ADDRESS)
  2547. {
  2548. fSkipIPv4Loopback = TRUE;
  2549. }
  2550. else
  2551. {
  2552. fFoundIPv4Loopback = TRUE;
  2553. }
  2554. dwTotalNumIPv4Addresses++;
  2555. }
  2556. }
  2557. else
  2558. {
  2559. DPFX(DPFPREP, 7, "Skipping address whose state (%u) is not preferred.",
  2560. pIpAdapterUnicastAddressCurrent->DadState);
  2561. }
  2562. pIpAdapterUnicastAddressCurrent = pIpAdapterUnicastAddressCurrent->Next;
  2563. }
  2564. pIpAdapterAddressesCurrent = pIpAdapterAddressesCurrent->Next;
  2565. }
  2566. //
  2567. // If we found the IPv4 loopback address but we can skip it, decrement our IPv4
  2568. // address count.
  2569. //
  2570. if ((fFoundIPv4Loopback) && (fSkipIPv4Loopback))
  2571. {
  2572. DNASSERT(dwTotalNumIPv4Addresses > 0);
  2573. dwTotalNumIPv4Addresses--;
  2574. }
  2575. }
  2576. //
  2577. // Allocate a buffer to hold the largest friendly name + the other info we add to the
  2578. // adapter description. INET6_ADDRSTRLEN is larger than INET_ADDRSTRLEN, and
  2579. // includes NULL termination char (+ other things we don't actually use).
  2580. //
  2581. pwszBuffer = (WCHAR*) DNMalloc((dwLongestDescription + sizeof(c_wszIPv6AdapterNameTemplate) + INET6_ADDRSTRLEN) * sizeof(WCHAR));
  2582. if (pwszBuffer == NULL)
  2583. {
  2584. DPFX(DPFPREP, 0, "Couldn't allocate memory for name string!");
  2585. hr = DPNERR_OUTOFMEMORY;
  2586. goto Failure;
  2587. }
  2588. paSortAdapterAddress = (SORTADAPTERADDRESS*) DNMalloc((dwTotalNumIPv6Addresses + dwTotalNumIPv4Addresses) * sizeof(SORTADAPTERADDRESS));
  2589. if (paSortAdapterAddress == NULL)
  2590. {
  2591. DPFX(DPFPREP, 0, "Couldn't allocate memory for sorted adapter list!");
  2592. hr = DPNERR_OUTOFMEMORY;
  2593. goto Failure;
  2594. }
  2595. memset(paSortAdapterAddress, 0, ((dwTotalNumIPv6Addresses + dwTotalNumIPv4Addresses) * sizeof(SORTADAPTERADDRESS)));
  2596. if (pIpAdapterAddresses == NULL)
  2597. {
  2598. memset(&saddrinLoopback, 0, sizeof(saddrinLoopback));
  2599. saddrinLoopback.sin_family = AF_INET;
  2600. saddrinLoopback.sin_addr.S_un.S_addr = IP_LOOPBACK_ADDRESS;
  2601. paSortAdapterAddress[0].psockaddr = (SOCKADDR*) &saddrinLoopback;
  2602. paSortAdapterAddress[0].pwszDescription = (WCHAR*) c_wszIPv4LoopbackAdapterString;
  2603. }
  2604. else
  2605. {
  2606. //
  2607. // Loop through all the adapters again to sort them.
  2608. // The rules are (in order of precedence):
  2609. // 1) Skip addresses that are not in the 'preferred' state.
  2610. // 2) IPv6 before IPv4.
  2611. // 3) Skip IPv6 loopback pseudo-interface.
  2612. // 4) IPv4 ICS-private-adapter-looking IP addresses (192.168.0.1) first.
  2613. // 5) Skip IPv4 loopback address (127.0.0.1) if we determined there were other addresses.
  2614. //
  2615. pIpAdapterAddressesCurrent = pIpAdapterAddresses;
  2616. while (pIpAdapterAddressesCurrent != NULL)
  2617. {
  2618. pIpAdapterUnicastAddressCurrent = pIpAdapterAddressesCurrent->FirstUnicastAddress;
  2619. while (pIpAdapterUnicastAddressCurrent != NULL)
  2620. {
  2621. if (pIpAdapterUnicastAddressCurrent->DadState == IpDadStatePreferred)
  2622. {
  2623. //
  2624. // Insert IPv6 adapters in the first half of the array, IPv4 in the second half.
  2625. //
  2626. if (pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family == AF_INET6)
  2627. {
  2628. SOCKADDR_IN6 * psaddrin6;
  2629. psaddrin6 = (SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr;
  2630. //
  2631. // Skip the loopback pseudo-interface as described earlier.
  2632. //
  2633. if (IN6_IS_ADDR_LOOPBACK(&psaddrin6->sin6_addr))
  2634. {
  2635. break;
  2636. }
  2637. //
  2638. // Save the pointers in the current slot.
  2639. //
  2640. paSortAdapterAddress[dwNumIPv6Addresses].psockaddr = (SOCKADDR*) psaddrin6;
  2641. if (pIpAdapterAddressesCurrent->FriendlyName != NULL)
  2642. {
  2643. paSortAdapterAddress[dwNumIPv6Addresses].pwszDescription = pIpAdapterAddressesCurrent->FriendlyName;
  2644. }
  2645. else
  2646. {
  2647. if (pIpAdapterAddressesCurrent->Description != NULL)
  2648. {
  2649. paSortAdapterAddress[dwNumIPv6Addresses].pwszDescription = pIpAdapterAddressesCurrent->Description;
  2650. }
  2651. }
  2652. DNASSERT(dwNumIPv6Addresses < dwTotalNumIPv6Addresses);
  2653. dwNumIPv6Addresses++;
  2654. }
  2655. else
  2656. {
  2657. DNASSERT(pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family == AF_INET);
  2658. if ((((SOCKADDR_IN*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin_addr.S_un.S_addr != IP_LOOPBACK_ADDRESS) ||
  2659. (! fSkipIPv4Loopback))
  2660. {
  2661. //
  2662. // If this looks like an ICS private adapter and there are other adapters, put it first,
  2663. // otherwise add to the end.
  2664. //
  2665. if ((((SOCKADDR_IN*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin_addr.S_un.S_addr == IP_PRIVATEICS_ADDRESS) &&
  2666. (dwNumIPv4Addresses > 0))
  2667. {
  2668. //
  2669. // Move all existing entries down one.
  2670. //
  2671. for(dwTemp = dwTotalNumIPv6Addresses + dwNumIPv4Addresses; dwTemp > dwTotalNumIPv6Addresses; dwTemp--)
  2672. {
  2673. memcpy(&paSortAdapterAddress[dwTemp],
  2674. &paSortAdapterAddress[dwTemp - 1],
  2675. sizeof(SORTADAPTERADDRESS));
  2676. }
  2677. //
  2678. // Add this new entry at the start of the IPv4 addresses.
  2679. //
  2680. paSortAdapterAddress[dwTotalNumIPv6Addresses].psockaddr = pIpAdapterUnicastAddressCurrent->Address.lpSockaddr;
  2681. if (pIpAdapterAddressesCurrent->FriendlyName != NULL)
  2682. {
  2683. paSortAdapterAddress[dwTotalNumIPv6Addresses].pwszDescription = pIpAdapterAddressesCurrent->FriendlyName;
  2684. }
  2685. else
  2686. {
  2687. if (pIpAdapterAddressesCurrent->Description != NULL)
  2688. {
  2689. paSortAdapterAddress[dwTotalNumIPv6Addresses].pwszDescription = pIpAdapterAddressesCurrent->Description;
  2690. }
  2691. }
  2692. }
  2693. else
  2694. {
  2695. //
  2696. // Add this entry at the current IPv4 address slot.
  2697. //
  2698. paSortAdapterAddress[dwTotalNumIPv6Addresses + dwNumIPv4Addresses].psockaddr = pIpAdapterUnicastAddressCurrent->Address.lpSockaddr;
  2699. if (pIpAdapterAddressesCurrent->FriendlyName != NULL)
  2700. {
  2701. paSortAdapterAddress[dwTotalNumIPv6Addresses + dwNumIPv4Addresses].pwszDescription = pIpAdapterAddressesCurrent->FriendlyName;
  2702. }
  2703. else
  2704. {
  2705. if (pIpAdapterAddressesCurrent->Description != NULL)
  2706. {
  2707. paSortAdapterAddress[dwTotalNumIPv6Addresses + dwNumIPv4Addresses].pwszDescription = pIpAdapterAddressesCurrent->Description;
  2708. }
  2709. }
  2710. }
  2711. DNASSERT(dwNumIPv4Addresses < dwTotalNumIPv4Addresses);
  2712. dwNumIPv4Addresses++;
  2713. }
  2714. else
  2715. {
  2716. //
  2717. // Skip the IPv4 loopback address.
  2718. //
  2719. }
  2720. }
  2721. }
  2722. else
  2723. {
  2724. //
  2725. // Deprecated or otherwise non-preferred address.
  2726. //
  2727. }
  2728. pIpAdapterUnicastAddressCurrent = pIpAdapterUnicastAddressCurrent->Next;
  2729. }
  2730. pIpAdapterAddressesCurrent = pIpAdapterAddressesCurrent->Next;
  2731. }
  2732. }
  2733. //
  2734. // Finally loop through the sorted adapters and store them in the buffer (or get size needed).
  2735. //
  2736. for(dwTemp = 0; dwTemp < dwTotalNumIPv6Addresses + dwTotalNumIPv4Addresses; dwTemp++)
  2737. {
  2738. //
  2739. // Start off assuming this IP address won't have any special
  2740. // flags.
  2741. //
  2742. dwDeviceFlags = 0;
  2743. #pragma BUGBUG(vanceo, "Move to appropriate location so that turning on DPNBUILD_NOMULTICAST doesn't break")
  2744. /*
  2745. #ifndef DPNBUILD_NOMULTICAST
  2746. //
  2747. // If this is the first device and we couldn't use IPHLPAPI to
  2748. // determine the best multicast interface, then just say the
  2749. // default multicast interface is the first (for lack of a
  2750. // better idea).
  2751. //
  2752. #ifdef DPNBUILD_NOWINSOCK2
  2753. if (dwIndex == 0)
  2754. #else // ! DPNBUILD_NOWINSOCK2
  2755. if ((dwIndex == 0) && (dwMcastInterfaceIndex == INVALID_INTERFACE_INDEX))
  2756. #endif // ! DPNBUILD_NOWINSOCK2
  2757. {
  2758. dwDeviceFlags |= DPNSPINFO_DEFAULTMULTICASTDEVICE;
  2759. }
  2760. #endif // ! DPNBUILD_NOMULTICAST
  2761. */
  2762. //
  2763. // Create a string representation of the IP address and generate the name.
  2764. //
  2765. if (paSortAdapterAddress[dwTemp].psockaddr->sa_family == AF_INET6)
  2766. {
  2767. DNIpv6AddressToStringW(&((SOCKADDR_IN6*) paSortAdapterAddress[dwTemp].psockaddr)->sin6_addr,
  2768. wszIPAddress);
  2769. if (paSortAdapterAddress[dwTemp].pwszDescription != NULL)
  2770. {
  2771. wsprintfW(pwszBuffer,
  2772. c_wszIPv6AdapterNameTemplate,
  2773. paSortAdapterAddress[dwTemp].pwszDescription,
  2774. wszIPAddress);
  2775. }
  2776. else
  2777. {
  2778. wsprintfW(pwszBuffer,
  2779. c_wszIPv6AdapterNameNoDescTemplate,
  2780. wszIPAddress);
  2781. }
  2782. }
  2783. else
  2784. {
  2785. DNinet_ntow(((SOCKADDR_IN*) paSortAdapterAddress[dwTemp].psockaddr)->sin_addr,
  2786. wszIPAddress);
  2787. if (paSortAdapterAddress[dwTemp].pwszDescription != NULL)
  2788. {
  2789. wsprintfW(pwszBuffer,
  2790. c_wszIPv4AdapterNameTemplate,
  2791. paSortAdapterAddress[dwTemp].pwszDescription,
  2792. wszIPAddress);
  2793. }
  2794. else
  2795. {
  2796. wsprintfW(pwszBuffer,
  2797. c_wszIPv4AdapterNameNoDescTemplate,
  2798. wszIPAddress);
  2799. }
  2800. }
  2801. //
  2802. // Generate the GUID.
  2803. //
  2804. GuidFromAddress(&guidAdapter, paSortAdapterAddress[dwTemp].psockaddr);
  2805. DPFX(DPFPREP, 7, "Returning adapter %u: \"%ls\" {%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}, flags = 0x%lx.",
  2806. dwTemp,
  2807. pwszBuffer,
  2808. guidAdapter.Data1,
  2809. guidAdapter.Data2,
  2810. guidAdapter.Data3,
  2811. guidAdapter.Data4[0],
  2812. guidAdapter.Data4[1],
  2813. guidAdapter.Data4[2],
  2814. guidAdapter.Data4[3],
  2815. guidAdapter.Data4[4],
  2816. guidAdapter.Data4[5],
  2817. guidAdapter.Data4[6],
  2818. guidAdapter.Data4[7],
  2819. dwDeviceFlags);
  2820. //
  2821. // Add adapter to buffer.
  2822. //
  2823. hr = AddInfoToBuffer(&PackedBuffer, pwszBuffer, &guidAdapter, dwDeviceFlags);
  2824. if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
  2825. {
  2826. DPFX(DPFPREP, 0, "Failed to add adapter to buffer (err = 0x%lx)!", hr);
  2827. DisplayDNError( 0, hr );
  2828. goto Failure;
  2829. }
  2830. }
  2831. //
  2832. // If we're here, we successfully built the list of adapters, although
  2833. // the caller may not have given us enough buffer space to store it.
  2834. //
  2835. pEnumData->dwAdapterCount = dwTotalNumIPv6Addresses + dwTotalNumIPv4Addresses;
  2836. pEnumData->dwAdapterDataSize = PackedBuffer.GetSizeRequired();
  2837. Exit:
  2838. if (paSortAdapterAddress != NULL)
  2839. {
  2840. DNFree(paSortAdapterAddress);
  2841. paSortAdapterAddress = NULL;
  2842. }
  2843. if (pwszBuffer != NULL)
  2844. {
  2845. DNFree(pwszBuffer);
  2846. pwszBuffer = NULL;
  2847. }
  2848. if (pIpAdapterAddresses != NULL)
  2849. {
  2850. DNFree(pIpAdapterAddresses);
  2851. pIpAdapterAddresses = NULL;
  2852. }
  2853. if (hIpHlpApiDLL != NULL)
  2854. {
  2855. FreeLibrary(hIpHlpApiDLL);
  2856. hIpHlpApiDLL = NULL;
  2857. }
  2858. DPFX(DPFPREP, 6, "Return [0x%lx]", hr);
  2859. return hr;
  2860. Failure:
  2861. goto Exit;
  2862. }
  2863. //**********************************************************************
  2864. #endif // ! DPNBUILD_NOIPV6
  2865. #endif // ! DPNBUILD_ONLYONEADAPTER
  2866. #ifndef DPNBUILD_NOMULTICAST
  2867. //**********************************************************************
  2868. // ------------------------------
  2869. // CSocketAddress::EnumMulticastScopes - enumerate all multicast scopes for an adapter
  2870. //
  2871. // Entry: Pointer to enum multicast scopes data
  2872. //
  2873. // Exit: Error code
  2874. // ------------------------------
  2875. #undef DPF_MODNAME
  2876. #define DPF_MODNAME "CSocketAddress::EnumMulticastScopes"
  2877. HRESULT CSocketAddress::EnumMulticastScopes( SPENUMMULTICASTSCOPESDATA *const pEnumData, BOOL const fUseMADCAP ) const
  2878. {
  2879. HRESULT hr;
  2880. CPackedBuffer PackedBuffer;
  2881. #ifdef DPNBUILD_NOIPV6
  2882. SOCKADDR saddrAdapter;
  2883. #else // ! DPNBUILD_NOIPV6
  2884. SOCKADDR_STORAGE saddrAdapter;
  2885. #endif // ! DPNBUILD_NOIPV6
  2886. SOCKET sTemp = INVALID_SOCKET;
  2887. DWORD dwScopeCount = 0;
  2888. #ifdef DBG
  2889. DWORD dwError;
  2890. #endif // DBG
  2891. DPFX(DPFPREP, 6, "Parameters: (0x%p, %i)", pEnumData, fUseMADCAP);
  2892. PackedBuffer.Initialize(pEnumData->pScopeData, pEnumData->dwScopeDataSize);
  2893. #pragma TODO(vanceo, "Make IPv6 ready")
  2894. AddressFromGuid(pEnumData->pguidAdapter, &saddrAdapter);
  2895. //
  2896. // Make sure the adapter is valid by asking WinSock.
  2897. //
  2898. sTemp = socket(GetFamily(), SOCK_DGRAM, IPPROTO_UDP);
  2899. if (sTemp == INVALID_SOCKET)
  2900. {
  2901. #ifdef DBG
  2902. dwError = WSAGetLastError();
  2903. DPFX(DPFPREP, 0, "Couldn't create temporary UDP socket (err = %u)!", dwError);
  2904. DNASSERT(FALSE);
  2905. #endif // DBG
  2906. hr = DPNERR_GENERIC;
  2907. goto Failure;
  2908. }
  2909. #ifndef DPNBUILD_NOIPV6
  2910. if (saddrAdapter.ss_family == AF_INET6)
  2911. {
  2912. saddrAdapter.ss_family = GetFamily();
  2913. #pragma TODO(vanceo, "Make IPv6 ready")
  2914. }
  2915. else
  2916. #endif // ! DPNBUILD_NOIPV6
  2917. {
  2918. ((SOCKADDR_IN*) (&saddrAdapter))->sin_family = GetFamily();
  2919. ((SOCKADDR_IN*) (&saddrAdapter))->sin_port = ANY_PORT;
  2920. }
  2921. if (bind(sTemp, (SOCKADDR*) (&saddrAdapter), sizeof(saddrAdapter)) != 0)
  2922. {
  2923. #ifdef DBG
  2924. dwError = WSAGetLastError();
  2925. DPFX(DPFPREP, 0, "Adapter GUID is invalid (err = %u)!", dwError);
  2926. DisplayWinsockError(0, dwError);
  2927. DNASSERT(dwError == WSAEADDRNOTAVAIL);
  2928. #endif // DBG
  2929. hr = DPNERR_INVALIDDEVICEADDRESS;
  2930. goto Failure;
  2931. }
  2932. closesocket(sTemp);
  2933. sTemp = INVALID_SOCKET;
  2934. //
  2935. // The adapter is valid. First, fill in the 3 default multicast scopes.
  2936. //
  2937. hr = AddInfoToBuffer(&PackedBuffer, c_wszPrivateScopeString, &GUID_DP8MULTICASTSCOPE_PRIVATE, 0);
  2938. if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
  2939. {
  2940. DPFX(DPFPREP, 0, "Failed to add private scope to buffer (err = 0x%lx)!", hr);
  2941. DisplayDNError(0, hr);
  2942. goto Failure;
  2943. }
  2944. DPFX(DPFPREP, 7, "Returning scope %u: \"%ls\" {%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}.",
  2945. dwScopeCount,
  2946. c_wszPrivateScopeString,
  2947. GUID_DP8MULTICASTSCOPE_PRIVATE.Data1,
  2948. GUID_DP8MULTICASTSCOPE_PRIVATE.Data2,
  2949. GUID_DP8MULTICASTSCOPE_PRIVATE.Data3,
  2950. GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[0],
  2951. GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[1],
  2952. GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[2],
  2953. GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[3],
  2954. GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[4],
  2955. GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[5],
  2956. GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[6],
  2957. GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[7]);
  2958. dwScopeCount++;
  2959. hr = AddInfoToBuffer(&PackedBuffer, c_wszLocalScopeString, &GUID_DP8MULTICASTSCOPE_LOCAL, 0);
  2960. if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
  2961. {
  2962. DPFX(DPFPREP, 0, "Failed to add local scope to buffer (err = 0x%lx)!", hr);
  2963. DisplayDNError(0, hr);
  2964. goto Failure;
  2965. }
  2966. DPFX(DPFPREP, 7, "Returning scope %u: \"%ls\" {%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}.",
  2967. dwScopeCount,
  2968. c_wszLocalScopeString,
  2969. GUID_DP8MULTICASTSCOPE_LOCAL.Data1,
  2970. GUID_DP8MULTICASTSCOPE_LOCAL.Data2,
  2971. GUID_DP8MULTICASTSCOPE_LOCAL.Data3,
  2972. GUID_DP8MULTICASTSCOPE_LOCAL.Data4[0],
  2973. GUID_DP8MULTICASTSCOPE_LOCAL.Data4[1],
  2974. GUID_DP8MULTICASTSCOPE_LOCAL.Data4[2],
  2975. GUID_DP8MULTICASTSCOPE_LOCAL.Data4[3],
  2976. GUID_DP8MULTICASTSCOPE_LOCAL.Data4[4],
  2977. GUID_DP8MULTICASTSCOPE_LOCAL.Data4[5],
  2978. GUID_DP8MULTICASTSCOPE_LOCAL.Data4[6],
  2979. GUID_DP8MULTICASTSCOPE_LOCAL.Data4[7]);
  2980. dwScopeCount++;
  2981. hr = AddInfoToBuffer(&PackedBuffer, c_wszGlobalScopeString, &GUID_DP8MULTICASTSCOPE_GLOBAL, 0);
  2982. if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
  2983. {
  2984. DPFX(DPFPREP, 0, "Failed to add global scope to buffer (err = 0x%lx)!", hr);
  2985. DisplayDNError(0, hr);
  2986. goto Failure;
  2987. }
  2988. DPFX(DPFPREP, 7, "Returning scope %u: \"%ls\" {%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}.",
  2989. dwScopeCount,
  2990. c_wszGlobalScopeString,
  2991. GUID_DP8MULTICASTSCOPE_GLOBAL.Data1,
  2992. GUID_DP8MULTICASTSCOPE_GLOBAL.Data2,
  2993. GUID_DP8MULTICASTSCOPE_GLOBAL.Data3,
  2994. GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[0],
  2995. GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[1],
  2996. GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[2],
  2997. GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[3],
  2998. GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[4],
  2999. GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[5],
  3000. GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[6],
  3001. GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[7]);
  3002. dwScopeCount++;
  3003. //
  3004. // If this platform supports MADCAP, retrieve its list of scopes for
  3005. // this adapter.
  3006. // NOTE: This assumes MADCAP has been loaded by the thread pool
  3007. // already.
  3008. //
  3009. #ifdef WINNT
  3010. if (fUseMADCAP)
  3011. {
  3012. #ifndef DBG
  3013. DWORD dwError;
  3014. #endif // ! DBG
  3015. PMCAST_SCOPE_ENTRY paScopes = NULL;
  3016. DWORD dwScopesSize = 0;
  3017. DWORD dwNumScopeEntries;
  3018. DWORD dwTemp;
  3019. WCHAR * pwszScratch;
  3020. GUID guidScope;
  3021. //
  3022. // Determine how much room we need to hold the list of scopes.
  3023. //
  3024. dwError = McastEnumerateScopes(GetFamily(),
  3025. TRUE,
  3026. NULL,
  3027. &dwScopesSize,
  3028. &dwNumScopeEntries);
  3029. if (((dwError == ERROR_SUCCESS) || (dwError == ERROR_MORE_DATA)) &&
  3030. (dwScopesSize >= sizeof(MCAST_SCOPE_ENTRY)) &&
  3031. (dwNumScopeEntries > 0))
  3032. {
  3033. //
  3034. // We want to add " - TTL xxx" to every string entry, so allocate
  3035. // enough extra room for a scratch buffer for the largest possible
  3036. // string plus that extra information.
  3037. //
  3038. dwTemp = dwScopesSize - (dwNumScopeEntries * sizeof(MCAST_SCOPE_ENTRY)) + (10 * sizeof(WCHAR));
  3039. paScopes = (PMCAST_SCOPE_ENTRY) DNMalloc(dwScopesSize + dwTemp);
  3040. if (paScopes != NULL)
  3041. {
  3042. pwszScratch = (WCHAR*) (((BYTE*) (paScopes)) + dwScopesSize);
  3043. //
  3044. // Retrieve the list of scopes.
  3045. //
  3046. dwError = McastEnumerateScopes(GetFamily(),
  3047. FALSE,
  3048. paScopes,
  3049. &dwScopesSize,
  3050. &dwNumScopeEntries);
  3051. if ((dwError == ERROR_SUCCESS) &&
  3052. (dwScopesSize >= sizeof(MCAST_SCOPE_ENTRY)) &&
  3053. (dwNumScopeEntries > 0))
  3054. {
  3055. //
  3056. // Look for scopes that match the device we were given.
  3057. //
  3058. for(dwTemp = 0; dwTemp < dwNumScopeEntries; dwTemp++)
  3059. {
  3060. BOOL fResult;
  3061. #ifndef DPNBUILD_NOIPV6
  3062. if (GetFamily() == AF_INET6)
  3063. {
  3064. if (memcmp(&paScopes[dwTemp].ScopeCtx.Interface.IpAddrV6, &(((SOCKADDR_IN6*) (&saddrAdapter))->sin6_addr), sizeof(paScopes[dwTemp].ScopeCtx.Interface.IpAddrV6)) == 0)
  3065. {
  3066. fResult = TRUE;
  3067. }
  3068. else
  3069. {
  3070. fResult = FALSE;
  3071. }
  3072. }
  3073. else
  3074. #endif // ! DPNBUILD_NOIPV6
  3075. {
  3076. if (paScopes[dwTemp].ScopeCtx.Interface.IpAddrV4 == ((SOCKADDR_IN*) (&saddrAdapter))->sin_addr.S_un.S_addr)
  3077. {
  3078. fResult = TRUE;
  3079. }
  3080. else
  3081. {
  3082. fResult = FALSE;
  3083. }
  3084. }
  3085. if (fResult)
  3086. {
  3087. //
  3088. // Encrypt the scope context and TTL as a GUID.
  3089. //
  3090. #ifdef DPNBUILD_NOIPV6
  3091. CSocketAddress::CreateScopeGuid(&(paScopes[dwTemp].ScopeCtx),
  3092. #else // ! DPNBUILD_NOIPV6
  3093. CSocketAddress::CreateScopeGuid(GetFamily(),
  3094. &(paScopes[dwTemp].ScopeCtx),
  3095. #endif // ! DPNBUILD_NOIPV6
  3096. (BYTE) (paScopes[dwTemp].TTL),
  3097. &guidScope);
  3098. //
  3099. // Use the scratch space at the end of our buffer to
  3100. // append " - TTL xxx" to the description string.
  3101. //
  3102. wsprintfW(pwszScratch, L"%ls - TTL %u",
  3103. paScopes[dwTemp].ScopeDesc.Buffer,
  3104. (BYTE) (paScopes[dwTemp].TTL));
  3105. hr = AddInfoToBuffer(&PackedBuffer, pwszScratch, &guidScope, 0);
  3106. if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
  3107. {
  3108. DPFX(DPFPREP, 0, "Failed to add scope \"%ls\" to buffer (err = 0x%lx)!",
  3109. pwszScratch, hr);
  3110. DisplayDNError(0, hr);
  3111. DNFree(paScopes);
  3112. paScopes = NULL;
  3113. goto Failure;
  3114. }
  3115. DPFX(DPFPREP, 7, "Returning scope %u: \"%ls\" {%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}.",
  3116. dwScopeCount,
  3117. pwszScratch,
  3118. guidScope.Data1,
  3119. guidScope.Data2,
  3120. guidScope.Data3,
  3121. guidScope.Data4[0],
  3122. guidScope.Data4[1],
  3123. guidScope.Data4[2],
  3124. guidScope.Data4[3],
  3125. guidScope.Data4[4],
  3126. guidScope.Data4[5],
  3127. guidScope.Data4[6],
  3128. guidScope.Data4[7]);
  3129. dwScopeCount++;
  3130. }
  3131. else
  3132. {
  3133. DPFX(DPFPREP, 7, "Ignoring scope \"%ls - TTL %u\" for different adapter.",
  3134. paScopes[dwTemp].ScopeDesc.Buffer, paScopes[dwTemp].TTL);
  3135. }
  3136. }
  3137. }
  3138. else
  3139. {
  3140. DPFX(DPFPREP, 0, "Failed enumerating MADCAP scopes (err = %u, size %u, expected size %u, count %u)! Ignoring.",
  3141. dwError, dwScopesSize, sizeof(MCAST_SCOPE_ENTRY), dwNumScopeEntries);
  3142. }
  3143. DNFree(paScopes);
  3144. paScopes = NULL;
  3145. }
  3146. else
  3147. {
  3148. DPFX(DPFPREP, 0, "Failed allocating memory for MADCAP scopes! Ignoring.");
  3149. }
  3150. }
  3151. else
  3152. {
  3153. DPFX(DPFPREP, 0, "Enumerating scopes for size required didn't return expected error or size (err = %u, size %u, expected size %u, count %u)! Ignoring.",
  3154. dwError, dwScopesSize, sizeof(MCAST_SCOPE_ENTRY), dwNumScopeEntries);
  3155. }
  3156. } // end if (MADCAP should be used)
  3157. else
  3158. {
  3159. DPFX(DPFPREP, 7, "Not enumerating MADCAP scopes.");
  3160. }
  3161. #endif // WINNT
  3162. //
  3163. // If we're here, we successfully built the list of adapters, although
  3164. // the caller may not have given us enough buffer space to store it.
  3165. //
  3166. pEnumData->dwScopeCount = dwScopeCount;
  3167. pEnumData->dwScopeDataSize = PackedBuffer.GetSizeRequired();
  3168. Exit:
  3169. DPFX(DPFPREP, 6, "Returning: [0x%lx]", hr);
  3170. return hr;
  3171. Failure:
  3172. if (sTemp != INVALID_SOCKET)
  3173. {
  3174. closesocket(sTemp);
  3175. sTemp = INVALID_SOCKET;
  3176. }
  3177. goto Exit;
  3178. }
  3179. //**********************************************************************
  3180. //**********************************************************************
  3181. // ------------------------------
  3182. // CSocketAddress::SocketAddressFromMulticastDP8Address - convert a multicast style DP8Address into a socket address (may not be complete)
  3183. //
  3184. // Entry: Pointer to DP8Address
  3185. // Place to store scope GUID.
  3186. //
  3187. // Exit: Error code
  3188. // ------------------------------
  3189. #undef DPF_MODNAME
  3190. #define DPF_MODNAME "CSocketAddress::SocketAddressFromMulticastDP8Address"
  3191. HRESULT CSocketAddress::SocketAddressFromMulticastDP8Address( IDirectPlay8Address *const pDP8Address,
  3192. #ifdef DPNBUILD_XNETSECURITY
  3193. ULONGLONG * const pullKeyID,
  3194. #endif // DPNBUILD_XNETSECURITY
  3195. GUID * const pScopeGuid )
  3196. {
  3197. HRESULT hr;
  3198. WCHAR wszMulticastAddress[16]; // nnn.nnn.nnn.nnn + NULL termination
  3199. char szMulticastAddress[16]; // nnn.nnn.nnn.nnn + NULL termination
  3200. DWORD dwSize;
  3201. DWORD dwDataType;
  3202. DWORD dwPort;
  3203. DNASSERT(pDP8Address != NULL);
  3204. #ifdef DPNBUILD_XNETSECURITY
  3205. #error ("Multicast doesn't currently support secure transport!")
  3206. #endif // DPNBUILD_XNETSECURITY
  3207. //
  3208. // Get the multicast IP address, if it's there.
  3209. //
  3210. dwSize = sizeof(wszMulticastAddress);
  3211. hr = IDirectPlay8Address_GetComponentByName(pDP8Address,
  3212. DPNA_KEY_HOSTNAME,
  3213. wszMulticastAddress,
  3214. &dwSize,
  3215. &dwDataType);
  3216. if (hr == DPN_OK)
  3217. {
  3218. switch (dwDataType)
  3219. {
  3220. case DPNA_DATATYPE_STRING:
  3221. {
  3222. STR_jkWideToAnsi(szMulticastAddress,
  3223. wszMulticastAddress,
  3224. (sizeof(szMulticastAddress) / sizeof(char)));
  3225. break;
  3226. }
  3227. case DPNA_DATATYPE_STRING_ANSI:
  3228. {
  3229. DWORD dwStrSize;
  3230. //
  3231. // For some reason, addressing returned the string as ANSI,
  3232. // not Unicode. Not sure why this would happen, but go
  3233. // ahead and convert it.
  3234. // First make sure it's a reasonable size.
  3235. // If you're wondering about the funkiness of this copying,
  3236. // it's because PREfast goes a little overboard...
  3237. //
  3238. dwStrSize = (strlen((char*) wszMulticastAddress) + 1) * sizeof(char);
  3239. DNASSERT(dwStrSize == dwSize);
  3240. if (dwStrSize > (sizeof(szMulticastAddress) / sizeof(char)))
  3241. {
  3242. DPFX(DPFPREP, 0, "Unexpectedly long ANSI hostname string (%u bytes)!", dwStrSize);
  3243. hr = DPNERR_INVALIDADDRESSFORMAT;
  3244. goto Failure;
  3245. }
  3246. memcpy(szMulticastAddress, (char*) wszMulticastAddress, dwStrSize);
  3247. break;
  3248. }
  3249. default:
  3250. {
  3251. DPFX(DPFPREP, 0, "Unexpected data type %u for hostname component!", dwDataType);
  3252. hr = DPNERR_INVALIDADDRESSFORMAT;
  3253. goto Failure;
  3254. break;
  3255. }
  3256. }
  3257. //
  3258. // Convert the IP address string into an address.
  3259. //
  3260. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = inet_addr(szMulticastAddress);
  3261. //
  3262. // Make sure it's a valid multicast IP address.
  3263. //
  3264. if (! (IS_CLASSD_IPV4_ADDRESS(m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr)))
  3265. {
  3266. DPFX(DPFPREP, 0, "Hostname component \"%hs\" does not resolve to valid multicast IP address!",
  3267. szMulticastAddress);
  3268. hr = DPNERR_INVALIDHOSTADDRESS;
  3269. goto Failure;
  3270. }
  3271. }
  3272. else
  3273. {
  3274. DPFX(DPFPREP, 3, "Address didn't contain multicast hostname (err = 0x%lx).", hr);
  3275. DNASSERT(m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_ANY);
  3276. }
  3277. //
  3278. // Get the multicast port, if it's there.
  3279. //
  3280. dwSize = sizeof(dwPort);
  3281. hr = IDirectPlay8Address_GetComponentByName(pDP8Address,
  3282. DPNA_KEY_PORT,
  3283. &dwPort,
  3284. &dwSize,
  3285. &dwDataType);
  3286. if (hr == DPN_OK)
  3287. {
  3288. if (dwDataType != DPNA_DATATYPE_DWORD)
  3289. {
  3290. DPFX(DPFPREP, 0, "Unexpected data type %u for port component!", dwDataType);
  3291. hr = DPNERR_INVALIDADDRESSFORMAT;
  3292. goto Failure;
  3293. }
  3294. m_SocketAddress.IPSocketAddress.sin_port = HTONS((WORD) dwPort);
  3295. }
  3296. else
  3297. {
  3298. DPFX(DPFPREP, 3, "Address didn't contain multicast port (err = 0x%lx).", hr);
  3299. DNASSERT(m_SocketAddress.IPSocketAddress.sin_port == ANY_PORT);
  3300. }
  3301. //
  3302. // Get the multicast scope, if it's there.
  3303. //
  3304. dwSize = sizeof(*pScopeGuid);
  3305. hr = IDirectPlay8Address_GetComponentByName(pDP8Address,
  3306. DPNA_KEY_SCOPE,
  3307. pScopeGuid,
  3308. &dwSize,
  3309. &dwDataType);
  3310. if (hr == DPN_OK)
  3311. {
  3312. if (dwDataType != DPNA_DATATYPE_GUID)
  3313. {
  3314. DPFX(DPFPREP, 0, "Unexpected data type %u for scope component!", dwDataType);
  3315. hr = DPNERR_INVALIDADDRESSFORMAT;
  3316. goto Failure;
  3317. }
  3318. }
  3319. else
  3320. {
  3321. DPFX(DPFPREP, 3, "Address didn't contain multicast scope (err = 0x%lx), using private scope.", hr);
  3322. memcpy(pScopeGuid, &GUID_DP8MULTICASTSCOPE_PRIVATE, sizeof(*pScopeGuid));
  3323. }
  3324. hr = DPN_OK;
  3325. Exit:
  3326. return hr;
  3327. Failure:
  3328. goto Exit;
  3329. }
  3330. //**********************************************************************
  3331. #endif // ! DPNBUILD_NOMULTICAST
  3332. //**********************************************************************
  3333. // ------------------------------
  3334. // CSocketAddress::CompareFunction - compare against another address
  3335. //
  3336. // Entry: Pointer to other address
  3337. //
  3338. // Exit: Bool indicating equality of two addresses
  3339. // ------------------------------
  3340. #undef DPF_MODNAME
  3341. #define DPF_MODNAME "CSocketAddress::CompareFunction"
  3342. BOOL CSocketAddress::CompareFunction( PVOID pvKey1, PVOID pvKey2 )
  3343. {
  3344. CSocketAddress* pAddress1 = (CSocketAddress*)pvKey1;
  3345. CSocketAddress* pAddress2 = (CSocketAddress*)pvKey2;
  3346. DNASSERT(pAddress1 != NULL);
  3347. DNASSERT(pAddress2 != NULL);
  3348. DNASSERT(pAddress1->GetFamily() == pAddress2->GetFamily());
  3349. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3350. switch (pAddress1->GetFamily())
  3351. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3352. {
  3353. #ifndef DPNBUILD_NOIPV6
  3354. case AF_INET6:
  3355. {
  3356. //
  3357. // we need to compare the IPv6 address and port to guarantee uniqueness
  3358. //
  3359. if (IN6_ADDR_EQUAL(&(pAddress1->m_SocketAddress.IPv6SocketAddress.sin6_addr),
  3360. &(pAddress2->m_SocketAddress.IPv6SocketAddress.sin6_addr)))
  3361. {
  3362. if ( pAddress1->m_SocketAddress.IPv6SocketAddress.sin6_port ==
  3363. pAddress2->m_SocketAddress.IPv6SocketAddress.sin6_port )
  3364. {
  3365. return TRUE;
  3366. }
  3367. }
  3368. return FALSE;
  3369. break;
  3370. }
  3371. #endif // ! DPNBUILD_NOIPV6
  3372. #ifndef DPNBUILD_NOIPX
  3373. case AF_IPX:
  3374. {
  3375. //
  3376. // We only need to compare:
  3377. // netnumber (IPX network address) [ 4 bytes ]
  3378. // nodenumber (netcard adapter address) [ 6 bytes ]
  3379. // port [ 2 bytes ]
  3380. //
  3381. // Note that the nodenumber and port fields are sequentially arranged in the
  3382. // address structure and can be compared with DWORDs
  3383. //
  3384. DBG_CASSERT( OFFSETOF( SOCKADDR_IPX, sa_nodenum ) == ( OFFSETOF( SOCKADDR_IPX, sa_netnum ) + sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_netnum ) ) );
  3385. DBG_CASSERT( OFFSETOF( SOCKADDR_IPX, sa_socket ) == ( OFFSETOF( SOCKADDR_IPX, sa_nodenum ) + sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_nodenum ) ) );
  3386. return memcmp( &pAddress1->m_SocketAddress.IPXSocketAddress.sa_netnum,
  3387. pAddress2->m_SocketAddress.IPXSocketAddress.sa_netnum,
  3388. ( sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_netnum ) +
  3389. sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_nodenum ) +
  3390. sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_socket ) ) ) == 0;
  3391. break;
  3392. }
  3393. #endif // ! DPNBUILD_NOIPX
  3394. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3395. default:
  3396. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3397. {
  3398. DNASSERT(pAddress1->GetFamily() == AF_INET);
  3399. //
  3400. // we need to compare the IP address and port to guarantee uniqueness
  3401. //
  3402. if ( pAddress1->m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr ==
  3403. pAddress2->m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr )
  3404. {
  3405. if ( pAddress1->m_SocketAddress.IPSocketAddress.sin_port ==
  3406. pAddress2->m_SocketAddress.IPSocketAddress.sin_port )
  3407. {
  3408. return TRUE;
  3409. }
  3410. }
  3411. return FALSE;
  3412. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3413. break;
  3414. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3415. }
  3416. }
  3417. }
  3418. //**********************************************************************
  3419. //**********************************************************************
  3420. // ------------------------------
  3421. // CSocketAddress::HashFunction - hash address to N bits
  3422. //
  3423. // Entry: Count of bits to hash to
  3424. //
  3425. // Exit: Hashed value
  3426. // ------------------------------
  3427. #undef DPF_MODNAME
  3428. #define DPF_MODNAME "CSocketAddress::HashFunction"
  3429. DWORD CSocketAddress::HashFunction( PVOID pvKey, BYTE bBitDepth )
  3430. {
  3431. DWORD dwReturn;
  3432. UINT_PTR Temp;
  3433. CSocketAddress* pAddress = (CSocketAddress*) pvKey;
  3434. DNASSERT( bBitDepth != 0 );
  3435. DNASSERT( bBitDepth < 32 );
  3436. //
  3437. // initialize
  3438. //
  3439. dwReturn = 0;
  3440. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3441. switch (pAddress->GetFamily())
  3442. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3443. {
  3444. #ifndef DPNBUILD_NOIPV6
  3445. case AF_INET6:
  3446. {
  3447. DWORD dwTemp;
  3448. //
  3449. // hash IPv6 address
  3450. //
  3451. for(dwTemp = 0; dwTemp < (sizeof(pAddress->m_SocketAddress.IPv6SocketAddress.sin6_addr) / sizeof(UINT_PTR)); dwTemp++)
  3452. {
  3453. Temp = ((UINT_PTR*) (&pAddress->m_SocketAddress.IPv6SocketAddress.sin6_addr))[dwTemp];
  3454. do
  3455. {
  3456. dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
  3457. Temp >>= bBitDepth;
  3458. } while ( Temp != 0 );
  3459. }
  3460. //
  3461. // hash IPv6 port
  3462. //
  3463. Temp = pAddress->m_SocketAddress.IPv6SocketAddress.sin6_port;
  3464. do
  3465. {
  3466. dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
  3467. Temp >>= bBitDepth;
  3468. } while ( Temp != 0 );
  3469. break;
  3470. }
  3471. #endif // ! DPNBUILD_NOIPV6
  3472. #ifndef DPNBUILD_NOIPX
  3473. case AF_IPX:
  3474. {
  3475. //
  3476. // hash first DWORD of IPX address
  3477. //
  3478. Temp = *reinterpret_cast<const DWORD*>( &pAddress->m_SocketAddress.IPXSocketAddress.sa_nodenum[ 0 ] );
  3479. do
  3480. {
  3481. dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
  3482. Temp >>= bBitDepth;
  3483. } while ( Temp != 0 );
  3484. //
  3485. // hash second DWORD of IPX address and IPX socket
  3486. //
  3487. Temp = *reinterpret_cast<const WORD*>( &pAddress->m_SocketAddress.IPXSocketAddress.sa_nodenum[ sizeof( DWORD ) ] );
  3488. Temp += ( pAddress->m_SocketAddress.IPXSocketAddress.sa_socket << ( sizeof( WORD ) * 8 ) );
  3489. do
  3490. {
  3491. dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
  3492. Temp >>= bBitDepth;
  3493. } while ( Temp != 0 );
  3494. break;
  3495. }
  3496. #endif // ! DPNBUILD_NOIPX
  3497. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3498. default:
  3499. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3500. {
  3501. DNASSERT(pAddress->GetFamily() == AF_INET);
  3502. //
  3503. // hash IP address
  3504. //
  3505. Temp = pAddress->m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr;
  3506. do
  3507. {
  3508. dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
  3509. Temp >>= bBitDepth;
  3510. } while ( Temp != 0 );
  3511. //
  3512. // hash IP port
  3513. //
  3514. Temp = pAddress->m_SocketAddress.IPSocketAddress.sin_port;
  3515. do
  3516. {
  3517. dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
  3518. Temp >>= bBitDepth;
  3519. } while ( Temp != 0 );
  3520. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3521. break;
  3522. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3523. }
  3524. }
  3525. return dwReturn;
  3526. }
  3527. //**********************************************************************
  3528. //**********************************************************************
  3529. // ------------------------------
  3530. // CSocketAddress::GuidFromInternalAddressWithoutPort - get a guid from the internal
  3531. // address without a port.
  3532. //
  3533. // Entry: Reference to desintation GUID
  3534. //
  3535. // Exit: Nothing
  3536. // ------------------------------
  3537. #undef DPF_MODNAME
  3538. #define DPF_MODNAME "CSocketAddress::GuidFromInternalAddressWithoutPort"
  3539. void CSocketAddress::GuidFromInternalAddressWithoutPort( GUID * pOutputGuid ) const
  3540. {
  3541. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3542. switch (GetFamily())
  3543. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3544. {
  3545. #ifndef DPNBUILD_NOIPV6
  3546. case AF_INET6:
  3547. {
  3548. GuidFromAddress( pOutputGuid, &m_SocketAddress.SocketAddress );
  3549. break;
  3550. }
  3551. #endif // ! DPNBUILD_NOIPV6
  3552. #ifndef DPNBUILD_NOIPX
  3553. case AF_IPX:
  3554. {
  3555. union
  3556. {
  3557. SOCKADDR SockAddr;
  3558. SOCKADDR_IPX IPXSockAddr;
  3559. } TempSocketAddress;
  3560. memcpy( &TempSocketAddress.SockAddr, &m_SocketAddress.SocketAddress, sizeof( TempSocketAddress.SockAddr ) );
  3561. TempSocketAddress.IPXSockAddr.sa_socket = 0;
  3562. GuidFromAddress( pOutputGuid, &TempSocketAddress.SockAddr );
  3563. break;
  3564. }
  3565. #endif // ! DPNBUILD_NOIPX
  3566. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3567. default:
  3568. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3569. {
  3570. union
  3571. {
  3572. SOCKADDR SockAddr;
  3573. SOCKADDR_IN IPSockAddr;
  3574. } TempSocketAddress;
  3575. DNASSERT(GetFamily() == AF_INET);
  3576. memcpy( &TempSocketAddress.SockAddr, &m_SocketAddress.SocketAddress, sizeof( TempSocketAddress.SockAddr ) );
  3577. TempSocketAddress.IPSockAddr.sin_port = 0;
  3578. GuidFromAddress( pOutputGuid, &TempSocketAddress.SockAddr );
  3579. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3580. break;
  3581. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3582. }
  3583. }
  3584. }
  3585. //**********************************************************************
  3586. //**********************************************************************
  3587. // ------------------------------
  3588. // CSocketAddress::IsUndefinedHostAddress - determine if this is an undefined host
  3589. // address
  3590. //
  3591. // Entry: Nothing
  3592. //
  3593. // Exit: Boolean indicating whether this is an undefined host address
  3594. // TRUE = this is an undefined address
  3595. // FALSE = this is not an undefined address
  3596. // ------------------------------
  3597. #undef DPF_MODNAME
  3598. #define DPF_MODNAME "CSocketAddress::IsUndefinedHostAddress"
  3599. BOOL CSocketAddress::IsUndefinedHostAddress( void ) const
  3600. {
  3601. BOOL fReturn;
  3602. fReturn = FALSE;
  3603. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3604. switch (GetFamily())
  3605. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3606. {
  3607. #ifndef DPNBUILD_NOIPV6
  3608. case AF_INET6:
  3609. {
  3610. if (IN6_IS_ADDR_UNSPECIFIED(&m_SocketAddress.IPv6SocketAddress.sin6_addr))
  3611. {
  3612. fReturn = TRUE;
  3613. }
  3614. break;
  3615. }
  3616. #endif // ! DPNBUILD_NOIPV6
  3617. #ifndef DPNBUILD_NOIPX
  3618. case AF_IPX:
  3619. {
  3620. DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_netnum ) == sizeof( DWORD ) );
  3621. DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 6 );
  3622. if ( ( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_netnum ) == 0 ) &&
  3623. ( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 0 ) &&
  3624. ( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum[ 2 ] ) == 0 ) )
  3625. {
  3626. fReturn = TRUE;
  3627. }
  3628. break;
  3629. }
  3630. #endif // ! DPNBUILD_NOIPX
  3631. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3632. default:
  3633. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3634. {
  3635. if ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_ANY )
  3636. {
  3637. fReturn = TRUE;
  3638. }
  3639. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3640. break;
  3641. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3642. }
  3643. }
  3644. return fReturn;
  3645. }
  3646. //**********************************************************************
  3647. //**********************************************************************
  3648. // ------------------------------
  3649. // CSocketAddress::IsValidUnicastAddress - determine if this is valid unicast address
  3650. // address
  3651. //
  3652. // Entry: Whether to also allow the broadcast address or not.
  3653. //
  3654. // Exit: Boolean indicating whether this is a reachable address
  3655. // TRUE = this is a reachable address
  3656. // FALSE = this is not a reachable address
  3657. // ------------------------------
  3658. #undef DPF_MODNAME
  3659. #define DPF_MODNAME "CSocketAddress::IsValidUnicastAddress"
  3660. BOOL CSocketAddress::IsValidUnicastAddress( BOOL fAllowBroadcastAddress ) const
  3661. {
  3662. BOOL fReturn;
  3663. fReturn = TRUE;
  3664. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3665. switch (GetFamily())
  3666. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3667. {
  3668. #ifndef DPNBUILD_NOIPV6
  3669. case AF_INET6:
  3670. {
  3671. //
  3672. // Make sure the address is not all zeros.
  3673. //
  3674. if (IN6_IS_ADDR_UNSPECIFIED(&m_SocketAddress.IPv6SocketAddress.sin6_addr))
  3675. {
  3676. fReturn = FALSE;
  3677. DNASSERTX(! "IPv6 address is :: (all zeros)!", 2);
  3678. }
  3679. //
  3680. // Make sure the address is not a multicast address, unless broadcast is allowed
  3681. // and it's the special enum multicast address.
  3682. //
  3683. if (IN6_IS_ADDR_MULTICAST(&m_SocketAddress.IPv6SocketAddress.sin6_addr))
  3684. {
  3685. if ((! fAllowBroadcastAddress) ||
  3686. (! IN6_ADDR_EQUAL(&m_SocketAddress.IPv6SocketAddress.sin6_addr, &c_in6addrEnumMulticast)))
  3687. {
  3688. fReturn = FALSE;
  3689. DNASSERTX(! "IPv6 address is a multicast address!", 2);
  3690. }
  3691. }
  3692. //
  3693. // Disallow port 0.
  3694. //
  3695. if (m_SocketAddress.IPv6SocketAddress.sin6_port == 0)
  3696. {
  3697. fReturn = FALSE;
  3698. DNASSERTX(! "IPv6 port is 0!", 2);
  3699. }
  3700. break;
  3701. }
  3702. #endif // ! DPNBUILD_NOIPV6
  3703. #ifndef DPNBUILD_NOIPX
  3704. case AF_IPX:
  3705. {
  3706. DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_netnum ) == sizeof( DWORD ) );
  3707. DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 6 );
  3708. if ( ( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_netnum ) == 0 ) &&
  3709. ( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 0 ) &&
  3710. ( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum[ 2 ] ) == 0 ) )
  3711. {
  3712. fReturn = FALSE;
  3713. }
  3714. if (m_SocketAddress.IPXSocketAddress.sa_socket == 0)
  3715. {
  3716. fReturn = FALSE;
  3717. DNASSERTX(! "IPX socket/port is 0!", 2);
  3718. }
  3719. break;
  3720. }
  3721. #endif // ! DPNBUILD_NOIPX
  3722. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3723. default:
  3724. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3725. {
  3726. //
  3727. // Disallow 0.0.0.0, and multicast addresses 224.0.0.0 - 239.255.255.255.
  3728. //
  3729. if ( ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_ANY ) ||
  3730. ( IS_CLASSD_IPV4_ADDRESS( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr ) ) )
  3731. {
  3732. fReturn = FALSE;
  3733. DNASSERTX(! "IPv4 address is 0.0.0.0 or multicast!", 2);
  3734. }
  3735. //
  3736. // Prevent the broadcast address, unless caller allows it.
  3737. //
  3738. if ( ( ! fAllowBroadcastAddress ) &&
  3739. ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_BROADCAST ) )
  3740. {
  3741. fReturn = FALSE;
  3742. DNASSERTX(! "IPv4 address is broadcast!", 2);
  3743. }
  3744. //
  3745. // Disallow ports 0, 1900 (SSDP), 2234 (PAST), and 47624 (DPlay4).
  3746. //
  3747. if ( ( m_SocketAddress.IPSocketAddress.sin_port == HTONS( 0 ) ) ||
  3748. ( m_SocketAddress.IPSocketAddress.sin_port == HTONS( 1900 ) ) ||
  3749. ( m_SocketAddress.IPSocketAddress.sin_port == HTONS( 2234 ) ) ||
  3750. ( m_SocketAddress.IPSocketAddress.sin_port == HTONS( 47624 ) ) )
  3751. {
  3752. fReturn = FALSE;
  3753. DNASSERTX(! "IPv4 port is 0, 1900, 2234, or 47624!", 2);
  3754. }
  3755. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3756. break;
  3757. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3758. }
  3759. }
  3760. return fReturn;
  3761. }
  3762. //**********************************************************************
  3763. #ifndef DPNBUILD_NOREGISTRY
  3764. //**********************************************************************
  3765. // ------------------------------
  3766. // CSocketAddress::IsBannedAddress - determine if this is a banned address
  3767. //
  3768. // Entry: Nothing
  3769. //
  3770. // Exit: Boolean indicating whether this is a banned address
  3771. // TRUE = this is a banned address
  3772. // FALSE = this is not a banned address
  3773. // ------------------------------
  3774. #undef DPF_MODNAME
  3775. #define DPF_MODNAME "CSocketAddress::IsBannedAddress"
  3776. BOOL CSocketAddress::IsBannedAddress( void ) const
  3777. {
  3778. BOOL fReturn;
  3779. fReturn = FALSE;
  3780. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3781. switch (GetFamily())
  3782. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3783. {
  3784. #ifndef DPNBUILD_NOIPV6
  3785. case AF_INET6:
  3786. {
  3787. break;
  3788. }
  3789. #endif // ! DPNBUILD_NOIPV6
  3790. #ifndef DPNBUILD_NOIPX
  3791. case AF_IPX:
  3792. {
  3793. break;
  3794. }
  3795. #endif // ! DPNBUILD_NOIPX
  3796. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3797. default:
  3798. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3799. {
  3800. if (g_pHashBannedIPv4Addresses != NULL)
  3801. {
  3802. DWORD dwAddr;
  3803. DWORD dwBit;
  3804. PVOID pvMask;
  3805. //
  3806. // Try matching the IP address using masks.
  3807. // Start with a 32 bit mask (meaning match the IP address exactly)
  3808. // and gradually relax the mask until we get to a class A mask.
  3809. // We expect the network byte order of the IP address to be the
  3810. // opposite of host byte order.
  3811. //
  3812. dwAddr = m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr;
  3813. for(dwBit = 0x80000000; dwBit >= 0x00000080; dwBit >>= 1)
  3814. {
  3815. //
  3816. // Only hash based on this mask if we read in at least one entry that used it.
  3817. //
  3818. if (dwBit & g_dwBannedIPv4Masks)
  3819. {
  3820. if (g_pHashBannedIPv4Addresses->Find((PVOID) ((DWORD_PTR) dwAddr), &pvMask))
  3821. {
  3822. DNASSERT(((DWORD) ((DWORD_PTR) pvMask)) & dwBit);
  3823. DPFX(DPFPREP, 7, "Address %u.%u.%u.%u is banned (found as 0x%08x, bit 0x%08x).",
  3824. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b1,
  3825. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b2,
  3826. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b3,
  3827. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b4,
  3828. dwAddr,
  3829. dwBit);
  3830. fReturn = TRUE;
  3831. break;
  3832. }
  3833. }
  3834. dwAddr &= ~dwBit;
  3835. }
  3836. }
  3837. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3838. break;
  3839. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3840. }
  3841. }
  3842. return fReturn;
  3843. }
  3844. //**********************************************************************
  3845. #endif // ! DPNBUILD_NOREGISTRY
  3846. //**********************************************************************
  3847. // ------------------------------
  3848. // CSocketAddress::ChangeLoopBackToLocalAddress - change loopback to a local address
  3849. //
  3850. // Entry: Pointer to other address
  3851. //
  3852. // Exit: Nothing
  3853. // ------------------------------
  3854. #undef DPF_MODNAME
  3855. #define DPF_MODNAME "CSocketAddress::ChangeLoopBackToLocalAddress"
  3856. void CSocketAddress::ChangeLoopBackToLocalAddress( const CSocketAddress *const pOtherSocketAddress )
  3857. {
  3858. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3859. switch (pOtherSocketAddress->GetFamily())
  3860. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3861. {
  3862. #ifndef DPNBUILD_NOIPV6
  3863. case AF_INET6:
  3864. {
  3865. if (GetFamily() == AF_INET6)
  3866. {
  3867. SOCKADDR_IN6 *psaddrin6;
  3868. psaddrin6 = (SOCKADDR_IN6*) GetAddress();
  3869. if (IN6_IS_ADDR_LOOPBACK(&psaddrin6->sin6_addr))
  3870. {
  3871. memcpy(&psaddrin6->sin6_addr,
  3872. &(((SOCKADDR_IN6*) pOtherSocketAddress->GetAddress())->sin6_addr),
  3873. sizeof(psaddrin6->sin6_addr));
  3874. psaddrin6->sin6_scope_id = ((SOCKADDR_IN6*) pOtherSocketAddress->GetAddress())->sin6_scope_id;
  3875. DPFX(DPFPREP, 2, "Changing IPv6 loopback address to:" );
  3876. DumpSocketAddress( 2, (SOCKADDR*) psaddrin6, AF_INET6 );
  3877. }
  3878. }
  3879. break;
  3880. }
  3881. #endif // ! DPNBUILD_NOIPV6
  3882. #ifndef DPNBUILD_NOIPX
  3883. case AF_IPX:
  3884. {
  3885. DNASSERT( pOtherSocketAddress != NULL );
  3886. //
  3887. // there is no 'loopback' for IPX so this function doesn't do anything
  3888. //
  3889. break;
  3890. }
  3891. #endif // ! DPNBUILD_NOIPX
  3892. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3893. default:
  3894. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3895. {
  3896. #ifndef DPNBUILD_NOIPV6
  3897. if (GetFamily() == AF_INET)
  3898. #endif // ! DPNBUILD_NOIPV6
  3899. {
  3900. if ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == IP_LOOPBACK_ADDRESS )
  3901. {
  3902. DPFX(DPFPREP, 2, "Changing IPv4 loopback address to %u.%u.%u.%u.",
  3903. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b1,
  3904. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b2,
  3905. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b3,
  3906. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b4);
  3907. m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = pOtherSocketAddress->m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr;
  3908. }
  3909. }
  3910. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3911. break;
  3912. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3913. }
  3914. }
  3915. }
  3916. //**********************************************************************
  3917. //**********************************************************************
  3918. // ------------------------------
  3919. // EncryptGuid - encrypt a guid
  3920. //
  3921. // Entry: Pointer to source guid
  3922. // Pointer to destination guid
  3923. // Pointer to encryption key
  3924. //
  3925. // Exit: Nothing
  3926. // ------------------------------
  3927. #undef DPF_MODNAME
  3928. #define DPF_MODNAME "EncryptGuid"
  3929. void EncryptGuid( const GUID *const pSourceGuid,
  3930. GUID *const pDestinationGuid,
  3931. const GUID *const pEncryptionKey )
  3932. {
  3933. const char *pSourceBytes;
  3934. char *pDestinationBytes;
  3935. const char *pEncryptionBytes;
  3936. DWORD_PTR dwIndex;
  3937. DNASSERT( pSourceGuid != NULL );
  3938. DNASSERT( pDestinationGuid != NULL );
  3939. DNASSERT( pEncryptionKey != NULL );
  3940. DBG_CASSERT( sizeof( pSourceBytes ) == sizeof( pSourceGuid ) );
  3941. pSourceBytes = reinterpret_cast<const char*>( pSourceGuid );
  3942. DBG_CASSERT( sizeof( pDestinationBytes ) == sizeof( pDestinationGuid ) );
  3943. pDestinationBytes = reinterpret_cast<char*>( pDestinationGuid );
  3944. DBG_CASSERT( sizeof( pEncryptionBytes ) == sizeof( pEncryptionKey ) );
  3945. pEncryptionBytes = reinterpret_cast<const char*>( pEncryptionKey );
  3946. DBG_CASSERT( ( sizeof( *pSourceGuid ) == sizeof( *pEncryptionKey ) ) &&
  3947. ( sizeof( *pDestinationGuid ) == sizeof( *pEncryptionKey ) ) );
  3948. dwIndex = sizeof( *pSourceGuid );
  3949. while ( dwIndex != 0 )
  3950. {
  3951. dwIndex--;
  3952. pDestinationBytes[ dwIndex ] = pSourceBytes[ dwIndex ] ^ pEncryptionBytes[ dwIndex ];
  3953. }
  3954. }
  3955. //**********************************************************************
  3956. #undef DPF_MODNAME
  3957. #define DPF_MODNAME "CSocketAddress::GuidFromAddress"
  3958. void CSocketAddress::GuidFromAddress( GUID * pOutputGuid, const SOCKADDR * pSocketAddress ) const
  3959. {
  3960. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  3961. switch (pSocketAddress->sa_family)
  3962. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  3963. {
  3964. #ifndef DPNBUILD_NOIPV6
  3965. case AF_INET6:
  3966. {
  3967. const SOCKADDR_IN6 *pSocketAddressIPv6 = reinterpret_cast<const SOCKADDR_IN6*>( pSocketAddress );
  3968. DNASSERT((GetFamily() == AF_INET) || (GetFamily() == AF_INET6));
  3969. DBG_CASSERT(sizeof(pSocketAddressIPv6->sin6_addr) == sizeof(GUID));
  3970. //
  3971. // Hopefully the beginning of IPv6 addresses will never look like an IPv4
  3972. // socket family so our unpacking routine won't get confused.
  3973. //
  3974. DNASSERT(((SOCKADDR*) (&pSocketAddressIPv6->sin6_addr))->sa_family != AF_INET);
  3975. //
  3976. // Even though IPv6 addresses are already 128 bits long and fill an entire
  3977. // entire GUID, we need to somehow pack the scope ID for link local and
  3978. // site local addresses into the GUID as well. We do this by storing the
  3979. // scope ID in bytes 3-6. This is because the prefix identifier for link local
  3980. // addresses is FE80::/64, and for site local addresses is FEC0::/48,
  3981. // leaving us 38 bits of what should always be zeros after the 10 bit prefix
  3982. // headers. We round to 16 to get to the WORD boundary, and therefore
  3983. // have a handy 32 bits left.
  3984. //
  3985. if ((IN6_IS_ADDR_LINKLOCAL(&pSocketAddressIPv6->sin6_addr)) ||
  3986. (IN6_IS_ADDR_SITELOCAL(&pSocketAddressIPv6->sin6_addr)))
  3987. {
  3988. GUID guidTemp;
  3989. WORD * pawSrcAddr;
  3990. WORD * pawDstAddr;
  3991. memcpy(&guidTemp, &pSocketAddressIPv6->sin6_addr, sizeof(GUID));
  3992. //
  3993. // Assert that the scope is not 0 and that bits 17-48 really are zero.
  3994. // Then copy the scope ID.
  3995. // The destination bits are WORD, but not DWORD aligned.
  3996. //
  3997. DNASSERT(pSocketAddressIPv6->sin6_scope_id != 0);
  3998. pawSrcAddr = (WORD*) (&pSocketAddressIPv6->sin6_scope_id);
  3999. pawDstAddr = (WORD*) (&guidTemp);
  4000. DBG_CASSERT(sizeof(pSocketAddressIPv6->sin6_scope_id) == 4);
  4001. DNASSERT((pawDstAddr[1] == 0) && (pawDstAddr[2] == 0));
  4002. pawDstAddr[1] = pawSrcAddr[0];
  4003. pawDstAddr[2] = pawSrcAddr[1];
  4004. EncryptGuid( &guidTemp, pOutputGuid, &g_IPSPEncryptionGuid );
  4005. }
  4006. else
  4007. {
  4008. EncryptGuid( (GUID*) (&pSocketAddressIPv6->sin6_addr), pOutputGuid, &g_IPSPEncryptionGuid );
  4009. }
  4010. break;
  4011. }
  4012. #endif // ! DPNBUILD_NOIPV6
  4013. #ifndef DPNBUILD_NOIPX
  4014. case AF_IPX:
  4015. {
  4016. const SOCKADDR_IPX *pSocketAddressIPX = reinterpret_cast<const SOCKADDR_IPX*>( pSocketAddress );
  4017. DNASSERT(GetFamily() == AF_IPX);
  4018. memcpy( pOutputGuid, pSocketAddressIPX, sizeof( *pSocketAddressIPX ) );
  4019. memset( &( reinterpret_cast<BYTE*>( pOutputGuid )[ sizeof( *pSocketAddressIPX ) ] ), 0, ( sizeof( *pOutputGuid ) - sizeof( *pSocketAddressIPX ) ) );
  4020. EncryptGuid( pOutputGuid, pOutputGuid, &g_IPXSPEncryptionGuid );
  4021. break;
  4022. }
  4023. #endif // ! DPNBUILD_NOIPX
  4024. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  4025. default:
  4026. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  4027. {
  4028. const SOCKADDR_IN *pSocketAddressIP = reinterpret_cast<const SOCKADDR_IN*>( pSocketAddress );
  4029. DNASSERT(GetFamily() == AF_INET);
  4030. memcpy( pOutputGuid, pSocketAddressIP, ( sizeof( *pOutputGuid ) - sizeof( pSocketAddressIP->sin_zero ) ) );
  4031. memset( &( reinterpret_cast<BYTE*>( pOutputGuid )[ OFFSETOF( SOCKADDR_IN, sin_zero ) ] ), 0, sizeof( pSocketAddressIP->sin_zero ) );
  4032. EncryptGuid( pOutputGuid, pOutputGuid, &g_IPSPEncryptionGuid );
  4033. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  4034. break;
  4035. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  4036. }
  4037. }
  4038. }
  4039. #undef DPF_MODNAME
  4040. #define DPF_MODNAME "CSocketAddress::PoolAllocFunction"
  4041. BOOL CSocketAddress::PoolAllocFunction( void* pvItem, void* pvContext )
  4042. {
  4043. CSocketAddress* pAddress = (CSocketAddress*)pvItem;
  4044. // Base class
  4045. pAddress->m_Sig[0] = 'S';
  4046. pAddress->m_Sig[1] = 'P';
  4047. pAddress->m_Sig[2] = 'A';
  4048. pAddress->m_Sig[3] = 'D';
  4049. return TRUE;
  4050. }
  4051. #undef DPF_MODNAME
  4052. #define DPF_MODNAME "CSocketAddress::PoolGetFunction"
  4053. void CSocketAddress::PoolGetFunction( void* pvItem, void* pvContext )
  4054. {
  4055. CSocketAddress* pAddress = (CSocketAddress*)pvItem;
  4056. //
  4057. // The context is the socket address type if IPv6 and/or IPX are available in
  4058. // this build. If neither are available, it will be NULL, but SetFamilyProtocolAndSize
  4059. // should ignore the value.
  4060. //
  4061. pAddress->SetFamilyProtocolAndSize((short)(DWORD_PTR)pvContext);
  4062. }
  4063. #undef DPF_MODNAME
  4064. #define DPF_MODNAME "CSocketAddress::PoolReturnFunction"
  4065. void CSocketAddress::PoolReturnFunction( void* pvItem )
  4066. {
  4067. #ifdef DBG
  4068. const CSocketAddress* pAddress = (CSocketAddress*)pvItem;
  4069. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  4070. switch (pAddress->m_SocketAddress.SocketAddress.sa_family)
  4071. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  4072. {
  4073. #ifndef DPNBUILD_NOIPV6
  4074. case AF_INET6:
  4075. {
  4076. DNASSERT( pAddress->m_iSocketAddressSize == sizeof( pAddress->m_SocketAddress.IPv6SocketAddress ) );
  4077. DNASSERT( pAddress->m_SocketAddress.IPSocketAddress.sin_family == AF_INET6 );
  4078. DNASSERT( pAddress->m_iSocketProtocol == IPPROTO_UDP );
  4079. break;
  4080. }
  4081. #endif // ! DPNBUILD_NOIPV6
  4082. #ifndef DPNBUILD_NOIPX
  4083. case AF_IPX:
  4084. {
  4085. DNASSERT( pAddress->m_iSocketAddressSize == sizeof( pAddress->m_SocketAddress.IPXSocketAddress ) );
  4086. DNASSERT( pAddress->m_SocketAddress.IPXSocketAddress.sa_family == AF_IPX );
  4087. DNASSERT( pAddress->m_iSocketProtocol == NSPROTO_IPX );
  4088. break;
  4089. }
  4090. #endif // ! DPNBUILD_NOIPX
  4091. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  4092. default:
  4093. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  4094. {
  4095. DNASSERT( pAddress->m_iSocketAddressSize == sizeof( pAddress->m_SocketAddress.IPSocketAddress ) );
  4096. DNASSERT( pAddress->m_SocketAddress.IPSocketAddress.sin_family == AF_INET );
  4097. DNASSERT( pAddress->m_iSocketProtocol == IPPROTO_UDP );
  4098. #if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
  4099. break;
  4100. #endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
  4101. }
  4102. }
  4103. #endif // DBG
  4104. }