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

4710 lines
133 KiB

/*==========================================================================
*
* 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
}