2004-09-29 05:10:48 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS TCP/IP protocol driver
|
|
|
|
* FILE: tcpip/address.c
|
|
|
|
* PURPOSE: Routines for handling addresses
|
|
|
|
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
|
|
* REVISIONS:
|
|
|
|
* CSH 01/08-2000 Created
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
|
|
extern int sprintf( char *out, const char *fmt, ... );
|
|
|
|
|
|
|
|
CHAR A2SStr[128];
|
|
|
|
|
|
|
|
PCHAR A2S(
|
|
|
|
PIP_ADDRESS Address)
|
|
|
|
/*
|
|
|
|
* FUNCTION: Convert an IP address to a string (for debugging)
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Address = Pointer to an IP address structure
|
|
|
|
* RETURNS:
|
|
|
|
* Pointer to buffer with string representation of IP address
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
ULONG ip;
|
|
|
|
PCHAR p;
|
|
|
|
|
|
|
|
p = A2SStr;
|
|
|
|
|
|
|
|
if (!Address) {
|
|
|
|
TI_DbgPrint(MIN_TRACE, ("NULL address given.\n"));
|
|
|
|
strcpy(p, "(NULL)");
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (Address->Type) {
|
|
|
|
case IP_ADDRESS_V4:
|
|
|
|
ip = DN2H(Address->Address.IPv4Address);
|
2005-05-08 02:16:32 +00:00
|
|
|
sprintf(p, "%d.%d.%d.%d",
|
|
|
|
(INT)((ip >> 24) & 0xFF),
|
|
|
|
(INT)((ip >> 16) & 0xFF),
|
|
|
|
(INT)((ip >> 8) & 0xFF),
|
2004-09-29 05:10:48 +00:00
|
|
|
(INT)(ip & 0xFF));
|
|
|
|
break;
|
2005-05-08 02:16:32 +00:00
|
|
|
|
2004-09-29 05:10:48 +00:00
|
|
|
case IP_ADDRESS_V6:
|
|
|
|
/* FIXME: IPv6 is not supported */
|
|
|
|
strcpy(p, "(IPv6 address not supported)");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG IPv4NToHl( ULONG Address ) {
|
2005-05-08 02:16:32 +00:00
|
|
|
return
|
2004-09-29 05:10:48 +00:00
|
|
|
((Address & 0xff) << 24) |
|
|
|
|
((Address & 0xff00) << 8) |
|
|
|
|
((Address >> 8) & 0xff00) |
|
|
|
|
((Address >> 24) & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT AddrCountPrefixBits( PIP_ADDRESS Netmask ) {
|
|
|
|
UINT Prefix = 0;
|
|
|
|
if( Netmask->Type == IP_ADDRESS_V4 ) {
|
|
|
|
ULONG BitTest = 0x80000000;
|
2005-05-08 02:16:32 +00:00
|
|
|
|
2004-09-29 05:10:48 +00:00
|
|
|
/* The mask has been read in network order. Put it in host order
|
|
|
|
* in order to scan it. */
|
|
|
|
|
|
|
|
ULONG TestMask = IPv4NToHl(Netmask->Address.IPv4Address);
|
2005-05-08 02:16:32 +00:00
|
|
|
|
2004-09-29 05:10:48 +00:00
|
|
|
while( (BitTest & TestMask) == BitTest ) {
|
|
|
|
Prefix++;
|
|
|
|
BitTest >>= 1;
|
|
|
|
}
|
|
|
|
return Prefix;
|
|
|
|
} else {
|
2005-05-08 02:16:32 +00:00
|
|
|
TI_DbgPrint(DEBUG_DATALINK, ("Don't know address type %d\n",
|
2004-09-29 05:10:48 +00:00
|
|
|
Netmask->Type));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-08 02:16:32 +00:00
|
|
|
VOID AddrWidenAddress( PIP_ADDRESS Network, PIP_ADDRESS Source,
|
2004-11-26 06:55:17 +00:00
|
|
|
PIP_ADDRESS Netmask ) {
|
|
|
|
if( Netmask->Type == IP_ADDRESS_V4 ) {
|
2005-02-12 03:53:19 +00:00
|
|
|
Network->Type = Netmask->Type;
|
2005-05-08 02:16:32 +00:00
|
|
|
Network->Address.IPv4Address =
|
2004-11-26 06:55:17 +00:00
|
|
|
Source->Address.IPv4Address & Netmask->Address.IPv4Address;
|
|
|
|
} else {
|
2005-05-08 02:16:32 +00:00
|
|
|
TI_DbgPrint(DEBUG_DATALINK, ("Don't know address type %d\n",
|
2004-11-26 06:55:17 +00:00
|
|
|
Netmask->Type));
|
|
|
|
*Network = *Source;
|
2005-05-08 02:16:32 +00:00
|
|
|
}
|
2004-11-26 06:55:17 +00:00
|
|
|
}
|
|
|
|
|
2004-09-29 05:10:48 +00:00
|
|
|
VOID IPAddressFree(
|
|
|
|
PVOID Object)
|
|
|
|
/*
|
|
|
|
* FUNCTION: Frees an IP_ADDRESS object
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Object = Pointer to an IP address structure
|
|
|
|
* RETURNS:
|
|
|
|
* Nothing
|
|
|
|
*/
|
|
|
|
{
|
2009-11-21 23:53:43 +00:00
|
|
|
ExFreePoolWithTag(Object, IP_ADDRESS_TAG);
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN AddrIsUnspecified(
|
|
|
|
PIP_ADDRESS Address)
|
|
|
|
/*
|
|
|
|
* FUNCTION: Return wether IP address is an unspecified address
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Address = Pointer to an IP address structure
|
|
|
|
* RETURNS:
|
|
|
|
* TRUE if the IP address is an unspecified address, FALSE if not
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
switch (Address->Type) {
|
|
|
|
case IP_ADDRESS_V4:
|
2009-08-03 20:10:47 +00:00
|
|
|
return (Address->Address.IPv4Address == 0 ||
|
|
|
|
Address->Address.IPv4Address == 0xFFFFFFFF);
|
2004-09-29 05:10:48 +00:00
|
|
|
|
|
|
|
case IP_ADDRESS_V6:
|
|
|
|
/* FIXME: IPv6 is not supported */
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: Extract IP address from TDI address structure
|
|
|
|
* ARGUMENTS:
|
|
|
|
* AddrList = Pointer to transport address list to extract from
|
|
|
|
* Address = Address of a pointer to where an IP address is stored
|
|
|
|
* Port = Pointer to where port number is stored
|
|
|
|
* Cache = Address of pointer to a cached address (updated on return)
|
|
|
|
* RETURNS:
|
|
|
|
* Status of operation
|
|
|
|
*/
|
|
|
|
NTSTATUS AddrGetAddress(
|
|
|
|
PTRANSPORT_ADDRESS AddrList,
|
|
|
|
PIP_ADDRESS Address,
|
|
|
|
PUSHORT Port)
|
|
|
|
{
|
|
|
|
PTA_ADDRESS CurAddr;
|
|
|
|
INT i;
|
|
|
|
|
|
|
|
/* We can only use IP addresses. Search the list until we find one */
|
|
|
|
CurAddr = AddrList->Address;
|
|
|
|
|
|
|
|
for (i = 0; i < AddrList->TAAddressCount; i++) {
|
|
|
|
switch (CurAddr->AddressType) {
|
|
|
|
case TDI_ADDRESS_TYPE_IP:
|
|
|
|
if (CurAddr->AddressLength >= TDI_ADDRESS_LENGTH_IP) {
|
|
|
|
/* This is an IPv4 address */
|
|
|
|
PTDI_ADDRESS_IP ValidAddr = (PTDI_ADDRESS_IP)CurAddr->Address;
|
|
|
|
*Port = ValidAddr->sin_port;
|
|
|
|
Address->Type = CurAddr->AddressType;
|
|
|
|
ValidAddr = (PTDI_ADDRESS_IP)CurAddr->Address;
|
|
|
|
AddrInitIPv4(Address, ValidAddr->in_addr);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: Extract IP address from TDI address structure
|
|
|
|
* ARGUMENTS:
|
|
|
|
* TdiAddress = Pointer to transport address list to extract from
|
|
|
|
* Address = Address of a pointer to where an IP address is stored
|
|
|
|
* Port = Pointer to where port number is stored
|
|
|
|
* RETURNS:
|
|
|
|
* Status of operation
|
|
|
|
*/
|
|
|
|
NTSTATUS AddrBuildAddress(
|
2004-10-03 21:44:43 +00:00
|
|
|
PTRANSPORT_ADDRESS TaAddress,
|
2004-11-30 00:10:41 +00:00
|
|
|
PIP_ADDRESS Address,
|
2004-09-29 05:10:48 +00:00
|
|
|
PUSHORT Port)
|
|
|
|
{
|
|
|
|
PTDI_ADDRESS_IP ValidAddr;
|
2004-10-03 21:44:43 +00:00
|
|
|
PTA_ADDRESS TdiAddress = &TaAddress->Address[0];
|
2004-09-29 05:10:48 +00:00
|
|
|
|
|
|
|
if (TdiAddress->AddressType != TDI_ADDRESS_TYPE_IP) {
|
|
|
|
TI_DbgPrint
|
2004-10-03 21:44:43 +00:00
|
|
|
(MID_TRACE,("AddressType %x, Not valid\n", TdiAddress->AddressType));
|
2004-09-29 05:10:48 +00:00
|
|
|
return STATUS_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
if (TdiAddress->AddressLength < TDI_ADDRESS_LENGTH_IP) {
|
|
|
|
TI_DbgPrint
|
2005-05-08 02:16:32 +00:00
|
|
|
(MID_TRACE,("AddressLength %x, Not valid (expected %x)\n",
|
2004-09-29 05:10:48 +00:00
|
|
|
TdiAddress->AddressLength, TDI_ADDRESS_LENGTH_IP));
|
|
|
|
return STATUS_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ValidAddr = (PTDI_ADDRESS_IP)TdiAddress->Address;
|
|
|
|
|
2004-11-30 00:10:41 +00:00
|
|
|
AddrInitIPv4(Address, ValidAddr->in_addr);
|
2004-09-29 05:10:48 +00:00
|
|
|
*Port = ValidAddr->sin_port;
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: Returns wether two addresses are equal
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Address1 = Pointer to first address
|
|
|
|
* Address2 = Pointer to last address
|
|
|
|
* RETURNS:
|
|
|
|
* TRUE if Address1 = Address2, FALSE if not
|
|
|
|
*/
|
|
|
|
BOOLEAN AddrIsEqual(
|
|
|
|
PIP_ADDRESS Address1,
|
|
|
|
PIP_ADDRESS Address2)
|
|
|
|
{
|
2005-02-12 03:53:19 +00:00
|
|
|
if (Address1->Type != Address2->Type) {
|
|
|
|
DbgPrint("AddrIsEqual: Unequal Address Types\n");
|
2004-09-29 05:10:48 +00:00
|
|
|
return FALSE;
|
2005-02-12 03:53:19 +00:00
|
|
|
}
|
2004-09-29 05:10:48 +00:00
|
|
|
|
|
|
|
switch (Address1->Type) {
|
|
|
|
case IP_ADDRESS_V4:
|
|
|
|
return (Address1->Address.IPv4Address == Address2->Address.IPv4Address);
|
|
|
|
|
|
|
|
case IP_ADDRESS_V6:
|
|
|
|
return (RtlCompareMemory(&Address1->Address, &Address2->Address,
|
|
|
|
sizeof(IPv6_RAW_ADDRESS)) == sizeof(IPv6_RAW_ADDRESS));
|
|
|
|
break;
|
2005-02-12 03:53:19 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
DbgPrint("AddrIsEqual: Bad address type\n");
|
|
|
|
break;
|
2004-09-29 05:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: Returns wether Address1 is less than Address2
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Address1 = Pointer to first address
|
|
|
|
* Address2 = Pointer to last address
|
|
|
|
* RETURNS:
|
|
|
|
* -1 if Address1 < Address2, 1 if Address1 > Address2,
|
|
|
|
* or 0 if they are equal
|
|
|
|
*/
|
|
|
|
INT AddrCompare(
|
|
|
|
PIP_ADDRESS Address1,
|
|
|
|
PIP_ADDRESS Address2)
|
|
|
|
{
|
|
|
|
switch (Address1->Type) {
|
|
|
|
case IP_ADDRESS_V4: {
|
|
|
|
ULONG Addr1, Addr2;
|
|
|
|
if (Address2->Type == IP_ADDRESS_V4) {
|
|
|
|
Addr1 = DN2H(Address1->Address.IPv4Address);
|
|
|
|
Addr2 = DN2H(Address2->Address.IPv4Address);
|
|
|
|
if (Addr1 < Addr2)
|
|
|
|
return -1;
|
|
|
|
else
|
|
|
|
if (Addr1 == Addr2)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
/* FIXME: Support IPv6 */
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
case IP_ADDRESS_V6:
|
|
|
|
/* FIXME: Support IPv6 */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: Returns wether two addresses are equal with IPv4 as input
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Address1 = Pointer to first address
|
|
|
|
* Address2 = Pointer to last address
|
|
|
|
* RETURNS:
|
|
|
|
* TRUE if Address1 = Address2, FALSE if not
|
|
|
|
*/
|
|
|
|
BOOLEAN AddrIsEqualIPv4(
|
|
|
|
PIP_ADDRESS Address1,
|
|
|
|
IPv4_RAW_ADDRESS Address2)
|
|
|
|
{
|
|
|
|
if (Address1->Type == IP_ADDRESS_V4)
|
|
|
|
return (Address1->Address.IPv4Address == Address2);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-27 15:02:47 +00:00
|
|
|
unsigned long NTAPI inet_addr(const char *AddrString)
|
2004-09-29 05:10:48 +00:00
|
|
|
/*
|
|
|
|
* Convert an ansi string dotted-quad address to a ulong
|
|
|
|
* NOTES:
|
2005-05-08 02:16:32 +00:00
|
|
|
* - this isn't quite like the real inet_addr() - * it doesn't
|
2004-09-29 05:10:48 +00:00
|
|
|
* handle "10.1" and similar - but it's good enough.
|
|
|
|
* - Returns in *host* byte order, unlike real inet_addr()
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
ULONG Octets[4] = {0,0,0,0};
|
|
|
|
ULONG i = 0;
|
|
|
|
|
|
|
|
if(!AddrString)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
while(*AddrString)
|
|
|
|
{
|
|
|
|
CHAR c = *AddrString;
|
|
|
|
AddrString++;
|
|
|
|
|
|
|
|
if(c == '.')
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(c < '0' || c > '9')
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
Octets[i] *= 10;
|
|
|
|
Octets[i] += (c - '0');
|
|
|
|
|
|
|
|
if(Octets[i] > 255)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Octets[3] << 24) + (Octets[2] << 16) + (Octets[1] << 8) + Octets[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|