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
4710 lines
133 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: SPAddress.cpp
|
|
* Content: Winsock address base class
|
|
*
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 01/20/1999 jtk Created
|
|
* 05/12/1999 jtk Derived from modem endpoint class
|
|
***************************************************************************/
|
|
|
|
#include "dnwsocki.h"
|
|
|
|
|
|
//**********************************************************************
|
|
// Constant definitions
|
|
//**********************************************************************
|
|
|
|
//
|
|
// maximum allowed hostname string size, in bytes, including NULL termination
|
|
//
|
|
#define MAX_HOSTNAME_SIZE 512
|
|
|
|
//
|
|
// broadcast address as a string
|
|
//
|
|
const WCHAR g_IPBroadcastAddress[] = L"255.255.255.255";
|
|
const DWORD g_dwIPBroadcastAddressSize = sizeof( g_IPBroadcastAddress );
|
|
|
|
//
|
|
// string for IP helper API
|
|
//
|
|
static const TCHAR c_tszIPHelperDLLName[] = TEXT("IPHLPAPI.DLL");
|
|
static const char c_szAdapterNameTemplate[] = "%s - %s";
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
//
|
|
// length of IPX host names 'xxxxxxxx,xxxxxxxxxxxx' including NULL
|
|
//
|
|
#define IPX_ADDRESS_STRING_LENGTH 22
|
|
|
|
//
|
|
// default broadcast and listen addresses
|
|
//
|
|
static const WCHAR g_IPXBroadcastAddress[] = L"00000000,FFFFFFFFFFFF";
|
|
static const WCHAR g_IPXListenAddress[] = L"00000000,000000000000";
|
|
|
|
//
|
|
// string used for single IPX adapter
|
|
//
|
|
static const WCHAR g_IPXAdapterString[] = L"Local IPX Adapter";
|
|
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#ifndef DPNBUILD_NOIPV6
|
|
|
|
static const WCHAR c_wszIPv6AdapterNameTemplate[] = L"%s - IPv6 - %s";
|
|
static const WCHAR c_wszIPv4AdapterNameTemplate[] = L"%s - IPv4 - %s";
|
|
static const WCHAR c_wszIPv6AdapterNameNoDescTemplate[] = L"IPv6 - %s";
|
|
static const WCHAR c_wszIPv4AdapterNameNoDescTemplate[] = L"IPv4 - %s";
|
|
|
|
//
|
|
// string used for IPv4 loopback adapter
|
|
//
|
|
static const WCHAR c_wszIPv4LoopbackAdapterString[] = L"IPv4 Loopback Adapter";
|
|
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
//
|
|
// 238.1.1.1 in network byte order
|
|
//
|
|
#define SAMPLE_MULTICAST_ADDRESS 0x010101EE
|
|
|
|
#define INVALID_INTERFACE_INDEX -1
|
|
|
|
static const WCHAR c_wszPrivateScopeString[] = L"Private Multicast Scope - TTL " MULTICAST_TTL_PRIVATE_AS_STRING;
|
|
static const WCHAR c_wszLocalScopeString[] = L"Local Multicast Scope - TTL " MULTICAST_TTL_LOCAL_AS_STRING;
|
|
static const WCHAR c_wszGlobalScopeString[] = L"Global Multicast Scope - TTL " MULTICAST_TTL_GLOBAL_AS_STRING;
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
|
|
//**********************************************************************
|
|
// Macro definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Structure definitions
|
|
//**********************************************************************
|
|
|
|
#ifndef DPNBUILD_NOIPV6
|
|
|
|
typedef struct _SORTADAPTERADDRESS
|
|
{
|
|
SOCKADDR * psockaddr;
|
|
WCHAR * pwszDescription;
|
|
} SORTADAPTERADDRESS;
|
|
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
|
|
//**********************************************************************
|
|
// Variable definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Function prototypes
|
|
//**********************************************************************
|
|
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
#ifndef DPNBUILD_NOWINSOCK2
|
|
typedef DWORD (WINAPI *PFNGETADAPTERSINFO)(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen);
|
|
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
typedef DWORD (WINAPI *PFNGETBESTINTERFACE)(IPAddr dwDestAddr, PDWORD pdwBestIfIndex);
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
|
|
#ifndef DPNBUILD_NOIPV6
|
|
typedef DWORD (WINAPI *PFNGETADAPTERSADDRESSES)(ULONG ulFamily, DWORD dwFlags, PVOID pvReserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pulOutBufLen);
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#endif // ! DPNBUILD_NOWINSOCK2
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
|
|
//**********************************************************************
|
|
// Function definitions
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::InitializeWithBroadcastAddress - initialize with the IP broadcast address
|
|
//
|
|
// Entry: Nothing
|
|
//
|
|
// Exit: Nothing
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::InitializeWithBroadcastAddress"
|
|
|
|
void CSocketAddress::InitializeWithBroadcastAddress( void )
|
|
{
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_netnum ) == sizeof( DWORD ) );
|
|
*reinterpret_cast<DWORD*>( m_SocketAddress.IPXSocketAddress.sa_netnum ) = 0x00000000;
|
|
|
|
DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 6 );
|
|
DBG_CASSERT( sizeof( DWORD ) == 4 );
|
|
*reinterpret_cast<DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum ) = 0xFFFFFFFF;
|
|
*reinterpret_cast<DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum[ 2 ] ) = 0xFFFFFFFF;
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
case AF_INET:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = INADDR_BROADCAST;
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
//
|
|
// We should never try to initialize an IPv6 address with the broadcast
|
|
// address. We use IPv4 broadcast addresses, and then convert to the
|
|
// IPv6 enum multicast address on the fly.
|
|
//
|
|
DNASSERT(FALSE);
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::SetAddressFromSOCKADDR - set address from a socket address
|
|
//
|
|
// Entry: Reference to address
|
|
// Size of address
|
|
//
|
|
// Exit: Nothing
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::SetAddressFromSOCKADDR"
|
|
|
|
void CSocketAddress::SetAddressFromSOCKADDR( const SOCKADDR *pAddress, const INT_PTR iAddressSize )
|
|
{
|
|
DNASSERT( iAddressSize == GetAddressSize() );
|
|
memcpy( &m_SocketAddress.SocketAddress, pAddress, iAddressSize );
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
//
|
|
// We don't validate anything in the address.
|
|
//
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
//
|
|
// IPX addresses are only 14 of the 16 bytes in the socket address structure,
|
|
// make sure the extra bytes are zero!
|
|
//
|
|
DNASSERT( m_SocketAddress.SocketAddress.sa_data[ 12 ] == 0 );
|
|
DNASSERT( m_SocketAddress.SocketAddress.sa_data[ 13 ] == 0 );
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
//
|
|
// Since Winsock won't guarantee that the sin_zero part of an IP address is
|
|
// really zero, we need to do it ourself. If we don't, it'll make a mess out
|
|
// of the Guid<-->Address code.
|
|
//
|
|
DBG_CASSERT( sizeof( &m_SocketAddress.IPSocketAddress.sin_zero[ 0 ] ) == sizeof( DWORD* ) );
|
|
DBG_CASSERT( sizeof( &m_SocketAddress.IPSocketAddress.sin_zero[ sizeof( DWORD ) ] ) == sizeof( DWORD* ) );
|
|
*reinterpret_cast<DWORD*>( &m_SocketAddress.IPSocketAddress.sin_zero[ 0 ] ) = 0;
|
|
*reinterpret_cast<DWORD*>( &m_SocketAddress.IPSocketAddress.sin_zero[ sizeof( DWORD ) ] ) = 0;
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::SocketAddressFromDP8Address - convert a DP8Address into a socket address
|
|
// NOTE: The address object may be modified
|
|
//
|
|
// Entry: Pointer to DP8Address
|
|
// Secure transport key ID, or NULL if none.
|
|
// Whether name resoultion (potentially blocking) is allowed.
|
|
// Address type
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::SocketAddressFromDP8Address"
|
|
|
|
HRESULT CSocketAddress::SocketAddressFromDP8Address( IDirectPlay8Address *const pDP8Address,
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
ULONGLONG * const pullKeyID,
|
|
#endif // DPNBUILD_XNETSECURITY
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
const BOOL fAllowNameResolution,
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
const SP_ADDRESS_TYPE AddressType )
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hTempResult;
|
|
BYTE abBuffer[MAX_HOSTNAME_SIZE];
|
|
DWORD dwPort;
|
|
DWORD dwTempSize;
|
|
DWORD dwDataType;
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
GUID AdapterGuid;
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
|
|
|
|
DPFX(DPFPREP, 8, "(0x%p) Parameters: (0x%p, %u)", this, pDP8Address, AddressType);
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
DNASSERT( pDP8Address != NULL );
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
DNASSERT( pullKeyID == NULL );
|
|
#endif // DPNBUILD_XNETSECURITY
|
|
|
|
//
|
|
// the address type will determine how the address is handled
|
|
//
|
|
switch ( AddressType )
|
|
{
|
|
//
|
|
// local device address, ask for the device guid and port to build a socket
|
|
// address
|
|
//
|
|
case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
|
|
case SP_ADDRESS_TYPE_DEVICE:
|
|
{
|
|
union
|
|
{
|
|
SOCKADDR SocketAddress;
|
|
SOCKADDR_IPX IPXSocketAddress;
|
|
#ifndef DPNBUILD_NOIPV6
|
|
SOCKADDR_STORAGE SocketAddressStorage;
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
} NetAddress;
|
|
|
|
|
|
//
|
|
// Ask for the adapter guid. If none is found, fail.
|
|
//
|
|
dwTempSize = sizeof( AdapterGuid );
|
|
hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_DEVICE, &AdapterGuid, &dwTempSize, &dwDataType );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// ok
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
DNASSERT( dwDataType == DPNA_DATATYPE_GUID );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// remap missing component to 'addressing' error
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
hr = DPNERR_ADDRESSING;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = hTempResult;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
DNASSERT( sizeof( AdapterGuid ) == dwTempSize );
|
|
|
|
//
|
|
// Ask for the port. If none is found, choose a default.
|
|
//
|
|
dwTempSize = sizeof( dwPort );
|
|
hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_PORT, &dwPort, &dwTempSize, &dwDataType );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// port present, nothing to do
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
DNASSERT( dwDataType == DPNA_DATATYPE_DWORD );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// port not present, fill in the appropriate default
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
DNASSERT( hr == DPN_OK );
|
|
switch ( AddressType )
|
|
{
|
|
case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
|
|
{
|
|
dwPort = ANY_PORT;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// other error, fail
|
|
//
|
|
default:
|
|
{
|
|
hr = hTempResult;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
DNASSERT( sizeof( dwPort ) == dwTempSize );
|
|
|
|
//
|
|
// convert the GUID to an address in temp space because the GUID contains ALL address information (port, etc)
|
|
// and we don't want to blindly wail on any information that might have already been set. Verify data
|
|
// integrity and then only copy the raw address.
|
|
//
|
|
#ifndef DPNBUILD_NOIPV6
|
|
AddressFromGuid( &AdapterGuid, &NetAddress.SocketAddressStorage );
|
|
#else // ! DPNBUILD_NOIPV6
|
|
AddressFromGuid( &AdapterGuid, &NetAddress.SocketAddress );
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
if ( NetAddress.IPXSocketAddress.sa_family != m_SocketAddress.IPXSocketAddress.sa_family )
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = DPNERR_ADDRESSING;
|
|
DPFX(DPFPREP, 0, "Invalid device guid!" );
|
|
goto Failure;
|
|
}
|
|
|
|
DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress ) == sizeof( NetAddress.IPXSocketAddress ) );
|
|
memcpy( &m_SocketAddress.IPXSocketAddress, &NetAddress.IPXSocketAddress, sizeof( m_SocketAddress.IPXSocketAddress ) );
|
|
m_SocketAddress.IPXSocketAddress.sa_socket = HTONS( static_cast<WORD>( dwPort ) );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// hostname
|
|
//
|
|
case SP_ADDRESS_TYPE_HOST:
|
|
{
|
|
//
|
|
// Ask for the port. If none is found, choose a default.
|
|
//
|
|
dwTempSize = sizeof( dwPort );
|
|
hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_PORT, &dwPort, &dwTempSize, &dwDataType );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// port present, nothing to do
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
DNASSERT( dwDataType == DPNA_DATATYPE_DWORD );
|
|
m_SocketAddress.IPXSocketAddress.sa_socket = HTONS( static_cast<WORD>( dwPort ) );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// port not present, fill in the appropriate default
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
#ifdef DPNBUILD_SINGLEPROCESS
|
|
const DWORD dwTempPort = BASE_DPLAY8_PORT;
|
|
#else // ! DPNBUILD_SINGLEPROCESS
|
|
const DWORD dwTempPort = DPNA_DPNSVR_PORT;
|
|
#endif // ! DPNBUILD_SINGLEPROCESS
|
|
|
|
|
|
m_SocketAddress.IPXSocketAddress.sa_socket = HTONS( static_cast<const WORD>( dwTempPort ) );
|
|
hTempResult = IDirectPlay8Address_AddComponent( pDP8Address,
|
|
DPNA_KEY_PORT,
|
|
&dwTempPort,
|
|
sizeof( dwTempPort ),
|
|
DPNA_DATATYPE_DWORD
|
|
);
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
hr = hTempResult;
|
|
goto Failure;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// remap everything else to an addressing failure
|
|
//
|
|
default:
|
|
{
|
|
hr = DPNERR_ADDRESSING;
|
|
goto Failure;
|
|
}
|
|
}
|
|
|
|
//
|
|
// attempt to determine host name
|
|
//
|
|
dwTempSize = sizeof(abBuffer);
|
|
hr = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_HOSTNAME, abBuffer, &dwTempSize, &dwDataType );
|
|
switch ( hr )
|
|
{
|
|
//
|
|
// keep the following codes and fail
|
|
//
|
|
case DPNERR_OUTOFMEMORY:
|
|
case DPNERR_INCOMPLETEADDRESS:
|
|
{
|
|
goto Failure;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// no problem
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
switch (dwDataType)
|
|
{
|
|
case DPNA_DATATYPE_STRING:
|
|
{
|
|
BYTE abBuffer2[MAX_HOSTNAME_SIZE];
|
|
|
|
|
|
//
|
|
// Unicode string, convert it to ANSI.
|
|
//
|
|
dwTempSize /= sizeof(WCHAR);
|
|
hr = STR_jkWideToAnsi( (char*) abBuffer2, (WCHAR*) abBuffer, dwTempSize );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to convert hostname to ANSI!" );
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
|
|
strncpy((char*) abBuffer, (char*) abBuffer2, dwTempSize);
|
|
|
|
//
|
|
// Fall through...
|
|
//
|
|
}
|
|
|
|
case DPNA_DATATYPE_STRING_ANSI:
|
|
{
|
|
long val;
|
|
char temp[3];
|
|
char *a, *b;
|
|
UINT_PTR uIndex;
|
|
|
|
|
|
//
|
|
// convert the text host name into the SOCKADDR structure
|
|
//
|
|
|
|
if ( dwTempSize != IPX_ADDRESS_STRING_LENGTH )
|
|
{
|
|
DPFX(DPFPREP, 0, "Invalid IPX net/node. Must be %d bytes of ASCII hex (net,node:socket)", ( IPX_ADDRESS_STRING_LENGTH - 1 ) );
|
|
DPFX(DPFPREP, 0, "IPXAddressFromDP8Address: Failed to parse IPX host name!" );
|
|
goto Failure;
|
|
}
|
|
|
|
// we convert the string for the hostname field into the components
|
|
temp[ 2 ] = 0;
|
|
a = (char*) abBuffer;
|
|
|
|
// the net number is 4 bytes
|
|
for ( uIndex = 0; uIndex < 4; uIndex++ )
|
|
{
|
|
strncpy( temp, a, 2 );
|
|
val = strtol( temp, &b, 16 );
|
|
m_SocketAddress.IPXSocketAddress.sa_netnum[ uIndex ] = (char) val;
|
|
a += 2;
|
|
}
|
|
|
|
// followed by a dot
|
|
a++;
|
|
|
|
// the node is 6 bytes
|
|
for ( uIndex = 0; uIndex < 6; uIndex++ )
|
|
{
|
|
strncpy( temp, a, 2 );
|
|
val = strtol( temp, &b, 16 );
|
|
m_SocketAddress.IPXSocketAddress.sa_nodenum[ uIndex ] = (char) val;
|
|
a += 2;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DPFX(DPFPREP, 0, "Hostname component wasn't a string (%u)!", dwDataType );
|
|
hr = DPNERR_ADDRESSING;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// hostname does not exist, treat as an incomplete address
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
hr = DPNERR_INCOMPLETEADDRESS;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// remap other errors to an addressing error
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = DPNERR_ADDRESSING;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown address type
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
DNASSERT( pDP8Address != NULL );
|
|
|
|
switch ( AddressType )
|
|
{
|
|
//
|
|
// local device address, ask for the device guid and port to build a socket
|
|
// address
|
|
//
|
|
case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
|
|
case SP_ADDRESS_TYPE_DEVICE:
|
|
{
|
|
union
|
|
{
|
|
SOCKADDR SocketAddress;
|
|
SOCKADDR_IN INetAddress;
|
|
#ifndef DPNBUILD_NOIPV6
|
|
SOCKADDR_IN6 INet6Address;
|
|
SOCKADDR_STORAGE SocketAddressStorage;
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
} INetSocketAddress;
|
|
#ifdef DPNBUILD_ONLYONEADAPTER
|
|
XNADDR xnaddr;
|
|
DWORD dwStatus;
|
|
|
|
|
|
#else // ! DPNBUILD_ONLYONEADAPTER
|
|
|
|
|
|
//
|
|
// Ask for the adapter guid. If none is found, fail.
|
|
//
|
|
hTempResult = IDirectPlay8Address_GetDevice( pDP8Address, &AdapterGuid );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// ok
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// remap missing component to 'addressing' error
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
DPFX(DPFPREP, 0, "Device GUID does not exist!" );
|
|
DNASSERTX(! "Device GUID does not exist", 2);
|
|
hr = DPNERR_ADDRESSING;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't get device (0x%lx)!", hr );
|
|
hr = hTempResult;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
|
|
//
|
|
// Ask for the port. If none is found, choose a default.
|
|
//
|
|
dwTempSize = sizeof( dwPort );
|
|
hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_PORT, &dwPort, &dwTempSize, &dwDataType );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// port present, nothing to do
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
DNASSERT( dwDataType == DPNA_DATATYPE_DWORD );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// port not present, fill in the appropriate default
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
DPFX(DPFPREP, 6, "Port component does not exist in address 0x%p.", pDP8Address );
|
|
DNASSERT( hr == DPN_OK );
|
|
switch ( AddressType )
|
|
{
|
|
case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
|
|
{
|
|
dwPort = ANY_PORT;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// other error, fail
|
|
//
|
|
default:
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't get port component (0x%lx)!", hr );
|
|
hr = hTempResult;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
DNASSERT( sizeof( dwPort ) == dwTempSize );
|
|
|
|
|
|
#ifdef DPNBUILD_ONLYONEADAPTER
|
|
DNASSERT( GetFamily() == AF_INET );
|
|
//
|
|
// Zero out the entire structure. This implies we use INADDR_ANY.
|
|
//
|
|
memset(&INetSocketAddress, 0, sizeof(INetSocketAddress));
|
|
|
|
dwStatus = XNetGetTitleXnAddr(&xnaddr);
|
|
if ((dwStatus != XNET_GET_XNADDR_PENDING) &&
|
|
(dwStatus != XNET_GET_XNADDR_NONE))
|
|
{
|
|
DPFX(DPFPREP, 5, "Using device %u.%u.%u.%u.",
|
|
xnaddr.ina.S_un.S_un_b.s_b1,
|
|
xnaddr.ina.S_un.S_un_b.s_b2,
|
|
xnaddr.ina.S_un.S_un_b.s_b3,
|
|
xnaddr.ina.S_un.S_un_b.s_b4);
|
|
INetSocketAddress.INetAddress.sin_addr.S_un.S_addr = xnaddr.ina.S_un.S_addr;
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 1, "Couldn't get XNet address, status = %u.",
|
|
dwStatus);
|
|
}
|
|
#else // ! DPNBUILD_ONLYONEADAPTER
|
|
//
|
|
// convert the GUID to an address in temp space because the GUID is large enough to potentially hold
|
|
// ALL address information (port, etc) and we don't want to blindly wail on any information that might
|
|
// have already been set. Verify data integrity and then only copy the raw address.
|
|
//
|
|
#ifdef DPNBUILD_NOIPV6
|
|
AddressFromGuid( &AdapterGuid, &INetSocketAddress.SocketAddress );
|
|
#else // ! DPNBUILD_NOIPV6
|
|
AddressFromGuid( &AdapterGuid, &INetSocketAddress.SocketAddressStorage );
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
if ( ( INetSocketAddress.INetAddress.sin_family != AF_INET ) ||
|
|
( reinterpret_cast<DWORD*>( &INetSocketAddress.INetAddress.sin_zero[ 0 ] )[ 0 ] != 0 ) ||
|
|
( reinterpret_cast<DWORD*>( &INetSocketAddress.INetAddress.sin_zero[ 0 ] )[ 1 ] != 0 ) )
|
|
{
|
|
#ifdef DPNBUILD_NOIPV6
|
|
hr = DPNERR_ADDRESSING;
|
|
DPFX(DPFPREP, 0, "Invalid device guid!" );
|
|
goto Exit;
|
|
#else // ! DPNBUILD_NOIPV6
|
|
//
|
|
// Assume it is an IPv6 address.
|
|
//
|
|
SetFamilyProtocolAndSize(AF_INET6);
|
|
AddressFromGuid( &AdapterGuid, &INetSocketAddress.SocketAddressStorage );
|
|
|
|
m_SocketAddress.IPv6SocketAddress.sin6_addr = INetSocketAddress.INet6Address.sin6_addr;
|
|
m_SocketAddress.IPv6SocketAddress.sin6_port = HTONS( static_cast<WORD>( dwPort ) );
|
|
m_SocketAddress.IPv6SocketAddress.sin6_scope_id = INetSocketAddress.INet6Address.sin6_scope_id;
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
{
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = INetSocketAddress.INetAddress.sin_addr.S_un.S_addr;
|
|
m_SocketAddress.IPSocketAddress.sin_port = HTONS( static_cast<WORD>( dwPort ) );
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// hostname
|
|
//
|
|
case SP_ADDRESS_TYPE_HOST:
|
|
{
|
|
//
|
|
// Ask for the port. If none is found, choose a default.
|
|
//
|
|
dwTempSize = sizeof( dwPort );
|
|
hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_PORT, &dwPort, &dwTempSize, &dwDataType );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// port present, nothing to do
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
DNASSERT( dwDataType == DPNA_DATATYPE_DWORD );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// port not present, fill in the appropriate default
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
#ifdef DPNBUILD_SINGLEPROCESS
|
|
dwPort = BASE_DPLAY8_PORT;
|
|
#else // ! DPNBUILD_SINGLEPROCESS
|
|
dwPort = DPNA_DPNSVR_PORT;
|
|
#endif // ! DPNBUILD_SINGLEPROCESS
|
|
DPFX(DPFPREP, 6, "Port component does not exist in address 0x%p, defaulting to %u.",
|
|
pDP8Address, dwPort );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// remap everything else to an addressing failure
|
|
//
|
|
default:
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't get port component (0x%lx)!", hr );
|
|
hr = DPNERR_ADDRESSING;
|
|
goto Failure;
|
|
}
|
|
}
|
|
|
|
m_SocketAddress.IPSocketAddress.sin_port = HTONS( static_cast<WORD>( dwPort ) );
|
|
|
|
//
|
|
// get the host name
|
|
//
|
|
dwTempSize = sizeof(abBuffer);
|
|
hTempResult = IDirectPlay8Address_GetComponentByName( pDP8Address, DPNA_KEY_HOSTNAME, abBuffer, &dwTempSize, &dwDataType );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// host name present, convert from string to valid binary value
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
switch (dwDataType)
|
|
{
|
|
case DPNA_DATATYPE_STRING:
|
|
{
|
|
BYTE abBuffer2[MAX_HOSTNAME_SIZE];
|
|
|
|
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
//
|
|
// The buffer should be large enough to hold an XNet address.
|
|
//
|
|
DBG_CASSERT(MAX_HOSTNAME_SIZE > ((sizeof(XNADDR) * 2) + 1) * sizeof(WCHAR));
|
|
#endif // DPNBUILD_XNETSECURITY
|
|
|
|
//
|
|
// Unicode string, convert it to ANSI.
|
|
//
|
|
dwTempSize /= sizeof(WCHAR);
|
|
hr = STR_jkWideToAnsi( (char*) abBuffer2, (WCHAR*) abBuffer, dwTempSize );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to convert hostname to ANSI!" );
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
|
|
strncpy((char*) abBuffer, (char*) abBuffer2, dwTempSize);
|
|
|
|
//
|
|
// Fall through...
|
|
//
|
|
}
|
|
|
|
case DPNA_DATATYPE_STRING_ANSI:
|
|
{
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
//
|
|
// This may be an XNet address. If we're allowed to check, and
|
|
// the string is the right size, convert it.
|
|
//
|
|
if ((pullKeyID != NULL) &&
|
|
(dwTempSize == ((sizeof(XNADDR) * 2) + 1))) // 2 characters for every byte + NULL termination
|
|
{
|
|
char * pcCurrentSrc;
|
|
XNADDR xnaddr;
|
|
BYTE * pbCurrentDest;
|
|
int iError;
|
|
|
|
|
|
//
|
|
// Convert all the hex characters into digits.
|
|
//
|
|
pcCurrentSrc = (char*) abBuffer;
|
|
memset(&xnaddr, 0, sizeof(xnaddr));
|
|
for (pbCurrentDest = (BYTE*) &xnaddr; pbCurrentDest < (BYTE*) (&xnaddr + 1); pbCurrentDest++)
|
|
{
|
|
if (((*pcCurrentSrc) >= '0') && ((*pcCurrentSrc) <= '9'))
|
|
{
|
|
*pbCurrentDest = (*pcCurrentSrc) - '0';
|
|
}
|
|
else if (((*pcCurrentSrc) >= 'a') && ((*pcCurrentSrc) <= 'f'))
|
|
{
|
|
*pbCurrentDest = (*pcCurrentSrc) - 'a' + 10;
|
|
}
|
|
else if (((*pcCurrentSrc) >= 'A') && ((*pcCurrentSrc) <= 'F'))
|
|
{
|
|
*pbCurrentDest = (*pcCurrentSrc) - 'A' + 10;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If the current character is not a valid hex digit
|
|
// this is not a valid secure transport address.
|
|
//
|
|
break;
|
|
}
|
|
pcCurrentSrc++;
|
|
*pbCurrentDest <<= 4;
|
|
|
|
if (((*pcCurrentSrc) >= '0') && ((*pcCurrentSrc) <= '9'))
|
|
{
|
|
*pbCurrentDest += (*pcCurrentSrc) - '0';
|
|
}
|
|
else if (((*pcCurrentSrc) >= 'a') && ((*pcCurrentSrc) <= 'f'))
|
|
{
|
|
*pbCurrentDest += (*pcCurrentSrc) - 'a' + 10;
|
|
}
|
|
else if (((*pcCurrentSrc) >= 'A') && ((*pcCurrentSrc) <= 'F'))
|
|
{
|
|
*pbCurrentDest += (*pcCurrentSrc) - 'A' + 10;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If the current character is not a valid hex digit
|
|
// this is not a valid secure transport address.
|
|
//
|
|
break;
|
|
}
|
|
pcCurrentSrc++;
|
|
}
|
|
|
|
iError = XNetXnAddrToInAddr(&xnaddr,
|
|
(XNKID*) pullKeyID,
|
|
&m_SocketAddress.IPSocketAddress.sin_addr);
|
|
if (iError == 0)
|
|
{
|
|
DNASSERT(hr == DPN_OK);
|
|
goto Exit;
|
|
}
|
|
|
|
DPFX(DPFPREP, 1, "Couldn't convert XNet address \"%hs\" to InAddr (err = %i).",
|
|
(char*) abBuffer, iError);
|
|
DNASSERTX(! "Address exactly matching XNet address size and format failed to be converted!", 2);
|
|
|
|
//
|
|
// Continue on to trying to decode it as a
|
|
// host name.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// XNet addresses should not be recognized,
|
|
// or the string wasn't the right size.
|
|
//
|
|
}
|
|
#endif // ! DPNBUILD_XNETSECURITY
|
|
|
|
//
|
|
// If we're here, it wasn't an XNet address.
|
|
//
|
|
|
|
#ifdef DPNBUILD_NOIPV6
|
|
//
|
|
// Try to convert as a raw IPv4 address first.
|
|
//
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = inet_addr((char*) abBuffer);
|
|
if ((m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_NONE) &&
|
|
(strcmp((char*) abBuffer, "255.255.255.255") != 0))
|
|
{
|
|
#ifdef _XBOX
|
|
#pragma TODO(vanceo, "Use Xbox specific name lookup if available")
|
|
DPFX(DPFPREP, 0, "Unable to resolve IP address \"%hs\"!",
|
|
(char*) abBuffer);
|
|
DNASSERTX(! "Unable to resolve IP address!", 2);
|
|
hr = DPNERR_INVALIDHOSTADDRESS;
|
|
goto Failure;
|
|
#else // ! _XBOX
|
|
//
|
|
// Converting raw IP failed, and it wasn't supposed to
|
|
// be the broadcast address. Convert as a host name if
|
|
// we're allowed.
|
|
//
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
if (! fAllowNameResolution)
|
|
{
|
|
DPFX(DPFPREP, 2, "Couldn't convert \"%hs\" to IP address, not allowed to resolve as hostname.",
|
|
(char*) abBuffer);
|
|
hr = DPNERR_TIMEDOUT;
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
{
|
|
PHOSTENT phostent;
|
|
|
|
|
|
phostent = gethostbyname((char*) abBuffer);
|
|
if (phostent == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't get IP address from \"%hs\"!",
|
|
(char*) abBuffer);
|
|
DNASSERTX(! "Unable to resolve IP address!", 2);
|
|
hr = DPNERR_INVALIDHOSTADDRESS;
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// Select the first IP address returned.
|
|
//
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = ((IN_ADDR*) (phostent->h_addr_list[0]))->S_un.S_addr;
|
|
}
|
|
#endif // ! _XBOX
|
|
}
|
|
else
|
|
{
|
|
DNASSERT(hr == DPN_OK);
|
|
}
|
|
#else // ! DPNBUILD_NOIPV6
|
|
char szPort[32];
|
|
addrinfo addrinfoHints;
|
|
addrinfo * paddrinfoResult;
|
|
addrinfo * paddrinfoCurrent;
|
|
int iError;
|
|
|
|
|
|
//
|
|
// Try to convert the host name or raw address.
|
|
//
|
|
memset(&addrinfoHints, 0, sizeof(addrinfoHints));
|
|
if (! fAllowNameResolution)
|
|
{
|
|
addrinfoHints.ai_flags |= AI_NUMERICHOST;
|
|
}
|
|
addrinfoHints.ai_family = g_iIPAddressFamily; // IPv4, IPv6, or both
|
|
addrinfoHints.ai_socktype = SOCK_DGRAM;
|
|
addrinfoHints.ai_protocol = IPPROTO_UDP;
|
|
//addrinfoHints.ai_addrlen = 0;
|
|
//addrinfoHints.ai_canonname = NULL;
|
|
//addrinfoHints.ai_addr = NULL;
|
|
//addrinfoHints.ai_next = NULL;
|
|
|
|
wsprintfA(szPort, "%u", dwPort);
|
|
iError = getaddrinfo((char*) abBuffer, szPort, &addrinfoHints, &paddrinfoResult);
|
|
if (iError == 0)
|
|
{
|
|
//
|
|
// Pick the first valid address returned.
|
|
//
|
|
#pragma BUGBUG(vanceo, "Should we implement some mechanism to try the other results?")
|
|
paddrinfoCurrent = paddrinfoResult;
|
|
while (paddrinfoCurrent != NULL)
|
|
{
|
|
DNASSERT(paddrinfoCurrent->ai_addr != NULL);
|
|
if ((paddrinfoCurrent->ai_addr->sa_family == AF_INET) ||
|
|
(paddrinfoCurrent->ai_addr->sa_family == AF_INET6))
|
|
{
|
|
DNASSERT(paddrinfoCurrent->ai_addrlen <= sizeof(m_SocketAddress));
|
|
memcpy(&m_SocketAddress, paddrinfoCurrent->ai_addr, paddrinfoCurrent->ai_addrlen);
|
|
m_iSocketAddressSize = paddrinfoCurrent->ai_addrlen;
|
|
DNASSERT(GetPort() != 0);
|
|
freeaddrinfo(paddrinfoResult);
|
|
paddrinfoResult = NULL;
|
|
DNASSERT(hr == DPN_OK);
|
|
goto Exit;
|
|
}
|
|
|
|
DPFX(DPFPREP, 1, "Ignoring address family %u.",
|
|
paddrinfoCurrent->ai_addr->sa_family);
|
|
|
|
paddrinfoCurrent = paddrinfoCurrent->ai_next;
|
|
}
|
|
|
|
//
|
|
// We didn't find any valid addresses.
|
|
//
|
|
DPFX(DPFPREP, 0, "Got address(es) from \"%hs\", but none were IP!",
|
|
(char*) abBuffer);
|
|
freeaddrinfo(paddrinfoResult);
|
|
paddrinfoResult = NULL;
|
|
hr = DPNERR_INVALIDHOSTADDRESS;
|
|
goto Failure;
|
|
}
|
|
else
|
|
{
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
if (! fAllowNameResolution)
|
|
{
|
|
DPFX(DPFPREP, 2, "Couldn't convert \"%hs\" to IP address (err = %i), not allowed to resolve as hostname.",
|
|
(char*) abBuffer, iError);
|
|
hr = DPNERR_TIMEDOUT;
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't get IP address from \"%hs\" (err = %i)!",
|
|
(char*) abBuffer, iError);
|
|
DNASSERTX(! "Unable to resolve IP address!", 2);
|
|
hr = DPNERR_INVALIDHOSTADDRESS;
|
|
goto Failure;
|
|
}
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DPFX(DPFPREP, 0, "Hostname component wasn't a string (%u)!", dwDataType );
|
|
hr = DPNERR_ADDRESSING;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// return DPNERR_INCOMPLETEADDRESS if the host name didn't exist
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
DPFX(DPFPREP, 6, "Hostname component does not exist in address 0x%p.", pDP8Address );
|
|
hr = DPNERR_INCOMPLETEADDRESS;
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// remap everything else to an addressing failure
|
|
//
|
|
default:
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't get hostname component (0x%lx)!", hr );
|
|
hr = DPNERR_ADDRESSING;
|
|
goto Failure;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown address type
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
DPFX(DPFPREP, 8, "(0x%p) Returning [0x%lx]", this, hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::DP8AddressFromSocketAddress - convert a socket address to a DP8Address
|
|
//
|
|
// Entry: Address type
|
|
//
|
|
// Exit: Pointer to DP8Address
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::DP8AddressFromSocketAddress"
|
|
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
IDirectPlay8Address *CSocketAddress::DP8AddressFromSocketAddress( ULONGLONG * const pullKeyID,
|
|
const XNADDR * const pxnaddr,
|
|
const SP_ADDRESS_TYPE AddressType ) const
|
|
#else // ! DPNBUILD_XNETSECURITY
|
|
IDirectPlay8Address *CSocketAddress::DP8AddressFromSocketAddress( const SP_ADDRESS_TYPE AddressType ) const
|
|
#endif // ! DPNBUILD_XNETSECURITY
|
|
{
|
|
HRESULT hr;
|
|
IDirectPlay8Address * pDP8Address;
|
|
DWORD dwPort;
|
|
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
pDP8Address = NULL;
|
|
|
|
|
|
//
|
|
// create and initialize the address
|
|
//
|
|
#ifdef DPNBUILD_LIBINTERFACE
|
|
hr = DP8ACF_CreateInstance( IID_IDirectPlay8Address,
|
|
reinterpret_cast<void**>( &pDP8Address ) );
|
|
#else // ! DPNBUILD_LIBINTERFACE
|
|
hr = COM_CoCreateInstance( CLSID_DirectPlay8Address,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IDirectPlay8Address,
|
|
reinterpret_cast<void**>( &pDP8Address ),
|
|
FALSE );
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
if ( hr != S_OK )
|
|
{
|
|
DNASSERT( pDP8Address == NULL );
|
|
DPFX(DPFPREP, 0, "Failed to create DP8Address when converting socket address" );
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
DNASSERT(pullKeyID == NULL);
|
|
#endif // DPNBUILD_XNETSECURITY
|
|
|
|
//
|
|
// set SP
|
|
//
|
|
hr = IDirectPlay8Address_SetSP( pDP8Address, &CLSID_DP8SP_IPX );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to set SP type!" );
|
|
DisplayDNError( 0, hr );
|
|
goto FailureIPX;
|
|
}
|
|
|
|
//
|
|
// add on the port because it's always set
|
|
//
|
|
dwPort = NTOHS( m_SocketAddress.IPXSocketAddress.sa_socket );
|
|
hr = IDirectPlay8Address_AddComponent( pDP8Address, DPNA_KEY_PORT, &dwPort, sizeof( dwPort ), DPNA_DATATYPE_DWORD );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to set port!" );
|
|
DisplayDNError( 0, hr );
|
|
goto FailureIPX;
|
|
}
|
|
|
|
//
|
|
// add on the device or hostname depending on what type of address this is
|
|
//
|
|
switch ( AddressType )
|
|
{
|
|
case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
|
|
case SP_ADDRESS_TYPE_DEVICE:
|
|
{
|
|
GUID DeviceGuid;
|
|
|
|
|
|
GuidFromInternalAddressWithoutPort( &DeviceGuid );
|
|
hr = IDirectPlay8Address_AddComponent( pDP8Address,
|
|
DPNA_KEY_DEVICE,
|
|
&DeviceGuid,
|
|
sizeof( DeviceGuid ),
|
|
DPNA_DATATYPE_GUID );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add device!" );
|
|
DisplayDNError( 0, hr );
|
|
goto FailureIPX;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// host address type
|
|
//
|
|
case SP_ADDRESS_TYPE_READ_HOST:
|
|
case SP_ADDRESS_TYPE_HOST:
|
|
{
|
|
char HostName[ 255 ];
|
|
WCHAR WCharHostName[ sizeof( HostName ) ];
|
|
DWORD dwHostNameLength;
|
|
DWORD dwWCharHostNameLength;
|
|
|
|
|
|
//
|
|
// remove constness of parameter for broken Socket API
|
|
//
|
|
dwHostNameLength = LENGTHOF( HostName );
|
|
if ( IPXAddressToStringNoSocket( const_cast<SOCKADDR*>( &m_SocketAddress.SocketAddress ),
|
|
sizeof( m_SocketAddress.IPXSocketAddress ),
|
|
HostName,
|
|
&dwHostNameLength
|
|
) != 0 )
|
|
{
|
|
DPFERR("Error returned from IPXAddressToString");
|
|
hr = DPNERR_ADDRESSING;
|
|
goto ExitIPX;
|
|
}
|
|
|
|
//
|
|
// convert ANSI host name to WCHAR
|
|
//
|
|
dwWCharHostNameLength = LENGTHOF( WCharHostName );
|
|
hr = STR_AnsiToWide( HostName, -1, WCharHostName, &dwWCharHostNameLength );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to convert hostname to WCHAR!" );
|
|
DisplayDNError( 0, hr );
|
|
goto FailureIPX;
|
|
}
|
|
|
|
hr = IDirectPlay8Address_AddComponent( pDP8Address,
|
|
DPNA_KEY_HOSTNAME,
|
|
WCharHostName,
|
|
dwWCharHostNameLength * sizeof( WCHAR ),
|
|
DPNA_DATATYPE_STRING );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add hostname!" );
|
|
DisplayDNError( 0, hr );
|
|
goto FailureIPX;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown address type
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
ExitIPX:
|
|
return pDP8Address;
|
|
|
|
FailureIPX:
|
|
if ( pDP8Address != NULL )
|
|
{
|
|
IDirectPlay8Address_Release( pDP8Address );
|
|
pDP8Address = NULL;
|
|
}
|
|
|
|
goto ExitIPX;
|
|
break;
|
|
}
|
|
#endif // !DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_ONLYONESP
|
|
//
|
|
// set SP
|
|
//
|
|
hr = IDirectPlay8Address_SetSP( pDP8Address, &CLSID_DP8SP_TCPIP );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to set SP GUID!" );
|
|
DisplayDNError( 0, hr );
|
|
goto FailureIP;
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
|
|
switch ( AddressType )
|
|
{
|
|
case SP_ADDRESS_TYPE_DEVICE_USE_ANY_PORT:
|
|
case SP_ADDRESS_TYPE_DEVICE:
|
|
{
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
GUID DeviceGuid;
|
|
|
|
|
|
GuidFromInternalAddressWithoutPort( &DeviceGuid );
|
|
hr = IDirectPlay8Address_SetDevice( pDP8Address, &DeviceGuid );
|
|
if (hr != DPN_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't add device GUID!");
|
|
goto FailureIP;
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
break;
|
|
}
|
|
|
|
case SP_ADDRESS_TYPE_PUBLIC_HOST_ADDRESS:
|
|
case SP_ADDRESS_TYPE_READ_HOST:
|
|
case SP_ADDRESS_TYPE_HOST:
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
case SP_ADDRESS_TYPE_MULTICAST_GROUP:
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
{
|
|
TCHAR tszHostname[MAX_HOSTNAME_SIZE / sizeof(TCHAR)];
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
TCHAR * ptszCurrent;
|
|
BYTE * pbCurrent;
|
|
DWORD dwTemp;
|
|
|
|
//
|
|
// The buffer should be large enough to hold an XNet address.
|
|
//
|
|
DBG_CASSERT(MAX_HOSTNAME_SIZE > ((sizeof(XNADDR) * 2) + 1) * sizeof(WCHAR));
|
|
#endif // DPNBUILD_XNETSECURITY
|
|
#ifndef DPNBUILD_NOIPV6
|
|
if (GetFamily() == AF_INET6)
|
|
{
|
|
DBG_CASSERT((sizeof(tszHostname) / sizeof(TCHAR)) >= INET6_ADDRSTRLEN);
|
|
#ifdef UNICODE
|
|
DNIpv6AddressToStringW(&m_SocketAddress.IPv6SocketAddress.sin6_addr, tszHostname);
|
|
#else // ! UNICODE
|
|
Won't compile because we haven't implemented DNIpv6AddressToStringA
|
|
#endif // ! UNICODE
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
{
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
if (pxnaddr != NULL)
|
|
{
|
|
ptszCurrent = tszHostname;
|
|
pbCurrent = (BYTE*) pxnaddr;
|
|
for(dwTemp = 0; dwTemp < sizeof(XNADDR); dwTemp++)
|
|
{
|
|
ptszCurrent += wsprintf(ptszCurrent, _T("%02X"), (*pbCurrent));
|
|
pbCurrent++;
|
|
}
|
|
}
|
|
else if ((pullKeyID != NULL) &&
|
|
(m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr != INADDR_BROADCAST))
|
|
{
|
|
int iError;
|
|
XNADDR xnaddr;
|
|
#ifdef DBG
|
|
XNKID xnkid;
|
|
#endif // DBG
|
|
|
|
|
|
DBG_CASSERT(sizeof(xnkid) == sizeof(*pullKeyID));
|
|
#ifdef DPNBUILD_ONLYONEADAPTER
|
|
IN_ADDR inaddrToUse;
|
|
|
|
//
|
|
// Special case 0.0.0.0, the XNet library expects the loopback address
|
|
// instead when retrieving the local address.
|
|
//
|
|
inaddrToUse = m_SocketAddress.IPSocketAddress.sin_addr;
|
|
if (inaddrToUse.S_un.S_addr == 0)
|
|
{
|
|
inaddrToUse.S_un.S_addr = IP_LOOPBACK_ADDRESS;
|
|
}
|
|
iError = XNetInAddrToXnAddr(inaddrToUse,
|
|
#else // ! DPNBUILD_ONLYONEADAPTER
|
|
iError = XNetInAddrToXnAddr(m_SocketAddress.IPSocketAddress.sin_addr,
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
&xnaddr,
|
|
#ifdef DBG
|
|
&xnkid);
|
|
#else // ! DBG
|
|
NULL);
|
|
#endif // ! DBG
|
|
|
|
if (iError != 0)
|
|
{
|
|
DPFX(DPFPREP, 0, "Converting XNet address to InAddr failed (err = %i)!",
|
|
iError);
|
|
DNASSERT(FALSE);
|
|
//hr = DPNERR_NOCONNECTION;
|
|
goto FailureIP;
|
|
}
|
|
|
|
#ifdef DPNBUILD_ONLYONEADAPTER
|
|
if (inaddrToUse.S_un.S_addr != IP_LOOPBACK_ADDRESS)
|
|
#endif // DPNBUILD_ONLYONEADAPTER
|
|
{
|
|
#ifdef DBG
|
|
DNASSERT(memcmp(&xnkid, pullKeyID, sizeof(xnkid)) == 0);
|
|
#endif // DBG
|
|
}
|
|
|
|
ptszCurrent = tszHostname;
|
|
pbCurrent = (BYTE*) (&xnaddr);
|
|
for(dwTemp = 0; dwTemp < sizeof(XNADDR); dwTemp++)
|
|
{
|
|
ptszCurrent += wsprintf(tszHostname, _T("%02X"), (*pbCurrent));
|
|
pbCurrent++;
|
|
}
|
|
}
|
|
else
|
|
#endif // DPNBUILD_XNETSECURITY
|
|
{
|
|
wsprintf(tszHostname, _T("%u.%u.%u.%u"),
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b1,
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b2,
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b3,
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b4);
|
|
}
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
hr = IDirectPlay8Address_AddComponent( pDP8Address,
|
|
DPNA_KEY_HOSTNAME,
|
|
tszHostname,
|
|
(_tcslen(tszHostname) + 1) * sizeof (TCHAR),
|
|
DPNA_DATATYPE_STRING );
|
|
#else // ! UNICODE
|
|
hr = IDirectPlay8Address_AddComponent( pDP8Address,
|
|
DPNA_KEY_HOSTNAME,
|
|
tszHostname,
|
|
(_tcslen(tszHostname) + 1) * sizeof (TCHAR),
|
|
DPNA_DATATYPE_STRING_ANSI );
|
|
#endif // ! UNICODE
|
|
if (hr != DPN_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't add hostname component!");
|
|
goto FailureIP;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
dwPort = NTOHS( m_SocketAddress.IPSocketAddress.sin_port );
|
|
|
|
hr = IDirectPlay8Address_AddComponent( pDP8Address,
|
|
DPNA_KEY_PORT,
|
|
&dwPort,
|
|
(sizeof(dwPort)),
|
|
DPNA_DATATYPE_DWORD );
|
|
if (hr != DPN_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't add port component!");
|
|
goto FailureIP;
|
|
}
|
|
|
|
ExitIP:
|
|
|
|
return pDP8Address;
|
|
|
|
FailureIP:
|
|
|
|
if ( pDP8Address != NULL )
|
|
{
|
|
IDirectPlay8Address_Release( pDP8Address );
|
|
pDP8Address = NULL;
|
|
}
|
|
|
|
goto ExitIP;
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::CompareToBaseAddress - compare this address to a 'base' address
|
|
// of this class
|
|
//
|
|
// Entry: Pointer to base address
|
|
//
|
|
// Exit: Integer indicating relative magnitude:
|
|
// 0 = items equal
|
|
// -1 = other item is of greater magnitude
|
|
// 1 = this item is of lesser magnitude
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::CompareToBaseAddress"
|
|
|
|
INT_PTR CSocketAddress::CompareToBaseAddress( const SOCKADDR *const pBaseAddress ) const
|
|
{
|
|
DNASSERT( pBaseAddress != NULL );
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
const SOCKADDR_IN6 *pBaseIPv6Address;
|
|
|
|
|
|
if ( pBaseAddress->sa_family != m_SocketAddress.SocketAddress.sa_family )
|
|
{
|
|
DNASSERT(pBaseAddress->sa_family == AF_INET);
|
|
return -1;
|
|
}
|
|
|
|
pBaseIPv6Address = reinterpret_cast<const SOCKADDR_IN6*>( pBaseAddress );
|
|
return (memcmp(&m_SocketAddress.IPv6SocketAddress.sin6_addr,
|
|
&pBaseIPv6Address->sin6_addr,
|
|
sizeof(m_SocketAddress.IPv6SocketAddress.sin6_addr)));
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
const SOCKADDR_IPX *pBaseIPXAddress;
|
|
|
|
|
|
DNASSERT( pBaseAddress->sa_family == m_SocketAddress.SocketAddress.sa_family );
|
|
pBaseIPXAddress = reinterpret_cast<const SOCKADDR_IPX *>( pBaseAddress );
|
|
DBG_CASSERT( OFFSETOF( SOCKADDR_IPX, sa_nodenum ) == OFFSETOF( SOCKADDR_IPX, sa_netnum ) + sizeof( pBaseIPXAddress->sa_netnum ) );
|
|
return memcmp( &m_SocketAddress.IPXSocketAddress.sa_nodenum,
|
|
&pBaseIPXAddress->sa_nodenum,
|
|
sizeof( pBaseIPXAddress->sa_nodenum ) );
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
const SOCKADDR_IN *pBaseIPAddress;
|
|
|
|
DNASSERT( GetFamily() == AF_INET );
|
|
|
|
#ifndef DPNBUILD_NOIPV6
|
|
if ( pBaseAddress->sa_family != m_SocketAddress.SocketAddress.sa_family )
|
|
{
|
|
DNASSERT(pBaseAddress->sa_family == AF_INET6);
|
|
return -1;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
pBaseIPAddress = reinterpret_cast<const SOCKADDR_IN*>( pBaseAddress );
|
|
if ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == pBaseIPAddress->sin_addr.S_un.S_addr )
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
if ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr < pBaseIPAddress->sin_addr.S_un.S_addr )
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::EnumAdapters - enumerate all of the adapters for this machine
|
|
//
|
|
// Entry: Pointer to enum adapters data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::EnumAdapters"
|
|
|
|
HRESULT CSocketAddress::EnumAdapters( SPENUMADAPTERSDATA *const pEnumData ) const
|
|
{
|
|
#ifndef DPNBUILD_NOIPX
|
|
if (GetFamily() == AF_IPX)
|
|
{
|
|
return EnumIPXAdapters(pEnumData);
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_NOIPX
|
|
{
|
|
#ifdef DPNBUILD_NOIPV6
|
|
return EnumIPv4Adapters(pEnumData);
|
|
#else // ! DPNBUILD_NOIPV6
|
|
return EnumIPv6and4Adapters(pEnumData);
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::EnumIPXAdapters - enumerate all of the adapters for this machine
|
|
//
|
|
// Entry: Pointer to enum adapters data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::EnumIPXAdapters"
|
|
|
|
HRESULT CSocketAddress::EnumIPXAdapters( SPENUMADAPTERSDATA *const pEnumData ) const
|
|
{
|
|
HRESULT hr;
|
|
CPackedBuffer PackedBuffer;
|
|
SOCKET TestSocket;
|
|
INT iWSAReturn;
|
|
DWORD dwAddressCount;
|
|
union
|
|
{
|
|
SOCKADDR_IPX IPXSocketAddress;
|
|
SOCKADDR SocketAddress;
|
|
} SockAddr;
|
|
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
|
|
|
|
DNASSERT( pEnumData != NULL );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
DEBUG_ONLY( memset( pEnumData->pAdapterData, 0xAA, pEnumData->dwAdapterDataSize ) );
|
|
PackedBuffer.Initialize( pEnumData->pAdapterData, pEnumData->dwAdapterDataSize );
|
|
pEnumData->dwAdapterCount = 0;
|
|
TestSocket = INVALID_SOCKET;
|
|
dwAddressCount = 0;
|
|
|
|
//
|
|
// create a socket and attempt to query for all of the IPX addresses. If
|
|
// that fails, fall back to using just the address from 'getsockname'.
|
|
//
|
|
TestSocket = socket( GetFamily(), SOCK_DGRAM, NSPROTO_IPX );
|
|
if ( TestSocket == INVALID_SOCKET )
|
|
{
|
|
DWORD dwWSAError;
|
|
|
|
|
|
hr = DPNERR_UNSUPPORTED;
|
|
dwWSAError = WSAGetLastError();
|
|
DPFX(DPFPREP, 0, "Failed to create IPX socket when enumerating adapters!" );
|
|
DisplayWinsockError( 0, dwWSAError );
|
|
goto Failure;
|
|
}
|
|
|
|
memset( &SockAddr, 0x00, sizeof( SockAddr ) );
|
|
SockAddr.IPXSocketAddress.sa_family = GetFamily();
|
|
|
|
iWSAReturn = bind( TestSocket, &SockAddr.SocketAddress, sizeof( SockAddr.IPXSocketAddress ) );
|
|
if ( iWSAReturn == SOCKET_ERROR )
|
|
{
|
|
DWORD dwWSAError;
|
|
|
|
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
dwWSAError = WSAGetLastError();
|
|
DPFX(DPFPREP, 0, "Failed to bind IPX socket when enumerating adapters!" );
|
|
DisplayWinsockError( 0, dwWSAError );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// NOTE: THE CODE TO EXTRACT ALL IPX ADDRESSES ON NT HAS BEEN DISABLED BECAUSE
|
|
// NT TREATS ALL OF THEM AS THE SAME ONCE THEY ARE BOUND TO THE NETWORK. IF THE
|
|
// CORE IS ATTEMPTING TO BIND TO ALL ADAPTERS THIS WILL CAUSE ALL OF THE BINDS
|
|
// AFTER THE FIRST TO FAIL!
|
|
//
|
|
|
|
// iIPXAdapterCount = 0;
|
|
// iIPXAdapterCountSize = sizeof( iIPXAdapterCount );
|
|
// iWSAReturn = getsockopt( TestSocket,
|
|
// NSPROTO_IPX,
|
|
// IPX_MAX_ADAPTER_NUM,
|
|
// reinterpret_cast<char*>( &iIPXAdapterCount ),
|
|
// &iIPXAdapterCountSize );
|
|
// if ( iWSAReturn != 0 )
|
|
// {
|
|
// DWORD dwWSAError;
|
|
//
|
|
//
|
|
// dwWSAError = WSAGetLastError();
|
|
// switch ( dwWSAError )
|
|
// {
|
|
// //
|
|
// // can't enumerate adapters on this machine, fallback to getsockname()
|
|
// //
|
|
// case WSAENOPROTOOPT:
|
|
// {
|
|
INT iReturn;
|
|
INT iSocketNameSize;
|
|
union
|
|
{
|
|
SOCKADDR SocketAddress;
|
|
SOCKADDR_IPX SocketAddressIPX;
|
|
} SocketAddress;
|
|
|
|
|
|
memset( &SocketAddress, 0x00, sizeof( SocketAddress ) );
|
|
iSocketNameSize = sizeof( SocketAddress );
|
|
iReturn = getsockname( TestSocket, &SocketAddress.SocketAddress, &iSocketNameSize );
|
|
if ( iReturn != 0 )
|
|
{
|
|
DWORD dwWSAError;
|
|
|
|
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
dwWSAError = WSAGetLastError();
|
|
DPFX(DPFPREP, 0, "Failed to get socket name enumerating IPX sockets!", dwWSAError );
|
|
goto Failure;
|
|
}
|
|
else
|
|
{
|
|
GUID SocketAddressGUID;
|
|
|
|
|
|
SocketAddress.SocketAddressIPX.sa_socket = 0;
|
|
GuidFromAddress( &SocketAddressGUID, &SocketAddress.SocketAddress );
|
|
|
|
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.",
|
|
g_IPXAdapterString,
|
|
SocketAddressGUID.Data1,
|
|
SocketAddressGUID.Data2,
|
|
SocketAddressGUID.Data3,
|
|
SocketAddressGUID.Data4[0],
|
|
SocketAddressGUID.Data4[1],
|
|
SocketAddressGUID.Data4[2],
|
|
SocketAddressGUID.Data4[3],
|
|
SocketAddressGUID.Data4[4],
|
|
SocketAddressGUID.Data4[5],
|
|
SocketAddressGUID.Data4[6],
|
|
SocketAddressGUID.Data4[7]);
|
|
|
|
hr = AddInfoToBuffer( &PackedBuffer, g_IPXAdapterString, &SocketAddressGUID, 0 );
|
|
if ( ( hr != DPN_OK ) && ( hr != DPNERR_BUFFERTOOSMALL ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add adapter (getsockname)!" );
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
|
|
dwAddressCount++;
|
|
}
|
|
|
|
// break;
|
|
// }
|
|
//
|
|
// //
|
|
// // other Winsock error
|
|
// //
|
|
// default:
|
|
// {
|
|
// DWORD dwWSAError;
|
|
//
|
|
//
|
|
// hr = DPNERR_OUTOFMEMORY;
|
|
// dwWSAError = WSAGetLastError();
|
|
// DPFX(DPFPREP, 0, "Failed to get IPX adapter count!" );
|
|
// DisplayWinsockError( 0, dwWSAError );
|
|
// goto Failure;
|
|
//
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// while ( iIPXAdapterCount != 0 )
|
|
// {
|
|
// IPX_ADDRESS_DATA IPXData;
|
|
// int iIPXDataSize;
|
|
//
|
|
//
|
|
// iIPXAdapterCount--;
|
|
// memset( &IPXData, 0x00, sizeof( IPXData ) );
|
|
// iIPXDataSize = sizeof( IPXData );
|
|
// IPXData.adapternum = iIPXAdapterCount;
|
|
//
|
|
// iWSAReturn = p_getsockopt( TestSocket,
|
|
// NSPROTO_IPX,
|
|
// IPX_ADDRESS,
|
|
// reinterpret_cast<char*>( &IPXData ),
|
|
// &iIPXDataSize );
|
|
// if ( iWSAReturn != 0 )
|
|
// {
|
|
// DPFX(DPFPREP, 0, "Failed to get adapter information for adapter: 0x%x", ( iIPXAdapterCount + 1 ) );
|
|
// }
|
|
// else
|
|
// {
|
|
// char Buffer[ 500 ];
|
|
// GUID SocketAddressGUID;
|
|
// union
|
|
// {
|
|
// SOCKADDR_IPX IPXSocketAddress;
|
|
// SOCKADDR SocketAddress;
|
|
// } SocketAddress;
|
|
//
|
|
//
|
|
// wsprintf( Buffer,
|
|
// "IPX Adapter %d - (%02X%02X%02X%02X-%02X%02X%02X%02X%02X%02X)",
|
|
// ( iIPXAdapterCount + 1 ),
|
|
// IPXData.netnum[ 0 ],
|
|
// IPXData.netnum[ 1 ],
|
|
// IPXData.netnum[ 2 ],
|
|
// IPXData.netnum[ 3 ],
|
|
// IPXData.nodenum[ 0 ],
|
|
// IPXData.nodenum[ 1 ],
|
|
// IPXData.nodenum[ 2 ],
|
|
// IPXData.nodenum[ 3 ],
|
|
// IPXData.nodenum[ 4 ],
|
|
// IPXData.nodenum[ 5 ] );
|
|
//
|
|
// memset( &SocketAddress, 0x00, sizeof( SocketAddress ) );
|
|
// SocketAddress.IPXSocketAddress.sa_family = GetFamily();
|
|
// DBG_CASSERT( sizeof( SocketAddress.IPXSocketAddress.sa_netnum ) == sizeof( IPXData.netnum ) );
|
|
// memcpy( &SocketAddress.IPXSocketAddress.sa_netnum, IPXData.netnum, sizeof( SocketAddress.IPXSocketAddress.sa_netnum ) );
|
|
// DBG_CASSERT( sizeof( SocketAddress.IPXSocketAddress.sa_nodenum ) == sizeof( IPXData.nodenum ) );
|
|
// memcpy( &SocketAddress.IPXSocketAddress.sa_nodenum, IPXData.nodenum, sizeof( SocketAddress.IPXSocketAddress.sa_nodenum ) );
|
|
// GuidFromAddress( SocketAddressGUID, SocketAddress.SocketAddress );
|
|
//
|
|
// hr = AddInfoToBuffer( &PackedBuffer, Buffer, &SocketAddressGUID, 0 );
|
|
// if ( ( hr != DPN_OK ) && ( hr != DPNERR_BUFFERTOOSMALL ) )
|
|
// {
|
|
// DPFX(DPFPREP, 0, "Failed to add adapter (getsockname)!" );
|
|
// DisplayDNError( 0, hr );
|
|
// goto Failure;
|
|
// }
|
|
//
|
|
// dwAddressCount++;
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// // if there was one adapter added, we can return 'All Adapters'
|
|
// //
|
|
// if ( dwAddressCount != 0 )
|
|
// {
|
|
// dwAddressCount++;
|
|
// hr = AddInfoToBuffer( &PackedBuffer, g_AllAdaptersString, &ALL_ADAPTERS_GUID, 0 );
|
|
// if ( ( hr != DPN_OK ) && ( hr != DPNERR_BUFFERTOOSMALL ) )
|
|
// {
|
|
// DPFX(DPFPREP, 0, "Failed to add 'All Adapters'" );
|
|
// DisplayDNError( 0, hr );
|
|
// goto Failure;
|
|
// }
|
|
// }
|
|
|
|
pEnumData->dwAdapterCount = dwAddressCount;
|
|
pEnumData->dwAdapterDataSize = PackedBuffer.GetSizeRequired();
|
|
|
|
Exit:
|
|
if ( TestSocket != INVALID_SOCKET )
|
|
{
|
|
closesocket( TestSocket );
|
|
TestSocket = INVALID_SOCKET;
|
|
}
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::EnumIPv4Adapters - enumerate all of the IPv4 adapters for this machine
|
|
//
|
|
// Entry: Pointer to enum adapters data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::EnumIPv4Adapters"
|
|
|
|
HRESULT CSocketAddress::EnumIPv4Adapters( SPENUMADAPTERSDATA *const pEnumData ) const
|
|
{
|
|
HRESULT hr = DPN_OK;
|
|
#if !defined(DPNBUILD_NOWINSOCK2) || defined(DBG)
|
|
DWORD dwError;
|
|
#endif // !DPNBUILD_NOWINSOCK2 OR DBG
|
|
SOCKADDR_IN saddrinTemp;
|
|
const HOSTENT * pHostData;
|
|
IN_ADDR ** ppinaddrTemp;
|
|
DWORD dwAddressCount;
|
|
BOOL fFoundPrivateICS = FALSE;
|
|
IN_ADDR * pinaddrBuffer = NULL;
|
|
DWORD dwIndex;
|
|
ULONG ulAdapterInfoBufferSize = 0;
|
|
GUID guidAdapter;
|
|
DWORD dwDeviceFlags;
|
|
CPackedBuffer PackedBuffer;
|
|
char acBuffer[512];
|
|
WCHAR wszIPAddress[512];
|
|
#ifndef DPNBUILD_NOWINSOCK2
|
|
HMODULE hIpHlpApiDLL;
|
|
IP_ADAPTER_INFO * pCurrentAdapterInfo;
|
|
PIP_ADDR_STRING pIPAddrString;
|
|
PFNGETADAPTERSINFO pfnGetAdaptersInfo;
|
|
IP_ADAPTER_INFO * pAdapterInfoBuffer = NULL;
|
|
const char * pszIPAddress;
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
DWORD dwMcastInterfaceIndex;
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
#endif // ! DPNBUILD_NOWINSOCK2
|
|
|
|
|
|
DPFX(DPFPREP, 6, "Parameters: (0x%p)", pEnumData);
|
|
|
|
|
|
PackedBuffer.Initialize( pEnumData->pAdapterData, pEnumData->dwAdapterDataSize );
|
|
|
|
ZeroMemory(&saddrinTemp, sizeof(saddrinTemp));
|
|
saddrinTemp.sin_family = GetFamily();
|
|
|
|
|
|
//
|
|
// Get the list of local IPs from WinSock. We use this method since it's
|
|
// available on all platforms and conveniently returns the loopback address
|
|
// when no valid adapters are currently available.
|
|
//
|
|
|
|
if (gethostname(acBuffer, sizeof(acBuffer)) == SOCKET_ERROR)
|
|
{
|
|
#ifdef DBG
|
|
dwError = WSAGetLastError();
|
|
DPFX(DPFPREP, 0, "Failed to get host name into fixed size buffer (err = %u)!", dwError);
|
|
DisplayWinsockError(0, dwError);
|
|
#endif // DBG
|
|
hr = DPNERR_GENERIC;
|
|
goto Failure;
|
|
}
|
|
|
|
pHostData = gethostbyname(acBuffer);
|
|
if (pHostData == NULL)
|
|
{
|
|
#ifdef DBG
|
|
dwError = WSAGetLastError();
|
|
DPFX(DPFPREP, 0, "Failed to get host data (err = %u)!", dwError);
|
|
DisplayWinsockError(0, dwError);
|
|
#endif // DBG
|
|
hr = DPNERR_GENERIC;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// Count number of addresses.
|
|
//
|
|
dwAddressCount = 0;
|
|
ppinaddrTemp = (IN_ADDR**) (pHostData->h_addr_list);
|
|
while ((*ppinaddrTemp) != NULL)
|
|
{
|
|
//
|
|
// Remember if it's 192.168.0.1. See below
|
|
//
|
|
if ((*ppinaddrTemp)->S_un.S_addr == IP_PRIVATEICS_ADDRESS)
|
|
{
|
|
fFoundPrivateICS = TRUE;
|
|
}
|
|
|
|
dwAddressCount++;
|
|
ppinaddrTemp++;
|
|
}
|
|
|
|
if (dwAddressCount == 0)
|
|
{
|
|
DPFX(DPFPREP, 1, "No IP addresses, forcing loopback address.");
|
|
DNASSERTX(!" No IP addresses!", 2);
|
|
dwAddressCount++;
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 3, "WinSock reported %u addresses.", dwAddressCount);
|
|
}
|
|
|
|
|
|
//
|
|
// Winsock says we should copy this data before any other Winsock calls.
|
|
//
|
|
// We also use this as an opportunity to ensure that the order returned to the caller is
|
|
// to our liking. In particular, we make sure the private address 192.168.0.1 appears
|
|
// first.
|
|
//
|
|
DNASSERT(pHostData->h_length == sizeof(IN_ADDR));
|
|
pinaddrBuffer = (IN_ADDR*) DNMalloc(dwAddressCount * sizeof(IN_ADDR));
|
|
if (pinaddrBuffer == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to allocate memory to store copy of addresses!");
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
dwIndex = 0;
|
|
|
|
//
|
|
// First, store 192.168.0.1 if we found it.
|
|
//
|
|
if (fFoundPrivateICS)
|
|
{
|
|
pinaddrBuffer[dwIndex].S_un.S_addr = IP_PRIVATEICS_ADDRESS;
|
|
dwIndex++;
|
|
}
|
|
|
|
//
|
|
// Then copy the rest.
|
|
//
|
|
ppinaddrTemp = (IN_ADDR**) (pHostData->h_addr_list);
|
|
while ((*ppinaddrTemp) != NULL)
|
|
{
|
|
if ((*ppinaddrTemp)->S_un.S_addr != IP_PRIVATEICS_ADDRESS)
|
|
{
|
|
pinaddrBuffer[dwIndex].S_un.S_addr = (*ppinaddrTemp)->S_un.S_addr;
|
|
dwIndex++;
|
|
}
|
|
|
|
ppinaddrTemp++;
|
|
}
|
|
|
|
//
|
|
// If we didn't have any addresses, slap in the loopback address.
|
|
//
|
|
if (dwIndex == 0)
|
|
{
|
|
pinaddrBuffer[0].S_un.S_addr = IP_LOOPBACK_ADDRESS;
|
|
dwIndex++;
|
|
}
|
|
|
|
|
|
DNASSERT(dwIndex == dwAddressCount);
|
|
|
|
|
|
//
|
|
// Now we try to generate names and GUIDs for these IP addresses.
|
|
// We'll use what IPHLPAPI reports for a name if possible, and fall
|
|
// back to just using the IP address string as the name.
|
|
//
|
|
|
|
#ifndef DPNBUILD_NOWINSOCK2
|
|
//
|
|
// Load the IPHLPAPI module and get the adapter list if possible.
|
|
//
|
|
hIpHlpApiDLL = LoadLibrary(c_tszIPHelperDLLName);
|
|
if (hIpHlpApiDLL != NULL)
|
|
{
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
PFNGETBESTINTERFACE pfnGetBestInterface;
|
|
|
|
|
|
pfnGetBestInterface = (PFNGETBESTINTERFACE) GetProcAddress(hIpHlpApiDLL, _TWINCE("GetBestInterface"));
|
|
if (pfnGetBestInterface != NULL)
|
|
{
|
|
//
|
|
// Ask IPHLPAPI for its opinion on the best multicast interface.
|
|
// We use an arbitrary multicast address, and assume that the
|
|
// TCP/IP stack doesn't treat individual multicast addresses
|
|
// differently.
|
|
//
|
|
dwError = pfnGetBestInterface(SAMPLE_MULTICAST_ADDRESS, &dwMcastInterfaceIndex);
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't determine best multicast interface index (err = %u)! Continuing.",
|
|
dwError);
|
|
dwMcastInterfaceIndex = INVALID_INTERFACE_INDEX;
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 7, "Best interface for multicasting is index 0x%x.",
|
|
dwMcastInterfaceIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = GetLastError();
|
|
DPFX(DPFPREP, 0, "Couldn't load \"GetBestInterface\" function (err = %u)! Continuing.",
|
|
dwError);
|
|
}
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
|
|
pfnGetAdaptersInfo = (PFNGETADAPTERSINFO) GetProcAddress(hIpHlpApiDLL, _TWINCE("GetAdaptersInfo"));
|
|
if (pfnGetAdaptersInfo != NULL)
|
|
{
|
|
//
|
|
// Keep resizing the buffer until there's enough room.
|
|
//
|
|
do
|
|
{
|
|
dwError = pfnGetAdaptersInfo(pAdapterInfoBuffer,
|
|
&ulAdapterInfoBufferSize);
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// We got all the info we're going to get. Make sure it
|
|
// was something.
|
|
//
|
|
if (ulAdapterInfoBufferSize == 0)
|
|
{
|
|
DPFX(DPFPREP, 0, "GetAdaptersInfo returned 0 byte size requirement! Ignoring.");
|
|
|
|
//
|
|
// Get rid of the buffer if allocated.
|
|
//
|
|
if (pAdapterInfoBuffer != NULL)
|
|
{
|
|
DNFree(pAdapterInfoBuffer);
|
|
pAdapterInfoBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// Continue with exiting the loop.
|
|
//
|
|
}
|
|
#ifdef DBG
|
|
else
|
|
{
|
|
int iStrLen;
|
|
char szIPList[256];
|
|
char * pszCurrentIP;
|
|
|
|
|
|
//
|
|
// Print out all the adapters for debugging purposes.
|
|
//
|
|
pCurrentAdapterInfo = pAdapterInfoBuffer;
|
|
while (pCurrentAdapterInfo != NULL)
|
|
{
|
|
//
|
|
// Initialize IP address list string.
|
|
//
|
|
szIPList[0] = '\0';
|
|
pszCurrentIP = szIPList;
|
|
|
|
|
|
//
|
|
// Loop through all addresses for this adapter.
|
|
//
|
|
pIPAddrString = &pCurrentAdapterInfo->IpAddressList;
|
|
while (pIPAddrString != NULL)
|
|
{
|
|
//
|
|
// Copy the IP address string (if there's enough room),
|
|
// then tack on a space and NULL terminator.
|
|
//
|
|
iStrLen = strlen(pIPAddrString->IpAddress.String);
|
|
if ((pszCurrentIP + iStrLen + 2) < (szIPList + sizeof(szIPList)))
|
|
{
|
|
memcpy(pszCurrentIP, pIPAddrString->IpAddress.String, iStrLen);
|
|
pszCurrentIP += iStrLen;
|
|
(*pszCurrentIP) = ' ';
|
|
pszCurrentIP++;
|
|
(*pszCurrentIP) = '\0';
|
|
pszCurrentIP++;
|
|
}
|
|
|
|
pIPAddrString = pIPAddrString->Next;
|
|
}
|
|
|
|
|
|
DPFX(DPFPREP, 8, "Adapter index %u IPs = %hs, %hs, \"%hs\".",
|
|
pCurrentAdapterInfo->Index,
|
|
szIPList,
|
|
pCurrentAdapterInfo->AdapterName,
|
|
pCurrentAdapterInfo->Description);
|
|
|
|
|
|
//
|
|
// Go to next adapter.
|
|
//
|
|
pCurrentAdapterInfo = pCurrentAdapterInfo->Next;
|
|
}
|
|
} // end else (got valid buffer size)
|
|
#endif // DBG
|
|
|
|
break;
|
|
}
|
|
|
|
if ((dwError != ERROR_BUFFER_OVERFLOW) &&
|
|
(dwError != ERROR_INSUFFICIENT_BUFFER))
|
|
{
|
|
DPFX(DPFPREP, 0, "GetAdaptersInfo failed (err = 0x%lx)! Ignoring.", dwError);
|
|
|
|
//
|
|
// Get rid of the buffer if allocated, and then bail out of
|
|
// the loop.
|
|
//
|
|
if (pAdapterInfoBuffer != NULL)
|
|
{
|
|
DNFree(pAdapterInfoBuffer);
|
|
pAdapterInfoBuffer = NULL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// If we're here, then we need to reallocate the buffer.
|
|
//
|
|
if (pAdapterInfoBuffer != NULL)
|
|
{
|
|
DNFree(pAdapterInfoBuffer);
|
|
pAdapterInfoBuffer = NULL;
|
|
}
|
|
|
|
pAdapterInfoBuffer = (IP_ADAPTER_INFO*) DNMalloc(ulAdapterInfoBufferSize);
|
|
if (pAdapterInfoBuffer == NULL)
|
|
{
|
|
//
|
|
// Couldn't allocate memory. Bail out of the loop.
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Successfully allocated buffer. Try again.
|
|
//
|
|
}
|
|
while (TRUE);
|
|
|
|
|
|
//
|
|
// We get here in all cases, so we may have failed to get an info
|
|
// buffer. That's fine, we'll use the fallback to generate the
|
|
// names.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
#ifdef DBG
|
|
dwError = GetLastError();
|
|
DPFX(DPFPREP, 0, "Failed to get proc address for GetAdaptersInfo!");
|
|
DisplayErrorCode(0, dwError);
|
|
#endif // DBG
|
|
|
|
//
|
|
// Continue. We'll use the fallback to generate the names.
|
|
//
|
|
}
|
|
|
|
|
|
//
|
|
// We don't need the library anymore.
|
|
//
|
|
FreeLibrary(hIpHlpApiDLL);
|
|
hIpHlpApiDLL = NULL;
|
|
}
|
|
else
|
|
{
|
|
#ifdef DBG
|
|
dwError = GetLastError();
|
|
DPFX(DPFPREP, 0, "Failed to get proc address for GetAdaptersInfo!");
|
|
DisplayErrorCode(0, dwError);
|
|
#endif // DBG
|
|
|
|
//
|
|
// Continue. We'll use the fallback to generate the names.
|
|
//
|
|
}
|
|
#endif // !DPNBUILD_NOWINSOCK2
|
|
|
|
//
|
|
// Loop through all IP addresses, generating names and GUIDs.
|
|
//
|
|
for(dwIndex = 0; dwIndex < dwAddressCount; dwIndex++)
|
|
{
|
|
//
|
|
// Start off assuming this IP address won't have any special
|
|
// flags.
|
|
//
|
|
dwDeviceFlags = 0;
|
|
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
//
|
|
// If this is the first device and we couldn't use IPHLPAPI to
|
|
// determine the best multicast interface, then just say the
|
|
// default multicast interface is the first (for lack of a
|
|
// better idea).
|
|
//
|
|
#ifdef DPNBUILD_NOWINSOCK2
|
|
if (dwIndex == 0)
|
|
#else // ! DPNBUILD_NOWINSOCK2
|
|
if ((dwIndex == 0) && (dwMcastInterfaceIndex == INVALID_INTERFACE_INDEX))
|
|
#endif // ! DPNBUILD_NOWINSOCK2
|
|
{
|
|
dwDeviceFlags |= DPNSPINFO_DEFAULTMULTICASTDEVICE;
|
|
}
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
|
|
|
|
#ifdef DPNBUILD_NOWINSOCK2
|
|
DNinet_ntow(pinaddrBuffer[dwIndex], wszIPAddress);
|
|
#else // ! DPNBUILD_NOWINSOCK2
|
|
//
|
|
// Get the IP address string. We don't make any other WinSock
|
|
// calls, so holding on to the pointer is OK. This pointer
|
|
// may be used as the device name string, too.
|
|
//
|
|
pszIPAddress = inet_ntoa(pinaddrBuffer[dwIndex]);
|
|
|
|
//
|
|
// Look for an adapter name from IPHLPAPI if possible.
|
|
//
|
|
if (pAdapterInfoBuffer != NULL)
|
|
{
|
|
pCurrentAdapterInfo = pAdapterInfoBuffer;
|
|
while (pCurrentAdapterInfo != NULL)
|
|
{
|
|
//
|
|
// Look for matching IP.
|
|
//
|
|
pIPAddrString = &pCurrentAdapterInfo->IpAddressList;
|
|
while (pIPAddrString != NULL)
|
|
{
|
|
if (strcmp(pIPAddrString->IpAddress.String, pszIPAddress) == 0)
|
|
{
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
//
|
|
// If it's the interface reported earlier as the best
|
|
// multicast interface, remember that fact.
|
|
//
|
|
if (pCurrentAdapterInfo->Index == dwMcastInterfaceIndex)
|
|
{
|
|
DPFX(DPFPREP, 7, "Found %hs under adapter index %u (\"%hs\"), and it's the best multicast interface.",
|
|
pszIPAddress, pCurrentAdapterInfo->Index,
|
|
pCurrentAdapterInfo->Description);
|
|
DNASSERT(pCurrentAdapterInfo->Index != INVALID_INTERFACE_INDEX);
|
|
|
|
dwDeviceFlags |= DPNSPINFO_DEFAULTMULTICASTDEVICE;
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
{
|
|
DPFX(DPFPREP, 9, "Found %hs under adapter index %u (\"%hs\").",
|
|
pszIPAddress, pCurrentAdapterInfo->Index,
|
|
pCurrentAdapterInfo->Description);
|
|
}
|
|
|
|
|
|
//
|
|
// Build the name string.
|
|
//
|
|
DBG_CASSERT(sizeof(acBuffer) > MAX_ADAPTER_DESCRIPTION_LENGTH);
|
|
wsprintfA(acBuffer,
|
|
c_szAdapterNameTemplate,
|
|
pCurrentAdapterInfo->Description,
|
|
pszIPAddress);
|
|
|
|
//
|
|
// Point the name string to the buffer and drop out
|
|
// of the loop.
|
|
//
|
|
pszIPAddress = acBuffer;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Move to next IP address.
|
|
//
|
|
pIPAddrString = pIPAddrString->Next;
|
|
}
|
|
|
|
|
|
//
|
|
// If we found the address, stop looping through adapters,
|
|
// too.
|
|
//
|
|
if (pszIPAddress == acBuffer)
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Otherwise, go to next adapter.
|
|
//
|
|
pCurrentAdapterInfo = pCurrentAdapterInfo->Next;
|
|
}
|
|
|
|
//
|
|
// If we never found the adapter, pszIPAddress will still point to
|
|
// the IP address string.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Didn't successfully get IPHLPAPI adapter info. pszIPAddress will
|
|
// still point to the IP address string.
|
|
//
|
|
}
|
|
|
|
hr = STR_jkAnsiToWide(wszIPAddress, pszIPAddress, 512);
|
|
if (FAILED(hr))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to convert adapter name to wide (err = 0x%lx)!", hr);
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
#endif // ! DPNBUILD_NOWINSOCK2
|
|
|
|
|
|
//
|
|
// Generate the GUID.
|
|
//
|
|
saddrinTemp.sin_addr = pinaddrBuffer[dwIndex];
|
|
GuidFromAddress(&guidAdapter, (SOCKADDR*) (&saddrinTemp));
|
|
|
|
|
|
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.",
|
|
dwIndex,
|
|
wszIPAddress,
|
|
guidAdapter.Data1,
|
|
guidAdapter.Data2,
|
|
guidAdapter.Data3,
|
|
guidAdapter.Data4[0],
|
|
guidAdapter.Data4[1],
|
|
guidAdapter.Data4[2],
|
|
guidAdapter.Data4[3],
|
|
guidAdapter.Data4[4],
|
|
guidAdapter.Data4[5],
|
|
guidAdapter.Data4[6],
|
|
guidAdapter.Data4[7],
|
|
dwDeviceFlags);
|
|
|
|
|
|
//
|
|
// Add adapter to buffer.
|
|
//
|
|
hr = AddInfoToBuffer(&PackedBuffer, wszIPAddress, &guidAdapter, dwDeviceFlags);
|
|
if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add adapter to buffer (err = 0x%lx)!", hr);
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
} // end for (each IP address)
|
|
|
|
|
|
//
|
|
// If we're here, we successfully built the list of adapters, although
|
|
// the caller may not have given us enough buffer space to store it.
|
|
//
|
|
pEnumData->dwAdapterCount = dwAddressCount;
|
|
pEnumData->dwAdapterDataSize = PackedBuffer.GetSizeRequired();
|
|
|
|
|
|
Exit:
|
|
|
|
#ifndef DPNBUILD_NOWINSOCK2
|
|
if (pAdapterInfoBuffer != NULL)
|
|
{
|
|
DNFree(pAdapterInfoBuffer);
|
|
pAdapterInfoBuffer = NULL;
|
|
}
|
|
#endif // !DPNBUILD_NOWINSOCK2
|
|
|
|
if (pinaddrBuffer != NULL)
|
|
{
|
|
DNFree(pinaddrBuffer);
|
|
pinaddrBuffer = NULL;
|
|
}
|
|
|
|
DPFX(DPFPREP, 6, "Return [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
|
|
Failure:
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
|
|
#ifndef DPNBUILD_NOIPV6
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::EnumIPv6and4Adapters - enumerate all of the IPv6 and IPv4 adapters for this machine
|
|
//
|
|
// Entry: Pointer to enum adapters data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::EnumIPv6and4Adapters"
|
|
|
|
HRESULT CSocketAddress::EnumIPv6and4Adapters( SPENUMADAPTERSDATA *const pEnumData ) const
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwError;
|
|
HMODULE hIpHlpApiDLL = NULL;
|
|
PFNGETADAPTERSADDRESSES pfnGetAdaptersAddresses;
|
|
CPackedBuffer PackedBuffer;
|
|
IP_ADAPTER_ADDRESSES * pIpAdapterAddresses = NULL;
|
|
ULONG ulIpAdapterAddressesLength = 0;
|
|
DWORD dwTotalNumIPv6Addresses = 0;
|
|
DWORD dwTotalNumIPv4Addresses = 0;
|
|
DWORD dwLongestDescription = 0;
|
|
WCHAR * pwszBuffer = NULL;
|
|
IP_ADAPTER_ADDRESSES * pIpAdapterAddressesCurrent;
|
|
IP_ADAPTER_UNICAST_ADDRESS * pIpAdapterUnicastAddressCurrent;
|
|
SORTADAPTERADDRESS * paSortAdapterAddress = NULL;
|
|
DWORD dwNumIPv6Addresses = 0;
|
|
DWORD dwNumIPv4Addresses = 0;
|
|
BOOL fSkipIPv4Loopback = FALSE;
|
|
BOOL fFoundIPv4Loopback = FALSE;
|
|
SOCKADDR_IN saddrinLoopback;
|
|
GUID guidAdapter;
|
|
DWORD dwTemp;
|
|
DWORD dwDeviceFlags;
|
|
WCHAR wszIPAddress[INET6_ADDRSTRLEN];
|
|
|
|
|
|
DPFX(DPFPREP, 6, "Parameters: (0x%p)", pEnumData);
|
|
|
|
|
|
PackedBuffer.Initialize( pEnumData->pAdapterData, pEnumData->dwAdapterDataSize );
|
|
|
|
//
|
|
// Load the IPHLPAPI module and get the adapter list if possible.
|
|
//
|
|
hIpHlpApiDLL = LoadLibrary(c_tszIPHelperDLLName);
|
|
if (hIpHlpApiDLL == NULL)
|
|
{
|
|
#ifdef DBG
|
|
dwError = GetLastError();
|
|
DPFX(DPFPREP, 1, "Couldn't load IPHLPAPI, unable to look for IPv6 adapters (err = %u).", dwError);
|
|
#endif // DBG
|
|
|
|
//
|
|
// Just enumerate IPv4 adapters.
|
|
//
|
|
hr = EnumIPv4Adapters(pEnumData);
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
pfnGetAdaptersAddresses = (PFNGETADAPTERSADDRESSES) GetProcAddress(hIpHlpApiDLL, _TWINCE("GetAdaptersAddresses"));
|
|
if (pfnGetAdaptersAddresses == NULL)
|
|
{
|
|
#ifdef DBG
|
|
dwError = GetLastError();
|
|
DPFX(DPFPREP, 1, "Couldn't find \"GetAdaptersAddresses\" function, unable to look for IPv6 adapters (err = %u).", dwError);
|
|
#endif // DBG
|
|
|
|
//
|
|
// Just enumerate IPv4 adapters.
|
|
//
|
|
hr = EnumIPv4Adapters(pEnumData);
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// OK, we're on a platform where it's possible to look for both IPv6 & IPv4 adapters.
|
|
//
|
|
|
|
do
|
|
{
|
|
dwError = pfnGetAdaptersAddresses(g_iIPAddressFamily,
|
|
(GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER),
|
|
NULL,
|
|
pIpAdapterAddresses,
|
|
&ulIpAdapterAddressesLength);
|
|
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// We got all the info we're going to get. Make sure it was something.
|
|
//
|
|
if (ulIpAdapterAddressesLength < sizeof(IP_ADAPTER_ADDRESSES))
|
|
{
|
|
DPFX(DPFPREP, 0, "GetAdaptersAddresses returned invalid size %u!", ulIpAdapterAddressesLength);
|
|
|
|
//
|
|
// Get rid of the buffer if allocated.
|
|
//
|
|
if (pIpAdapterAddresses != NULL)
|
|
{
|
|
DNFree(pIpAdapterAddresses);
|
|
pIpAdapterAddresses = NULL;
|
|
ulIpAdapterAddressesLength = 0;
|
|
}
|
|
|
|
//
|
|
// Continue with exiting the loop.
|
|
//
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if ((dwError != ERROR_BUFFER_OVERFLOW) &&
|
|
(dwError != ERROR_INSUFFICIENT_BUFFER))
|
|
{
|
|
DPFX(DPFPREP, 0, "GetAdaptersAddresses failed (err = 0x%lx)!", dwError);
|
|
hr = DPNERR_OUTOFMEMORY; // assume it's a resource issue
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// If we're here, then we need to reallocate the buffer.
|
|
//
|
|
if (pIpAdapterAddresses != NULL)
|
|
{
|
|
DNFree(pIpAdapterAddresses);
|
|
pIpAdapterAddresses = NULL;
|
|
}
|
|
|
|
pIpAdapterAddresses = (IP_ADAPTER_ADDRESSES*) DNMalloc(ulIpAdapterAddressesLength);
|
|
if (pIpAdapterAddresses == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't allocate memory for adapter list!");
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
}
|
|
while (TRUE);
|
|
|
|
|
|
|
|
//
|
|
// If there aren't any addresses, throw in the IPv4 loopback address. We will assume that
|
|
// IPv4 is available because IPv6 should always report loopback/link local address and
|
|
// therefore cause pIpAdapterAddresses to be allocated. If IPv6 is not available, then IPv4
|
|
// must be available otherwise we wouldn't have allowed this SP to be loaded.
|
|
//
|
|
// If there are addresses, loop through all the adapters we found to count them and to
|
|
// figure out the longest description name.
|
|
//
|
|
if (pIpAdapterAddresses == NULL)
|
|
{
|
|
DNASSERT(pIpAdapterAddresses == NULL);
|
|
dwTotalNumIPv4Addresses++;
|
|
}
|
|
else
|
|
{
|
|
pIpAdapterAddressesCurrent = pIpAdapterAddresses;
|
|
while (pIpAdapterAddressesCurrent != NULL)
|
|
{
|
|
if (pIpAdapterAddressesCurrent->FriendlyName != NULL)
|
|
{
|
|
dwTemp = wcslen(pIpAdapterAddressesCurrent->FriendlyName);
|
|
if (dwTemp > dwLongestDescription)
|
|
{
|
|
dwLongestDescription = dwTemp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pIpAdapterAddressesCurrent->Description != NULL)
|
|
{
|
|
dwTemp = wcslen(pIpAdapterAddressesCurrent->Description);
|
|
if (dwTemp > dwLongestDescription)
|
|
{
|
|
dwLongestDescription = dwTemp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No friendly name or description.
|
|
//
|
|
}
|
|
}
|
|
|
|
//
|
|
// Count the number of addresses.
|
|
//
|
|
pIpAdapterUnicastAddressCurrent = pIpAdapterAddressesCurrent->FirstUnicastAddress;
|
|
while (pIpAdapterUnicastAddressCurrent != NULL)
|
|
{
|
|
DumpSocketAddress(8, pIpAdapterUnicastAddressCurrent->Address.lpSockaddr, pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family);
|
|
|
|
#pragma TODO(vanceo, "Option to allow non-preferred addresses? See below, too.")
|
|
if (pIpAdapterUnicastAddressCurrent->DadState == IpDadStatePreferred)
|
|
{
|
|
if (pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family == AF_INET6)
|
|
{
|
|
//
|
|
// Skip the loopback pseudo-interface. Windows reports the true
|
|
// loopback address, and then a link-local-looking address. We
|
|
// don't care about the link-local one either because there should
|
|
// be real link-local addresses available under other interfaces.
|
|
// So completely jump out of the address loop when we see the
|
|
// IPv6 loopback address. See sorting loop below as well.
|
|
//
|
|
if (IN6_IS_ADDR_LOOPBACK(&(((SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin6_addr)))
|
|
{
|
|
DNASSERT(pIpAdapterUnicastAddressCurrent == pIpAdapterAddressesCurrent->FirstUnicastAddress);
|
|
#pragma TODO(vanceo, "Are we sure we want to depend on the order the addresses are reported? See below, too.")
|
|
break;
|
|
}
|
|
|
|
if ((IN6_IS_ADDR_LINKLOCAL(&(((SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin6_addr))) ||
|
|
(IN6_IS_ADDR_SITELOCAL(&(((SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin6_addr))))
|
|
{
|
|
DNASSERT(((SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin6_scope_id != 0);
|
|
}
|
|
|
|
dwTotalNumIPv6Addresses++;
|
|
fSkipIPv4Loopback = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DNASSERT(pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family == AF_INET);
|
|
|
|
//
|
|
// Skip the IPv4 loopback address if there are other addresses.
|
|
//
|
|
if (((SOCKADDR_IN*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin_addr.S_un.S_addr != IP_LOOPBACK_ADDRESS)
|
|
{
|
|
fSkipIPv4Loopback = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fFoundIPv4Loopback = TRUE;
|
|
}
|
|
dwTotalNumIPv4Addresses++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 7, "Skipping address whose state (%u) is not preferred.",
|
|
pIpAdapterUnicastAddressCurrent->DadState);
|
|
}
|
|
pIpAdapterUnicastAddressCurrent = pIpAdapterUnicastAddressCurrent->Next;
|
|
}
|
|
|
|
pIpAdapterAddressesCurrent = pIpAdapterAddressesCurrent->Next;
|
|
}
|
|
|
|
//
|
|
// If we found the IPv4 loopback address but we can skip it, decrement our IPv4
|
|
// address count.
|
|
//
|
|
if ((fFoundIPv4Loopback) && (fSkipIPv4Loopback))
|
|
{
|
|
DNASSERT(dwTotalNumIPv4Addresses > 0);
|
|
dwTotalNumIPv4Addresses--;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer to hold the largest friendly name + the other info we add to the
|
|
// adapter description. INET6_ADDRSTRLEN is larger than INET_ADDRSTRLEN, and
|
|
// includes NULL termination char (+ other things we don't actually use).
|
|
//
|
|
pwszBuffer = (WCHAR*) DNMalloc((dwLongestDescription + sizeof(c_wszIPv6AdapterNameTemplate) + INET6_ADDRSTRLEN) * sizeof(WCHAR));
|
|
if (pwszBuffer == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't allocate memory for name string!");
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
paSortAdapterAddress = (SORTADAPTERADDRESS*) DNMalloc((dwTotalNumIPv6Addresses + dwTotalNumIPv4Addresses) * sizeof(SORTADAPTERADDRESS));
|
|
if (paSortAdapterAddress == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't allocate memory for sorted adapter list!");
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
memset(paSortAdapterAddress, 0, ((dwTotalNumIPv6Addresses + dwTotalNumIPv4Addresses) * sizeof(SORTADAPTERADDRESS)));
|
|
|
|
if (pIpAdapterAddresses == NULL)
|
|
{
|
|
memset(&saddrinLoopback, 0, sizeof(saddrinLoopback));
|
|
saddrinLoopback.sin_family = AF_INET;
|
|
saddrinLoopback.sin_addr.S_un.S_addr = IP_LOOPBACK_ADDRESS;
|
|
|
|
paSortAdapterAddress[0].psockaddr = (SOCKADDR*) &saddrinLoopback;
|
|
paSortAdapterAddress[0].pwszDescription = (WCHAR*) c_wszIPv4LoopbackAdapterString;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Loop through all the adapters again to sort them.
|
|
// The rules are (in order of precedence):
|
|
// 1) Skip addresses that are not in the 'preferred' state.
|
|
// 2) IPv6 before IPv4.
|
|
// 3) Skip IPv6 loopback pseudo-interface.
|
|
// 4) IPv4 ICS-private-adapter-looking IP addresses (192.168.0.1) first.
|
|
// 5) Skip IPv4 loopback address (127.0.0.1) if we determined there were other addresses.
|
|
//
|
|
pIpAdapterAddressesCurrent = pIpAdapterAddresses;
|
|
while (pIpAdapterAddressesCurrent != NULL)
|
|
{
|
|
pIpAdapterUnicastAddressCurrent = pIpAdapterAddressesCurrent->FirstUnicastAddress;
|
|
while (pIpAdapterUnicastAddressCurrent != NULL)
|
|
{
|
|
if (pIpAdapterUnicastAddressCurrent->DadState == IpDadStatePreferred)
|
|
{
|
|
//
|
|
// Insert IPv6 adapters in the first half of the array, IPv4 in the second half.
|
|
//
|
|
if (pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family == AF_INET6)
|
|
{
|
|
SOCKADDR_IN6 * psaddrin6;
|
|
|
|
|
|
psaddrin6 = (SOCKADDR_IN6*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr;
|
|
|
|
//
|
|
// Skip the loopback pseudo-interface as described earlier.
|
|
//
|
|
if (IN6_IS_ADDR_LOOPBACK(&psaddrin6->sin6_addr))
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Save the pointers in the current slot.
|
|
//
|
|
|
|
paSortAdapterAddress[dwNumIPv6Addresses].psockaddr = (SOCKADDR*) psaddrin6;
|
|
|
|
if (pIpAdapterAddressesCurrent->FriendlyName != NULL)
|
|
{
|
|
paSortAdapterAddress[dwNumIPv6Addresses].pwszDescription = pIpAdapterAddressesCurrent->FriendlyName;
|
|
}
|
|
else
|
|
{
|
|
if (pIpAdapterAddressesCurrent->Description != NULL)
|
|
{
|
|
paSortAdapterAddress[dwNumIPv6Addresses].pwszDescription = pIpAdapterAddressesCurrent->Description;
|
|
}
|
|
}
|
|
|
|
DNASSERT(dwNumIPv6Addresses < dwTotalNumIPv6Addresses);
|
|
dwNumIPv6Addresses++;
|
|
}
|
|
else
|
|
{
|
|
DNASSERT(pIpAdapterUnicastAddressCurrent->Address.lpSockaddr->sa_family == AF_INET);
|
|
|
|
if ((((SOCKADDR_IN*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin_addr.S_un.S_addr != IP_LOOPBACK_ADDRESS) ||
|
|
(! fSkipIPv4Loopback))
|
|
{
|
|
//
|
|
// If this looks like an ICS private adapter and there are other adapters, put it first,
|
|
// otherwise add to the end.
|
|
//
|
|
if ((((SOCKADDR_IN*) pIpAdapterUnicastAddressCurrent->Address.lpSockaddr)->sin_addr.S_un.S_addr == IP_PRIVATEICS_ADDRESS) &&
|
|
(dwNumIPv4Addresses > 0))
|
|
{
|
|
//
|
|
// Move all existing entries down one.
|
|
//
|
|
for(dwTemp = dwTotalNumIPv6Addresses + dwNumIPv4Addresses; dwTemp > dwTotalNumIPv6Addresses; dwTemp--)
|
|
{
|
|
memcpy(&paSortAdapterAddress[dwTemp],
|
|
&paSortAdapterAddress[dwTemp - 1],
|
|
sizeof(SORTADAPTERADDRESS));
|
|
}
|
|
|
|
//
|
|
// Add this new entry at the start of the IPv4 addresses.
|
|
//
|
|
|
|
paSortAdapterAddress[dwTotalNumIPv6Addresses].psockaddr = pIpAdapterUnicastAddressCurrent->Address.lpSockaddr;
|
|
|
|
if (pIpAdapterAddressesCurrent->FriendlyName != NULL)
|
|
{
|
|
paSortAdapterAddress[dwTotalNumIPv6Addresses].pwszDescription = pIpAdapterAddressesCurrent->FriendlyName;
|
|
}
|
|
else
|
|
{
|
|
if (pIpAdapterAddressesCurrent->Description != NULL)
|
|
{
|
|
paSortAdapterAddress[dwTotalNumIPv6Addresses].pwszDescription = pIpAdapterAddressesCurrent->Description;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Add this entry at the current IPv4 address slot.
|
|
//
|
|
|
|
paSortAdapterAddress[dwTotalNumIPv6Addresses + dwNumIPv4Addresses].psockaddr = pIpAdapterUnicastAddressCurrent->Address.lpSockaddr;
|
|
|
|
if (pIpAdapterAddressesCurrent->FriendlyName != NULL)
|
|
{
|
|
paSortAdapterAddress[dwTotalNumIPv6Addresses + dwNumIPv4Addresses].pwszDescription = pIpAdapterAddressesCurrent->FriendlyName;
|
|
}
|
|
else
|
|
{
|
|
if (pIpAdapterAddressesCurrent->Description != NULL)
|
|
{
|
|
paSortAdapterAddress[dwTotalNumIPv6Addresses + dwNumIPv4Addresses].pwszDescription = pIpAdapterAddressesCurrent->Description;
|
|
}
|
|
}
|
|
}
|
|
|
|
DNASSERT(dwNumIPv4Addresses < dwTotalNumIPv4Addresses);
|
|
dwNumIPv4Addresses++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Skip the IPv4 loopback address.
|
|
//
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Deprecated or otherwise non-preferred address.
|
|
//
|
|
}
|
|
pIpAdapterUnicastAddressCurrent = pIpAdapterUnicastAddressCurrent->Next;
|
|
}
|
|
|
|
pIpAdapterAddressesCurrent = pIpAdapterAddressesCurrent->Next;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Finally loop through the sorted adapters and store them in the buffer (or get size needed).
|
|
//
|
|
for(dwTemp = 0; dwTemp < dwTotalNumIPv6Addresses + dwTotalNumIPv4Addresses; dwTemp++)
|
|
{
|
|
//
|
|
// Start off assuming this IP address won't have any special
|
|
// flags.
|
|
//
|
|
dwDeviceFlags = 0;
|
|
|
|
#pragma BUGBUG(vanceo, "Move to appropriate location so that turning on DPNBUILD_NOMULTICAST doesn't break")
|
|
/*
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
//
|
|
// If this is the first device and we couldn't use IPHLPAPI to
|
|
// determine the best multicast interface, then just say the
|
|
// default multicast interface is the first (for lack of a
|
|
// better idea).
|
|
//
|
|
#ifdef DPNBUILD_NOWINSOCK2
|
|
if (dwIndex == 0)
|
|
#else // ! DPNBUILD_NOWINSOCK2
|
|
if ((dwIndex == 0) && (dwMcastInterfaceIndex == INVALID_INTERFACE_INDEX))
|
|
#endif // ! DPNBUILD_NOWINSOCK2
|
|
{
|
|
dwDeviceFlags |= DPNSPINFO_DEFAULTMULTICASTDEVICE;
|
|
}
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
*/
|
|
|
|
|
|
//
|
|
// Create a string representation of the IP address and generate the name.
|
|
//
|
|
if (paSortAdapterAddress[dwTemp].psockaddr->sa_family == AF_INET6)
|
|
{
|
|
DNIpv6AddressToStringW(&((SOCKADDR_IN6*) paSortAdapterAddress[dwTemp].psockaddr)->sin6_addr,
|
|
wszIPAddress);
|
|
|
|
if (paSortAdapterAddress[dwTemp].pwszDescription != NULL)
|
|
{
|
|
wsprintfW(pwszBuffer,
|
|
c_wszIPv6AdapterNameTemplate,
|
|
paSortAdapterAddress[dwTemp].pwszDescription,
|
|
wszIPAddress);
|
|
}
|
|
else
|
|
{
|
|
wsprintfW(pwszBuffer,
|
|
c_wszIPv6AdapterNameNoDescTemplate,
|
|
wszIPAddress);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DNinet_ntow(((SOCKADDR_IN*) paSortAdapterAddress[dwTemp].psockaddr)->sin_addr,
|
|
wszIPAddress);
|
|
|
|
if (paSortAdapterAddress[dwTemp].pwszDescription != NULL)
|
|
{
|
|
wsprintfW(pwszBuffer,
|
|
c_wszIPv4AdapterNameTemplate,
|
|
paSortAdapterAddress[dwTemp].pwszDescription,
|
|
wszIPAddress);
|
|
}
|
|
else
|
|
{
|
|
wsprintfW(pwszBuffer,
|
|
c_wszIPv4AdapterNameNoDescTemplate,
|
|
wszIPAddress);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Generate the GUID.
|
|
//
|
|
GuidFromAddress(&guidAdapter, paSortAdapterAddress[dwTemp].psockaddr);
|
|
|
|
|
|
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.",
|
|
dwTemp,
|
|
pwszBuffer,
|
|
guidAdapter.Data1,
|
|
guidAdapter.Data2,
|
|
guidAdapter.Data3,
|
|
guidAdapter.Data4[0],
|
|
guidAdapter.Data4[1],
|
|
guidAdapter.Data4[2],
|
|
guidAdapter.Data4[3],
|
|
guidAdapter.Data4[4],
|
|
guidAdapter.Data4[5],
|
|
guidAdapter.Data4[6],
|
|
guidAdapter.Data4[7],
|
|
dwDeviceFlags);
|
|
|
|
|
|
//
|
|
// Add adapter to buffer.
|
|
//
|
|
hr = AddInfoToBuffer(&PackedBuffer, pwszBuffer, &guidAdapter, dwDeviceFlags);
|
|
if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add adapter to buffer (err = 0x%lx)!", hr);
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we're here, we successfully built the list of adapters, although
|
|
// the caller may not have given us enough buffer space to store it.
|
|
//
|
|
pEnumData->dwAdapterCount = dwTotalNumIPv6Addresses + dwTotalNumIPv4Addresses;
|
|
pEnumData->dwAdapterDataSize = PackedBuffer.GetSizeRequired();
|
|
|
|
|
|
Exit:
|
|
|
|
if (paSortAdapterAddress != NULL)
|
|
{
|
|
DNFree(paSortAdapterAddress);
|
|
paSortAdapterAddress = NULL;
|
|
}
|
|
|
|
if (pwszBuffer != NULL)
|
|
{
|
|
DNFree(pwszBuffer);
|
|
pwszBuffer = NULL;
|
|
}
|
|
|
|
if (pIpAdapterAddresses != NULL)
|
|
{
|
|
DNFree(pIpAdapterAddresses);
|
|
pIpAdapterAddresses = NULL;
|
|
}
|
|
|
|
if (hIpHlpApiDLL != NULL)
|
|
{
|
|
FreeLibrary(hIpHlpApiDLL);
|
|
hIpHlpApiDLL = NULL;
|
|
}
|
|
|
|
DPFX(DPFPREP, 6, "Return [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
|
|
|
|
|
|
#ifndef DPNBUILD_NOMULTICAST
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::EnumMulticastScopes - enumerate all multicast scopes for an adapter
|
|
//
|
|
// Entry: Pointer to enum multicast scopes data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::EnumMulticastScopes"
|
|
|
|
HRESULT CSocketAddress::EnumMulticastScopes( SPENUMMULTICASTSCOPESDATA *const pEnumData, BOOL const fUseMADCAP ) const
|
|
{
|
|
HRESULT hr;
|
|
CPackedBuffer PackedBuffer;
|
|
#ifdef DPNBUILD_NOIPV6
|
|
SOCKADDR saddrAdapter;
|
|
#else // ! DPNBUILD_NOIPV6
|
|
SOCKADDR_STORAGE saddrAdapter;
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
SOCKET sTemp = INVALID_SOCKET;
|
|
DWORD dwScopeCount = 0;
|
|
#ifdef DBG
|
|
DWORD dwError;
|
|
#endif // DBG
|
|
|
|
|
|
DPFX(DPFPREP, 6, "Parameters: (0x%p, %i)", pEnumData, fUseMADCAP);
|
|
|
|
PackedBuffer.Initialize(pEnumData->pScopeData, pEnumData->dwScopeDataSize);
|
|
|
|
#pragma TODO(vanceo, "Make IPv6 ready")
|
|
AddressFromGuid(pEnumData->pguidAdapter, &saddrAdapter);
|
|
|
|
//
|
|
// Make sure the adapter is valid by asking WinSock.
|
|
//
|
|
|
|
sTemp = socket(GetFamily(), SOCK_DGRAM, IPPROTO_UDP);
|
|
if (sTemp == INVALID_SOCKET)
|
|
{
|
|
#ifdef DBG
|
|
dwError = WSAGetLastError();
|
|
DPFX(DPFPREP, 0, "Couldn't create temporary UDP socket (err = %u)!", dwError);
|
|
DNASSERT(FALSE);
|
|
#endif // DBG
|
|
hr = DPNERR_GENERIC;
|
|
goto Failure;
|
|
}
|
|
|
|
#ifndef DPNBUILD_NOIPV6
|
|
if (saddrAdapter.ss_family == AF_INET6)
|
|
{
|
|
saddrAdapter.ss_family = GetFamily();
|
|
|
|
#pragma TODO(vanceo, "Make IPv6 ready")
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
{
|
|
((SOCKADDR_IN*) (&saddrAdapter))->sin_family = GetFamily();
|
|
((SOCKADDR_IN*) (&saddrAdapter))->sin_port = ANY_PORT;
|
|
}
|
|
|
|
if (bind(sTemp, (SOCKADDR*) (&saddrAdapter), sizeof(saddrAdapter)) != 0)
|
|
{
|
|
#ifdef DBG
|
|
dwError = WSAGetLastError();
|
|
DPFX(DPFPREP, 0, "Adapter GUID is invalid (err = %u)!", dwError);
|
|
DisplayWinsockError(0, dwError);
|
|
DNASSERT(dwError == WSAEADDRNOTAVAIL);
|
|
#endif // DBG
|
|
hr = DPNERR_INVALIDDEVICEADDRESS;
|
|
goto Failure;
|
|
}
|
|
|
|
closesocket(sTemp);
|
|
sTemp = INVALID_SOCKET;
|
|
|
|
|
|
//
|
|
// The adapter is valid. First, fill in the 3 default multicast scopes.
|
|
//
|
|
|
|
hr = AddInfoToBuffer(&PackedBuffer, c_wszPrivateScopeString, &GUID_DP8MULTICASTSCOPE_PRIVATE, 0);
|
|
if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add private scope to buffer (err = 0x%lx)!", hr);
|
|
DisplayDNError(0, hr);
|
|
goto Failure;
|
|
}
|
|
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}.",
|
|
dwScopeCount,
|
|
c_wszPrivateScopeString,
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data1,
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data2,
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data3,
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[0],
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[1],
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[2],
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[3],
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[4],
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[5],
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[6],
|
|
GUID_DP8MULTICASTSCOPE_PRIVATE.Data4[7]);
|
|
dwScopeCount++;
|
|
|
|
hr = AddInfoToBuffer(&PackedBuffer, c_wszLocalScopeString, &GUID_DP8MULTICASTSCOPE_LOCAL, 0);
|
|
if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add local scope to buffer (err = 0x%lx)!", hr);
|
|
DisplayDNError(0, hr);
|
|
goto Failure;
|
|
}
|
|
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}.",
|
|
dwScopeCount,
|
|
c_wszLocalScopeString,
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data1,
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data2,
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data3,
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data4[0],
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data4[1],
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data4[2],
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data4[3],
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data4[4],
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data4[5],
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data4[6],
|
|
GUID_DP8MULTICASTSCOPE_LOCAL.Data4[7]);
|
|
dwScopeCount++;
|
|
|
|
hr = AddInfoToBuffer(&PackedBuffer, c_wszGlobalScopeString, &GUID_DP8MULTICASTSCOPE_GLOBAL, 0);
|
|
if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add global scope to buffer (err = 0x%lx)!", hr);
|
|
DisplayDNError(0, hr);
|
|
goto Failure;
|
|
}
|
|
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}.",
|
|
dwScopeCount,
|
|
c_wszGlobalScopeString,
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data1,
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data2,
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data3,
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[0],
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[1],
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[2],
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[3],
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[4],
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[5],
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[6],
|
|
GUID_DP8MULTICASTSCOPE_GLOBAL.Data4[7]);
|
|
dwScopeCount++;
|
|
|
|
|
|
//
|
|
// If this platform supports MADCAP, retrieve its list of scopes for
|
|
// this adapter.
|
|
// NOTE: This assumes MADCAP has been loaded by the thread pool
|
|
// already.
|
|
//
|
|
#ifdef WINNT
|
|
if (fUseMADCAP)
|
|
{
|
|
#ifndef DBG
|
|
DWORD dwError;
|
|
#endif // ! DBG
|
|
PMCAST_SCOPE_ENTRY paScopes = NULL;
|
|
DWORD dwScopesSize = 0;
|
|
DWORD dwNumScopeEntries;
|
|
DWORD dwTemp;
|
|
WCHAR * pwszScratch;
|
|
GUID guidScope;
|
|
|
|
|
|
//
|
|
// Determine how much room we need to hold the list of scopes.
|
|
//
|
|
dwError = McastEnumerateScopes(GetFamily(),
|
|
TRUE,
|
|
NULL,
|
|
&dwScopesSize,
|
|
&dwNumScopeEntries);
|
|
if (((dwError == ERROR_SUCCESS) || (dwError == ERROR_MORE_DATA)) &&
|
|
(dwScopesSize >= sizeof(MCAST_SCOPE_ENTRY)) &&
|
|
(dwNumScopeEntries > 0))
|
|
{
|
|
//
|
|
// We want to add " - TTL xxx" to every string entry, so allocate
|
|
// enough extra room for a scratch buffer for the largest possible
|
|
// string plus that extra information.
|
|
//
|
|
dwTemp = dwScopesSize - (dwNumScopeEntries * sizeof(MCAST_SCOPE_ENTRY)) + (10 * sizeof(WCHAR));
|
|
|
|
paScopes = (PMCAST_SCOPE_ENTRY) DNMalloc(dwScopesSize + dwTemp);
|
|
if (paScopes != NULL)
|
|
{
|
|
pwszScratch = (WCHAR*) (((BYTE*) (paScopes)) + dwScopesSize);
|
|
|
|
//
|
|
// Retrieve the list of scopes.
|
|
//
|
|
dwError = McastEnumerateScopes(GetFamily(),
|
|
FALSE,
|
|
paScopes,
|
|
&dwScopesSize,
|
|
&dwNumScopeEntries);
|
|
if ((dwError == ERROR_SUCCESS) &&
|
|
(dwScopesSize >= sizeof(MCAST_SCOPE_ENTRY)) &&
|
|
(dwNumScopeEntries > 0))
|
|
{
|
|
//
|
|
// Look for scopes that match the device we were given.
|
|
//
|
|
for(dwTemp = 0; dwTemp < dwNumScopeEntries; dwTemp++)
|
|
{
|
|
BOOL fResult;
|
|
|
|
|
|
#ifndef DPNBUILD_NOIPV6
|
|
if (GetFamily() == AF_INET6)
|
|
{
|
|
if (memcmp(&paScopes[dwTemp].ScopeCtx.Interface.IpAddrV6, &(((SOCKADDR_IN6*) (&saddrAdapter))->sin6_addr), sizeof(paScopes[dwTemp].ScopeCtx.Interface.IpAddrV6)) == 0)
|
|
{
|
|
fResult = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
{
|
|
if (paScopes[dwTemp].ScopeCtx.Interface.IpAddrV4 == ((SOCKADDR_IN*) (&saddrAdapter))->sin_addr.S_un.S_addr)
|
|
{
|
|
fResult = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
|
|
if (fResult)
|
|
{
|
|
//
|
|
// Encrypt the scope context and TTL as a GUID.
|
|
//
|
|
#ifdef DPNBUILD_NOIPV6
|
|
CSocketAddress::CreateScopeGuid(&(paScopes[dwTemp].ScopeCtx),
|
|
#else // ! DPNBUILD_NOIPV6
|
|
CSocketAddress::CreateScopeGuid(GetFamily(),
|
|
&(paScopes[dwTemp].ScopeCtx),
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
(BYTE) (paScopes[dwTemp].TTL),
|
|
&guidScope);
|
|
|
|
//
|
|
// Use the scratch space at the end of our buffer to
|
|
// append " - TTL xxx" to the description string.
|
|
//
|
|
wsprintfW(pwszScratch, L"%ls - TTL %u",
|
|
paScopes[dwTemp].ScopeDesc.Buffer,
|
|
(BYTE) (paScopes[dwTemp].TTL));
|
|
|
|
hr = AddInfoToBuffer(&PackedBuffer, pwszScratch, &guidScope, 0);
|
|
if ((hr != DPN_OK) && (hr != DPNERR_BUFFERTOOSMALL))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add scope \"%ls\" to buffer (err = 0x%lx)!",
|
|
pwszScratch, hr);
|
|
DisplayDNError(0, hr);
|
|
DNFree(paScopes);
|
|
paScopes = NULL;
|
|
goto Failure;
|
|
}
|
|
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}.",
|
|
dwScopeCount,
|
|
pwszScratch,
|
|
guidScope.Data1,
|
|
guidScope.Data2,
|
|
guidScope.Data3,
|
|
guidScope.Data4[0],
|
|
guidScope.Data4[1],
|
|
guidScope.Data4[2],
|
|
guidScope.Data4[3],
|
|
guidScope.Data4[4],
|
|
guidScope.Data4[5],
|
|
guidScope.Data4[6],
|
|
guidScope.Data4[7]);
|
|
dwScopeCount++;
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 7, "Ignoring scope \"%ls - TTL %u\" for different adapter.",
|
|
paScopes[dwTemp].ScopeDesc.Buffer, paScopes[dwTemp].TTL);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed enumerating MADCAP scopes (err = %u, size %u, expected size %u, count %u)! Ignoring.",
|
|
dwError, dwScopesSize, sizeof(MCAST_SCOPE_ENTRY), dwNumScopeEntries);
|
|
}
|
|
|
|
DNFree(paScopes);
|
|
paScopes = NULL;
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed allocating memory for MADCAP scopes! Ignoring.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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.",
|
|
dwError, dwScopesSize, sizeof(MCAST_SCOPE_ENTRY), dwNumScopeEntries);
|
|
}
|
|
} // end if (MADCAP should be used)
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 7, "Not enumerating MADCAP scopes.");
|
|
}
|
|
#endif // WINNT
|
|
|
|
|
|
//
|
|
// If we're here, we successfully built the list of adapters, although
|
|
// the caller may not have given us enough buffer space to store it.
|
|
//
|
|
pEnumData->dwScopeCount = dwScopeCount;
|
|
pEnumData->dwScopeDataSize = PackedBuffer.GetSizeRequired();
|
|
|
|
|
|
Exit:
|
|
|
|
DPFX(DPFPREP, 6, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
|
|
if (sTemp != INVALID_SOCKET)
|
|
{
|
|
closesocket(sTemp);
|
|
sTemp = INVALID_SOCKET;
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::SocketAddressFromMulticastDP8Address - convert a multicast style DP8Address into a socket address (may not be complete)
|
|
//
|
|
// Entry: Pointer to DP8Address
|
|
// Place to store scope GUID.
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::SocketAddressFromMulticastDP8Address"
|
|
|
|
HRESULT CSocketAddress::SocketAddressFromMulticastDP8Address( IDirectPlay8Address *const pDP8Address,
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
ULONGLONG * const pullKeyID,
|
|
#endif // DPNBUILD_XNETSECURITY
|
|
GUID * const pScopeGuid )
|
|
{
|
|
HRESULT hr;
|
|
WCHAR wszMulticastAddress[16]; // nnn.nnn.nnn.nnn + NULL termination
|
|
char szMulticastAddress[16]; // nnn.nnn.nnn.nnn + NULL termination
|
|
DWORD dwSize;
|
|
DWORD dwDataType;
|
|
DWORD dwPort;
|
|
|
|
|
|
DNASSERT(pDP8Address != NULL);
|
|
|
|
#ifdef DPNBUILD_XNETSECURITY
|
|
#error ("Multicast doesn't currently support secure transport!")
|
|
#endif // DPNBUILD_XNETSECURITY
|
|
|
|
//
|
|
// Get the multicast IP address, if it's there.
|
|
//
|
|
dwSize = sizeof(wszMulticastAddress);
|
|
hr = IDirectPlay8Address_GetComponentByName(pDP8Address,
|
|
DPNA_KEY_HOSTNAME,
|
|
wszMulticastAddress,
|
|
&dwSize,
|
|
&dwDataType);
|
|
if (hr == DPN_OK)
|
|
{
|
|
switch (dwDataType)
|
|
{
|
|
case DPNA_DATATYPE_STRING:
|
|
{
|
|
STR_jkWideToAnsi(szMulticastAddress,
|
|
wszMulticastAddress,
|
|
(sizeof(szMulticastAddress) / sizeof(char)));
|
|
break;
|
|
}
|
|
|
|
case DPNA_DATATYPE_STRING_ANSI:
|
|
{
|
|
DWORD dwStrSize;
|
|
|
|
|
|
//
|
|
// For some reason, addressing returned the string as ANSI,
|
|
// not Unicode. Not sure why this would happen, but go
|
|
// ahead and convert it.
|
|
// First make sure it's a reasonable size.
|
|
// If you're wondering about the funkiness of this copying,
|
|
// it's because PREfast goes a little overboard...
|
|
//
|
|
dwStrSize = (strlen((char*) wszMulticastAddress) + 1) * sizeof(char);
|
|
DNASSERT(dwStrSize == dwSize);
|
|
if (dwStrSize > (sizeof(szMulticastAddress) / sizeof(char)))
|
|
{
|
|
DPFX(DPFPREP, 0, "Unexpectedly long ANSI hostname string (%u bytes)!", dwStrSize);
|
|
hr = DPNERR_INVALIDADDRESSFORMAT;
|
|
goto Failure;
|
|
}
|
|
memcpy(szMulticastAddress, (char*) wszMulticastAddress, dwStrSize);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DPFX(DPFPREP, 0, "Unexpected data type %u for hostname component!", dwDataType);
|
|
hr = DPNERR_INVALIDADDRESSFORMAT;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Convert the IP address string into an address.
|
|
//
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = inet_addr(szMulticastAddress);
|
|
|
|
|
|
//
|
|
// Make sure it's a valid multicast IP address.
|
|
//
|
|
if (! (IS_CLASSD_IPV4_ADDRESS(m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr)))
|
|
{
|
|
DPFX(DPFPREP, 0, "Hostname component \"%hs\" does not resolve to valid multicast IP address!",
|
|
szMulticastAddress);
|
|
hr = DPNERR_INVALIDHOSTADDRESS;
|
|
goto Failure;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 3, "Address didn't contain multicast hostname (err = 0x%lx).", hr);
|
|
DNASSERT(m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_ANY);
|
|
}
|
|
|
|
|
|
//
|
|
// Get the multicast port, if it's there.
|
|
//
|
|
dwSize = sizeof(dwPort);
|
|
hr = IDirectPlay8Address_GetComponentByName(pDP8Address,
|
|
DPNA_KEY_PORT,
|
|
&dwPort,
|
|
&dwSize,
|
|
&dwDataType);
|
|
if (hr == DPN_OK)
|
|
{
|
|
if (dwDataType != DPNA_DATATYPE_DWORD)
|
|
{
|
|
DPFX(DPFPREP, 0, "Unexpected data type %u for port component!", dwDataType);
|
|
hr = DPNERR_INVALIDADDRESSFORMAT;
|
|
goto Failure;
|
|
}
|
|
m_SocketAddress.IPSocketAddress.sin_port = HTONS((WORD) dwPort);
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 3, "Address didn't contain multicast port (err = 0x%lx).", hr);
|
|
DNASSERT(m_SocketAddress.IPSocketAddress.sin_port == ANY_PORT);
|
|
}
|
|
|
|
|
|
//
|
|
// Get the multicast scope, if it's there.
|
|
//
|
|
dwSize = sizeof(*pScopeGuid);
|
|
hr = IDirectPlay8Address_GetComponentByName(pDP8Address,
|
|
DPNA_KEY_SCOPE,
|
|
pScopeGuid,
|
|
&dwSize,
|
|
&dwDataType);
|
|
if (hr == DPN_OK)
|
|
{
|
|
if (dwDataType != DPNA_DATATYPE_GUID)
|
|
{
|
|
DPFX(DPFPREP, 0, "Unexpected data type %u for scope component!", dwDataType);
|
|
hr = DPNERR_INVALIDADDRESSFORMAT;
|
|
goto Failure;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 3, "Address didn't contain multicast scope (err = 0x%lx), using private scope.", hr);
|
|
memcpy(pScopeGuid, &GUID_DP8MULTICASTSCOPE_PRIVATE, sizeof(*pScopeGuid));
|
|
}
|
|
|
|
hr = DPN_OK;
|
|
|
|
|
|
Exit:
|
|
|
|
return hr;
|
|
|
|
|
|
Failure:
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
#endif // ! DPNBUILD_NOMULTICAST
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::CompareFunction - compare against another address
|
|
//
|
|
// Entry: Pointer to other address
|
|
//
|
|
// Exit: Bool indicating equality of two addresses
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::CompareFunction"
|
|
|
|
BOOL CSocketAddress::CompareFunction( PVOID pvKey1, PVOID pvKey2 )
|
|
{
|
|
CSocketAddress* pAddress1 = (CSocketAddress*)pvKey1;
|
|
CSocketAddress* pAddress2 = (CSocketAddress*)pvKey2;
|
|
|
|
DNASSERT(pAddress1 != NULL);
|
|
DNASSERT(pAddress2 != NULL);
|
|
|
|
DNASSERT(pAddress1->GetFamily() == pAddress2->GetFamily());
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (pAddress1->GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
//
|
|
// we need to compare the IPv6 address and port to guarantee uniqueness
|
|
//
|
|
if (IN6_ADDR_EQUAL(&(pAddress1->m_SocketAddress.IPv6SocketAddress.sin6_addr),
|
|
&(pAddress2->m_SocketAddress.IPv6SocketAddress.sin6_addr)))
|
|
{
|
|
if ( pAddress1->m_SocketAddress.IPv6SocketAddress.sin6_port ==
|
|
pAddress2->m_SocketAddress.IPv6SocketAddress.sin6_port )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
//
|
|
// We only need to compare:
|
|
// netnumber (IPX network address) [ 4 bytes ]
|
|
// nodenumber (netcard adapter address) [ 6 bytes ]
|
|
// port [ 2 bytes ]
|
|
//
|
|
// Note that the nodenumber and port fields are sequentially arranged in the
|
|
// address structure and can be compared with DWORDs
|
|
//
|
|
DBG_CASSERT( OFFSETOF( SOCKADDR_IPX, sa_nodenum ) == ( OFFSETOF( SOCKADDR_IPX, sa_netnum ) + sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_netnum ) ) );
|
|
DBG_CASSERT( OFFSETOF( SOCKADDR_IPX, sa_socket ) == ( OFFSETOF( SOCKADDR_IPX, sa_nodenum ) + sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_nodenum ) ) );
|
|
|
|
return memcmp( &pAddress1->m_SocketAddress.IPXSocketAddress.sa_netnum,
|
|
pAddress2->m_SocketAddress.IPXSocketAddress.sa_netnum,
|
|
( sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_netnum ) +
|
|
sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_nodenum ) +
|
|
sizeof( pAddress1->m_SocketAddress.IPXSocketAddress.sa_socket ) ) ) == 0;
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
DNASSERT(pAddress1->GetFamily() == AF_INET);
|
|
|
|
//
|
|
// we need to compare the IP address and port to guarantee uniqueness
|
|
//
|
|
if ( pAddress1->m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr ==
|
|
pAddress2->m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr )
|
|
{
|
|
if ( pAddress1->m_SocketAddress.IPSocketAddress.sin_port ==
|
|
pAddress2->m_SocketAddress.IPSocketAddress.sin_port )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::HashFunction - hash address to N bits
|
|
//
|
|
// Entry: Count of bits to hash to
|
|
//
|
|
// Exit: Hashed value
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::HashFunction"
|
|
|
|
DWORD CSocketAddress::HashFunction( PVOID pvKey, BYTE bBitDepth )
|
|
{
|
|
DWORD dwReturn;
|
|
UINT_PTR Temp;
|
|
CSocketAddress* pAddress = (CSocketAddress*) pvKey;
|
|
|
|
DNASSERT( bBitDepth != 0 );
|
|
DNASSERT( bBitDepth < 32 );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
dwReturn = 0;
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (pAddress->GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
DWORD dwTemp;
|
|
|
|
|
|
//
|
|
// hash IPv6 address
|
|
//
|
|
for(dwTemp = 0; dwTemp < (sizeof(pAddress->m_SocketAddress.IPv6SocketAddress.sin6_addr) / sizeof(UINT_PTR)); dwTemp++)
|
|
{
|
|
Temp = ((UINT_PTR*) (&pAddress->m_SocketAddress.IPv6SocketAddress.sin6_addr))[dwTemp];
|
|
|
|
do
|
|
{
|
|
dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
|
|
Temp >>= bBitDepth;
|
|
} while ( Temp != 0 );
|
|
}
|
|
|
|
//
|
|
// hash IPv6 port
|
|
//
|
|
Temp = pAddress->m_SocketAddress.IPv6SocketAddress.sin6_port;
|
|
|
|
do
|
|
{
|
|
dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
|
|
Temp >>= bBitDepth;
|
|
} while ( Temp != 0 );
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
//
|
|
// hash first DWORD of IPX address
|
|
//
|
|
Temp = *reinterpret_cast<const DWORD*>( &pAddress->m_SocketAddress.IPXSocketAddress.sa_nodenum[ 0 ] );
|
|
|
|
do
|
|
{
|
|
dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
|
|
Temp >>= bBitDepth;
|
|
} while ( Temp != 0 );
|
|
|
|
//
|
|
// hash second DWORD of IPX address and IPX socket
|
|
//
|
|
Temp = *reinterpret_cast<const WORD*>( &pAddress->m_SocketAddress.IPXSocketAddress.sa_nodenum[ sizeof( DWORD ) ] );
|
|
Temp += ( pAddress->m_SocketAddress.IPXSocketAddress.sa_socket << ( sizeof( WORD ) * 8 ) );
|
|
|
|
do
|
|
{
|
|
dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
|
|
Temp >>= bBitDepth;
|
|
} while ( Temp != 0 );
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
DNASSERT(pAddress->GetFamily() == AF_INET);
|
|
|
|
//
|
|
// hash IP address
|
|
//
|
|
Temp = pAddress->m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr;
|
|
|
|
do
|
|
{
|
|
dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
|
|
Temp >>= bBitDepth;
|
|
} while ( Temp != 0 );
|
|
|
|
//
|
|
// hash IP port
|
|
//
|
|
Temp = pAddress->m_SocketAddress.IPSocketAddress.sin_port;
|
|
|
|
do
|
|
{
|
|
dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
|
|
Temp >>= bBitDepth;
|
|
} while ( Temp != 0 );
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
return dwReturn;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::GuidFromInternalAddressWithoutPort - get a guid from the internal
|
|
// address without a port.
|
|
//
|
|
// Entry: Reference to desintation GUID
|
|
//
|
|
// Exit: Nothing
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::GuidFromInternalAddressWithoutPort"
|
|
|
|
void CSocketAddress::GuidFromInternalAddressWithoutPort( GUID * pOutputGuid ) const
|
|
{
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
GuidFromAddress( pOutputGuid, &m_SocketAddress.SocketAddress );
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
union
|
|
{
|
|
SOCKADDR SockAddr;
|
|
SOCKADDR_IPX IPXSockAddr;
|
|
} TempSocketAddress;
|
|
|
|
|
|
memcpy( &TempSocketAddress.SockAddr, &m_SocketAddress.SocketAddress, sizeof( TempSocketAddress.SockAddr ) );
|
|
TempSocketAddress.IPXSockAddr.sa_socket = 0;
|
|
GuidFromAddress( pOutputGuid, &TempSocketAddress.SockAddr );
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
union
|
|
{
|
|
SOCKADDR SockAddr;
|
|
SOCKADDR_IN IPSockAddr;
|
|
} TempSocketAddress;
|
|
|
|
|
|
DNASSERT(GetFamily() == AF_INET);
|
|
memcpy( &TempSocketAddress.SockAddr, &m_SocketAddress.SocketAddress, sizeof( TempSocketAddress.SockAddr ) );
|
|
TempSocketAddress.IPSockAddr.sin_port = 0;
|
|
GuidFromAddress( pOutputGuid, &TempSocketAddress.SockAddr );
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::IsUndefinedHostAddress - determine if this is an undefined host
|
|
// address
|
|
//
|
|
// Entry: Nothing
|
|
//
|
|
// Exit: Boolean indicating whether this is an undefined host address
|
|
// TRUE = this is an undefined address
|
|
// FALSE = this is not an undefined address
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::IsUndefinedHostAddress"
|
|
|
|
BOOL CSocketAddress::IsUndefinedHostAddress( void ) const
|
|
{
|
|
BOOL fReturn;
|
|
|
|
|
|
fReturn = FALSE;
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&m_SocketAddress.IPv6SocketAddress.sin6_addr))
|
|
{
|
|
fReturn = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
|
|
DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_netnum ) == sizeof( DWORD ) );
|
|
DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 6 );
|
|
if ( ( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_netnum ) == 0 ) &&
|
|
( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 0 ) &&
|
|
( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum[ 2 ] ) == 0 ) )
|
|
{
|
|
fReturn = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
if ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_ANY )
|
|
{
|
|
fReturn = TRUE;
|
|
}
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::IsValidUnicastAddress - determine if this is valid unicast address
|
|
// address
|
|
//
|
|
// Entry: Whether to also allow the broadcast address or not.
|
|
//
|
|
// Exit: Boolean indicating whether this is a reachable address
|
|
// TRUE = this is a reachable address
|
|
// FALSE = this is not a reachable address
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::IsValidUnicastAddress"
|
|
|
|
BOOL CSocketAddress::IsValidUnicastAddress( BOOL fAllowBroadcastAddress ) const
|
|
{
|
|
BOOL fReturn;
|
|
|
|
|
|
fReturn = TRUE;
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
//
|
|
// Make sure the address is not all zeros.
|
|
//
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&m_SocketAddress.IPv6SocketAddress.sin6_addr))
|
|
{
|
|
fReturn = FALSE;
|
|
DNASSERTX(! "IPv6 address is :: (all zeros)!", 2);
|
|
}
|
|
|
|
//
|
|
// Make sure the address is not a multicast address, unless broadcast is allowed
|
|
// and it's the special enum multicast address.
|
|
//
|
|
if (IN6_IS_ADDR_MULTICAST(&m_SocketAddress.IPv6SocketAddress.sin6_addr))
|
|
{
|
|
if ((! fAllowBroadcastAddress) ||
|
|
(! IN6_ADDR_EQUAL(&m_SocketAddress.IPv6SocketAddress.sin6_addr, &c_in6addrEnumMulticast)))
|
|
{
|
|
fReturn = FALSE;
|
|
DNASSERTX(! "IPv6 address is a multicast address!", 2);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Disallow port 0.
|
|
//
|
|
if (m_SocketAddress.IPv6SocketAddress.sin6_port == 0)
|
|
{
|
|
fReturn = FALSE;
|
|
DNASSERTX(! "IPv6 port is 0!", 2);
|
|
}
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
|
|
DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_netnum ) == sizeof( DWORD ) );
|
|
DBG_CASSERT( sizeof( m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 6 );
|
|
if ( ( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_netnum ) == 0 ) &&
|
|
( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum ) == 0 ) &&
|
|
( *reinterpret_cast<const DWORD*>( &m_SocketAddress.IPXSocketAddress.sa_nodenum[ 2 ] ) == 0 ) )
|
|
{
|
|
fReturn = FALSE;
|
|
}
|
|
|
|
if (m_SocketAddress.IPXSocketAddress.sa_socket == 0)
|
|
{
|
|
fReturn = FALSE;
|
|
DNASSERTX(! "IPX socket/port is 0!", 2);
|
|
}
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
//
|
|
// Disallow 0.0.0.0, and multicast addresses 224.0.0.0 - 239.255.255.255.
|
|
//
|
|
if ( ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_ANY ) ||
|
|
( IS_CLASSD_IPV4_ADDRESS( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr ) ) )
|
|
{
|
|
fReturn = FALSE;
|
|
DNASSERTX(! "IPv4 address is 0.0.0.0 or multicast!", 2);
|
|
}
|
|
|
|
//
|
|
// Prevent the broadcast address, unless caller allows it.
|
|
//
|
|
if ( ( ! fAllowBroadcastAddress ) &&
|
|
( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == INADDR_BROADCAST ) )
|
|
{
|
|
fReturn = FALSE;
|
|
DNASSERTX(! "IPv4 address is broadcast!", 2);
|
|
}
|
|
|
|
//
|
|
// Disallow ports 0, 1900 (SSDP), 2234 (PAST), and 47624 (DPlay4).
|
|
//
|
|
if ( ( m_SocketAddress.IPSocketAddress.sin_port == HTONS( 0 ) ) ||
|
|
( m_SocketAddress.IPSocketAddress.sin_port == HTONS( 1900 ) ) ||
|
|
( m_SocketAddress.IPSocketAddress.sin_port == HTONS( 2234 ) ) ||
|
|
( m_SocketAddress.IPSocketAddress.sin_port == HTONS( 47624 ) ) )
|
|
{
|
|
fReturn = FALSE;
|
|
DNASSERTX(! "IPv4 port is 0, 1900, 2234, or 47624!", 2);
|
|
}
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
#ifndef DPNBUILD_NOREGISTRY
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::IsBannedAddress - determine if this is a banned address
|
|
//
|
|
// Entry: Nothing
|
|
//
|
|
// Exit: Boolean indicating whether this is a banned address
|
|
// TRUE = this is a banned address
|
|
// FALSE = this is not a banned address
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::IsBannedAddress"
|
|
|
|
BOOL CSocketAddress::IsBannedAddress( void ) const
|
|
{
|
|
BOOL fReturn;
|
|
|
|
|
|
fReturn = FALSE;
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
if (g_pHashBannedIPv4Addresses != NULL)
|
|
{
|
|
DWORD dwAddr;
|
|
DWORD dwBit;
|
|
PVOID pvMask;
|
|
|
|
|
|
//
|
|
// Try matching the IP address using masks.
|
|
// Start with a 32 bit mask (meaning match the IP address exactly)
|
|
// and gradually relax the mask until we get to a class A mask.
|
|
// We expect the network byte order of the IP address to be the
|
|
// opposite of host byte order.
|
|
//
|
|
dwAddr = m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr;
|
|
for(dwBit = 0x80000000; dwBit >= 0x00000080; dwBit >>= 1)
|
|
{
|
|
//
|
|
// Only hash based on this mask if we read in at least one entry that used it.
|
|
//
|
|
if (dwBit & g_dwBannedIPv4Masks)
|
|
{
|
|
if (g_pHashBannedIPv4Addresses->Find((PVOID) ((DWORD_PTR) dwAddr), &pvMask))
|
|
{
|
|
DNASSERT(((DWORD) ((DWORD_PTR) pvMask)) & dwBit);
|
|
DPFX(DPFPREP, 7, "Address %u.%u.%u.%u is banned (found as 0x%08x, bit 0x%08x).",
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b1,
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b2,
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b3,
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b4,
|
|
dwAddr,
|
|
dwBit);
|
|
fReturn = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
dwAddr &= ~dwBit;
|
|
}
|
|
}
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
//**********************************************************************
|
|
#endif // ! DPNBUILD_NOREGISTRY
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CSocketAddress::ChangeLoopBackToLocalAddress - change loopback to a local address
|
|
//
|
|
// Entry: Pointer to other address
|
|
//
|
|
// Exit: Nothing
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::ChangeLoopBackToLocalAddress"
|
|
|
|
void CSocketAddress::ChangeLoopBackToLocalAddress( const CSocketAddress *const pOtherSocketAddress )
|
|
{
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (pOtherSocketAddress->GetFamily())
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
if (GetFamily() == AF_INET6)
|
|
{
|
|
SOCKADDR_IN6 *psaddrin6;
|
|
|
|
|
|
psaddrin6 = (SOCKADDR_IN6*) GetAddress();
|
|
if (IN6_IS_ADDR_LOOPBACK(&psaddrin6->sin6_addr))
|
|
{
|
|
memcpy(&psaddrin6->sin6_addr,
|
|
&(((SOCKADDR_IN6*) pOtherSocketAddress->GetAddress())->sin6_addr),
|
|
sizeof(psaddrin6->sin6_addr));
|
|
psaddrin6->sin6_scope_id = ((SOCKADDR_IN6*) pOtherSocketAddress->GetAddress())->sin6_scope_id;
|
|
|
|
DPFX(DPFPREP, 2, "Changing IPv6 loopback address to:" );
|
|
DumpSocketAddress( 2, (SOCKADDR*) psaddrin6, AF_INET6 );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
DNASSERT( pOtherSocketAddress != NULL );
|
|
//
|
|
// there is no 'loopback' for IPX so this function doesn't do anything
|
|
//
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
if (GetFamily() == AF_INET)
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
{
|
|
if ( m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr == IP_LOOPBACK_ADDRESS )
|
|
{
|
|
DPFX(DPFPREP, 2, "Changing IPv4 loopback address to %u.%u.%u.%u.",
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b1,
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b2,
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b3,
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_un_b.s_b4);
|
|
m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr = pOtherSocketAddress->m_SocketAddress.IPSocketAddress.sin_addr.S_un.S_addr;
|
|
}
|
|
}
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// EncryptGuid - encrypt a guid
|
|
//
|
|
// Entry: Pointer to source guid
|
|
// Pointer to destination guid
|
|
// Pointer to encryption key
|
|
//
|
|
// Exit: Nothing
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "EncryptGuid"
|
|
|
|
void EncryptGuid( const GUID *const pSourceGuid,
|
|
GUID *const pDestinationGuid,
|
|
const GUID *const pEncryptionKey )
|
|
{
|
|
const char *pSourceBytes;
|
|
char *pDestinationBytes;
|
|
const char *pEncryptionBytes;
|
|
DWORD_PTR dwIndex;
|
|
|
|
|
|
DNASSERT( pSourceGuid != NULL );
|
|
DNASSERT( pDestinationGuid != NULL );
|
|
DNASSERT( pEncryptionKey != NULL );
|
|
|
|
DBG_CASSERT( sizeof( pSourceBytes ) == sizeof( pSourceGuid ) );
|
|
pSourceBytes = reinterpret_cast<const char*>( pSourceGuid );
|
|
|
|
DBG_CASSERT( sizeof( pDestinationBytes ) == sizeof( pDestinationGuid ) );
|
|
pDestinationBytes = reinterpret_cast<char*>( pDestinationGuid );
|
|
|
|
DBG_CASSERT( sizeof( pEncryptionBytes ) == sizeof( pEncryptionKey ) );
|
|
pEncryptionBytes = reinterpret_cast<const char*>( pEncryptionKey );
|
|
|
|
DBG_CASSERT( ( sizeof( *pSourceGuid ) == sizeof( *pEncryptionKey ) ) &&
|
|
( sizeof( *pDestinationGuid ) == sizeof( *pEncryptionKey ) ) );
|
|
dwIndex = sizeof( *pSourceGuid );
|
|
while ( dwIndex != 0 )
|
|
{
|
|
dwIndex--;
|
|
pDestinationBytes[ dwIndex ] = pSourceBytes[ dwIndex ] ^ pEncryptionBytes[ dwIndex ];
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::GuidFromAddress"
|
|
void CSocketAddress::GuidFromAddress( GUID * pOutputGuid, const SOCKADDR * pSocketAddress ) const
|
|
{
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (pSocketAddress->sa_family)
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
const SOCKADDR_IN6 *pSocketAddressIPv6 = reinterpret_cast<const SOCKADDR_IN6*>( pSocketAddress );
|
|
|
|
|
|
DNASSERT((GetFamily() == AF_INET) || (GetFamily() == AF_INET6));
|
|
DBG_CASSERT(sizeof(pSocketAddressIPv6->sin6_addr) == sizeof(GUID));
|
|
|
|
//
|
|
// Hopefully the beginning of IPv6 addresses will never look like an IPv4
|
|
// socket family so our unpacking routine won't get confused.
|
|
//
|
|
DNASSERT(((SOCKADDR*) (&pSocketAddressIPv6->sin6_addr))->sa_family != AF_INET);
|
|
|
|
//
|
|
// Even though IPv6 addresses are already 128 bits long and fill an entire
|
|
// entire GUID, we need to somehow pack the scope ID for link local and
|
|
// site local addresses into the GUID as well. We do this by storing the
|
|
// scope ID in bytes 3-6. This is because the prefix identifier for link local
|
|
// addresses is FE80::/64, and for site local addresses is FEC0::/48,
|
|
// leaving us 38 bits of what should always be zeros after the 10 bit prefix
|
|
// headers. We round to 16 to get to the WORD boundary, and therefore
|
|
// have a handy 32 bits left.
|
|
//
|
|
if ((IN6_IS_ADDR_LINKLOCAL(&pSocketAddressIPv6->sin6_addr)) ||
|
|
(IN6_IS_ADDR_SITELOCAL(&pSocketAddressIPv6->sin6_addr)))
|
|
{
|
|
GUID guidTemp;
|
|
WORD * pawSrcAddr;
|
|
WORD * pawDstAddr;
|
|
|
|
|
|
memcpy(&guidTemp, &pSocketAddressIPv6->sin6_addr, sizeof(GUID));
|
|
|
|
//
|
|
// Assert that the scope is not 0 and that bits 17-48 really are zero.
|
|
// Then copy the scope ID.
|
|
// The destination bits are WORD, but not DWORD aligned.
|
|
//
|
|
DNASSERT(pSocketAddressIPv6->sin6_scope_id != 0);
|
|
pawSrcAddr = (WORD*) (&pSocketAddressIPv6->sin6_scope_id);
|
|
pawDstAddr = (WORD*) (&guidTemp);
|
|
DBG_CASSERT(sizeof(pSocketAddressIPv6->sin6_scope_id) == 4);
|
|
DNASSERT((pawDstAddr[1] == 0) && (pawDstAddr[2] == 0));
|
|
pawDstAddr[1] = pawSrcAddr[0];
|
|
pawDstAddr[2] = pawSrcAddr[1];
|
|
|
|
EncryptGuid( &guidTemp, pOutputGuid, &g_IPSPEncryptionGuid );
|
|
}
|
|
else
|
|
{
|
|
EncryptGuid( (GUID*) (&pSocketAddressIPv6->sin6_addr), pOutputGuid, &g_IPSPEncryptionGuid );
|
|
}
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
const SOCKADDR_IPX *pSocketAddressIPX = reinterpret_cast<const SOCKADDR_IPX*>( pSocketAddress );
|
|
|
|
|
|
DNASSERT(GetFamily() == AF_IPX);
|
|
memcpy( pOutputGuid, pSocketAddressIPX, sizeof( *pSocketAddressIPX ) );
|
|
memset( &( reinterpret_cast<BYTE*>( pOutputGuid )[ sizeof( *pSocketAddressIPX ) ] ), 0, ( sizeof( *pOutputGuid ) - sizeof( *pSocketAddressIPX ) ) );
|
|
EncryptGuid( pOutputGuid, pOutputGuid, &g_IPXSPEncryptionGuid );
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
const SOCKADDR_IN *pSocketAddressIP = reinterpret_cast<const SOCKADDR_IN*>( pSocketAddress );
|
|
|
|
|
|
DNASSERT(GetFamily() == AF_INET);
|
|
memcpy( pOutputGuid, pSocketAddressIP, ( sizeof( *pOutputGuid ) - sizeof( pSocketAddressIP->sin_zero ) ) );
|
|
memset( &( reinterpret_cast<BYTE*>( pOutputGuid )[ OFFSETOF( SOCKADDR_IN, sin_zero ) ] ), 0, sizeof( pSocketAddressIP->sin_zero ) );
|
|
EncryptGuid( pOutputGuid, pOutputGuid, &g_IPSPEncryptionGuid );
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::PoolAllocFunction"
|
|
BOOL CSocketAddress::PoolAllocFunction( void* pvItem, void* pvContext )
|
|
{
|
|
CSocketAddress* pAddress = (CSocketAddress*)pvItem;
|
|
|
|
|
|
// Base class
|
|
pAddress->m_Sig[0] = 'S';
|
|
pAddress->m_Sig[1] = 'P';
|
|
pAddress->m_Sig[2] = 'A';
|
|
pAddress->m_Sig[3] = 'D';
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::PoolGetFunction"
|
|
void CSocketAddress::PoolGetFunction( void* pvItem, void* pvContext )
|
|
{
|
|
CSocketAddress* pAddress = (CSocketAddress*)pvItem;
|
|
|
|
|
|
//
|
|
// The context is the socket address type if IPv6 and/or IPX are available in
|
|
// this build. If neither are available, it will be NULL, but SetFamilyProtocolAndSize
|
|
// should ignore the value.
|
|
//
|
|
pAddress->SetFamilyProtocolAndSize((short)(DWORD_PTR)pvContext);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CSocketAddress::PoolReturnFunction"
|
|
void CSocketAddress::PoolReturnFunction( void* pvItem )
|
|
{
|
|
#ifdef DBG
|
|
const CSocketAddress* pAddress = (CSocketAddress*)pvItem;
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
switch (pAddress->m_SocketAddress.SocketAddress.sa_family)
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
#ifndef DPNBUILD_NOIPV6
|
|
case AF_INET6:
|
|
{
|
|
DNASSERT( pAddress->m_iSocketAddressSize == sizeof( pAddress->m_SocketAddress.IPv6SocketAddress ) );
|
|
DNASSERT( pAddress->m_SocketAddress.IPSocketAddress.sin_family == AF_INET6 );
|
|
DNASSERT( pAddress->m_iSocketProtocol == IPPROTO_UDP );
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPV6
|
|
|
|
#ifndef DPNBUILD_NOIPX
|
|
case AF_IPX:
|
|
{
|
|
DNASSERT( pAddress->m_iSocketAddressSize == sizeof( pAddress->m_SocketAddress.IPXSocketAddress ) );
|
|
DNASSERT( pAddress->m_SocketAddress.IPXSocketAddress.sa_family == AF_IPX );
|
|
DNASSERT( pAddress->m_iSocketProtocol == NSPROTO_IPX );
|
|
break;
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
default:
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
{
|
|
DNASSERT( pAddress->m_iSocketAddressSize == sizeof( pAddress->m_SocketAddress.IPSocketAddress ) );
|
|
DNASSERT( pAddress->m_SocketAddress.IPSocketAddress.sin_family == AF_INET );
|
|
DNASSERT( pAddress->m_iSocketProtocol == IPPROTO_UDP );
|
|
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
|
|
break;
|
|
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
|
|
}
|
|
}
|
|
#endif // DBG
|
|
}
|