Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

729 lines
18 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
tcpcfg.c
Abstract:
TCP/IP translation routines
Author:
Mike Massa (mikemas) July 15, 1997
Revision History:
Who When What
-------- -------- ----------------------------------------------
mikemas 07-15-97 created
--*/
#include "clusrtlp.h"
#include <tdi.h>
#include <tdiinfo.h>
#include <ipinfo.h>
#include <llinfo.h>
#include <ntddtcp.h>
#include <winsock2.h>
#include <wchar.h>
//
// Private Constants
//
#define MAX_ADDRESS_STRING_LENGTH 15
#define MAX_ENDPOINT_STRING_LENGTH 5
VOID
ClRtlQueryTcpipInformation(
OUT LPDWORD MaxAddressStringLength,
OUT LPDWORD MaxEndpointStringLength,
OUT LPDWORD TdiAddressInfoLength
)
/*++
Routine Description:
Returns information about the TCP/IP protocol.
Arguments:
MaxAddressStringLength - A pointer to a variable into which to place
the maximum length, in characters, of a TCP/IP
network address value in string format, including
the terminating NULL. If this parameter is NUL,
it will be skipped.
MaxEndpointStringLength - A pointer to a variable into which to place
the maximum length, in characters, of a TCP/IP
transport endpoint value in string format,
including the terminating NUL. If this parameter
is NULL, it will be skipped.
Return Value:
None.
--*/
{
if (MaxAddressStringLength != NULL) {
*MaxAddressStringLength = MAX_ADDRESS_STRING_LENGTH;
}
if (MaxEndpointStringLength != NULL) {
*MaxEndpointStringLength = MAX_ENDPOINT_STRING_LENGTH;
}
if (TdiAddressInfoLength != NULL) {
*TdiAddressInfoLength = sizeof(TDI_ADDRESS_INFO) -
sizeof(TRANSPORT_ADDRESS) +
sizeof(TA_IP_ADDRESS);
}
return;
} // ClRtlQueryTcpipInformation
DWORD
ClRtlTcpipAddressToString(
ULONG AddressValue,
LPWSTR * AddressString
)
/*++
Routine Description:
Converts a binary representation of a TCP/IP network address,
in network byte order, into a string representation.
Arguments:
AddressValue - The binary value, in network byte order, to convert.
AddressString - A pointer to a pointer to a unicode string buffer into
which to place the converted value. If this parameter
is NULL, the string buffer will be allocated and
must be freed by the caller.
Return Value:
ERROR_SUCCESS if the operation was successful.
A Windows error code otherwise.
--*/
{
DWORD status;
NTSTATUS ntStatus;
UNICODE_STRING unicodeString;
ANSI_STRING ansiString;
LPSTR ansiBuffer;
LPWSTR addressString;
BOOLEAN allocatedStringBuffer = FALSE;
USHORT maxStringLength = (MAX_ADDRESS_STRING_LENGTH + 1) *
sizeof(WCHAR);
if (*AddressString == NULL) {
addressString = LocalAlloc(LMEM_FIXED, maxStringLength);
if (addressString == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
allocatedStringBuffer = TRUE;
}
else {
addressString = *AddressString;
}
ansiBuffer = inet_ntoa(*((struct in_addr *) &AddressValue));
if (ansiBuffer == NULL) {
status = ERROR_INVALID_PARAMETER;
goto error_exit;
}
RtlInitAnsiString(&ansiString, ansiBuffer);
unicodeString.Buffer = addressString;
unicodeString.Length = 0;
unicodeString.MaximumLength = maxStringLength;
ntStatus = RtlAnsiStringToUnicodeString(
&unicodeString,
&ansiString,
FALSE
);
if (ntStatus != STATUS_SUCCESS) {
status = RtlNtStatusToDosError(ntStatus);
goto error_exit;
}
*AddressString = addressString;
return(ERROR_SUCCESS);
error_exit:
if (allocatedStringBuffer) {
LocalFree(addressString);
}
return(status);
} // ClRtlTcpipAddressToString
DWORD
ClRtlTcpipStringToAddress(
LPCWSTR AddressString,
PULONG AddressValue
)
/*++
Routine Description:
Converts a string representation of a TCP/IP network address
into a binary representation in network byte order. The string must
be formatted in the canonical IP Address form (xxx.xxx.xxx.xxx).
Leading zeros are optional.
Arguments:
AddressString - A pointer to the string to convert.
AddressValue - A pointer to a variable into which to place the converted
binary value. The value will be in network byte order.
Return Value:
ERROR_SUCCESS if the operation was successful.
A Windows error code otherwise.
--*/
{
NTSTATUS status;
UNICODE_STRING unicodeString;
STRING ansiString;
ULONG address;
//
// Make sure the string is formatted correctly.
//
{
DWORD periodCount = 0;
DWORD digitCount = 0;
BOOLEAN isValid = TRUE;
LPCWSTR addressString = AddressString;
LPCWSTR digitString = AddressString;
while (*addressString != L'\0') {
if (*addressString == L'.') {
// Character is a period. There must be exactly
// three periods. There must be at least one
// digit before each period.
periodCount++;
if ((digitCount == 0) || (periodCount > 3)) {
isValid = FALSE;
} else if (wcstoul(digitString, NULL, 10) > 255) {
isValid = FALSE;
} else {
digitCount = 0;
digitString = addressString + 1;
}
} else if (iswdigit(*addressString)) {
// Character is a digit. There can be up to three
// decimal digits before each period, and the value
// can not exceed 255.
digitCount++;
if (digitCount > 3) {
isValid = FALSE;
}
}
else {
// Character is not a digit.
isValid = FALSE;
}
if (!isValid)
break;
addressString++;
}
if ((periodCount != 3) ||
(digitCount == 0) ||
(wcstoul(digitString, NULL, 10) > 255)) {
isValid = FALSE;
}
if (!isValid)
return(ERROR_INVALID_PARAMETER);
}
RtlInitUnicodeString(&unicodeString, AddressString);
status = RtlUnicodeStringToAnsiString(
&ansiString,
&unicodeString,
TRUE
);
if (status == STATUS_SUCCESS) {
address = inet_addr(ansiString.Buffer);
RtlFreeAnsiString(&ansiString);
if (address == INADDR_NONE) {
if (lstrcmpW(AddressString, L"255.255.255.255") != 0) {
return(ERROR_INVALID_PARAMETER);
}
}
*AddressValue = address;
return(ERROR_SUCCESS);
}
return(status);
} // ClRtlTcpipStringToAddress
DWORD
ClRtlTcpipEndpointToString(
USHORT EndpointValue,
LPWSTR * EndpointString
)
/*++
Routine Description:
Converts a binary representation of a TCP/IP transport endpoint,
in network byte order, into a string representation.
Arguments:
EndpointValue - The binary value, in network byte order, to convert.
EndpointString - A pointer to a pointer to a unicode string buffer into
which to place the converted value. If this parameter
is NULL, the string buffer will be allocated and
must be freed by the caller.
Return Value:
ERROR_SUCCESS if the operation was successful.
A Windows error code otherwise.
--*/
{
DWORD status;
NTSTATUS ntStatus;
ULONG endpointValue;
LPWSTR endpointString;
USHORT maxStringLength = (MAX_ENDPOINT_STRING_LENGTH + 1) *
sizeof(WCHAR);
if (*EndpointString == NULL) {
endpointString = LocalAlloc(LMEM_FIXED, maxStringLength);
if (endpointString == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
*EndpointString = endpointString;
}
else {
endpointString = *EndpointString;
}
endpointValue = 0;
endpointValue = ntohs(EndpointValue);
_ultow( endpointValue, endpointString, 10);
return(ERROR_SUCCESS);
} // ClRtlTcpipEndpointToString
DWORD
ClRtlTcpipStringToEndpoint(
LPCWSTR EndpointString,
PUSHORT EndpointValue
)
/*++
Routine Description:
Converts a string representation of a TCP/IP transport endpoint
into a binary representation in network byte order.
Arguments:
EndpointString - A pointer to the string to convert.
EndpointValue - A pointer to a variable into which to place the converted
binary value. The value will be in network byte order.
Return Value:
ERROR_SUCCESS if the operation was successful.
A Windows error code otherwise.
--*/
{
ULONG endpoint;
DWORD length = lstrlenW(EndpointString);
if ( (length == 0) || (length > MAX_ENDPOINT_STRING_LENGTH) ) {
return(ERROR_INCORRECT_ADDRESS);
}
endpoint = wcstoul(EndpointString, NULL, 10);
if (endpoint > 0xFFFF) {
return(ERROR_INCORRECT_ADDRESS);
}
*EndpointValue = (USHORT) htons( ((USHORT) endpoint) );
return(ERROR_SUCCESS);
} // ClRtlTcpipStringToEndpoint
BOOL
ClRtlIsValidTcpipAddress(
IN ULONG Address
)
{
//
// Convert to little-endian format, since that is what the broken
// winsock macros require.
//
Address = ntohl(Address);
if ( (Address == 0) ||
(!IN_CLASSA(Address) && !IN_CLASSB(Address) && !IN_CLASSC(Address))
)
{
return(FALSE);
}
return(TRUE);
} // ClRtlIsValidTcpipAddress
BOOL
ClRtlIsValidTcpipSubnetMask(
IN ULONG SubnetMask
)
{
if ( (SubnetMask == 0xffffffff) || (SubnetMask == 0)) {
return(FALSE);
}
return(TRUE);
} // ClRtlIsValidTcpipSubnetMask
BOOL
ClRtlIsValidTcpipAddressAndSubnetMask(
IN ULONG Address,
IN ULONG SubnetMask
)
{
ULONG NetOnly = Address & SubnetMask;
ULONG HostOnly = Address & ~SubnetMask;
//
// make sure the address/subnet combination makes sense.
// This assumes that the address has already been validated
// by a call to ClRtlIsValidTcpipAddress
//
return !( NetOnly == 0 ||
NetOnly == SubnetMask ||
HostOnly == 0 ||
HostOnly == ~SubnetMask
);
} // ClRtlIsValidTcpipAddressAndSubnetMask
DWORD
ClRtlBuildTcpipTdiAddress(
IN LPWSTR NetworkAddress,
IN LPWSTR TransportEndpoint,
OUT LPVOID * TdiAddress,
OUT LPDWORD TdiAddressLength
)
/*++
Routine Description:
Builds a TDI Transport Address structure containing the specified
NetworkAddress and TransportEndpoint. The memory for the TDI address
is allocated by this routine and must be freed by the caller.
Arguments:
NetworkAddress - A pointer to a unicode string containing the
network address to encode.
TransportEndpoint - A pointer to a unicode string containing the
transport endpoint to encode.
TdiAddress - On output, contains the address of the TDI Transport
Address structure.
TdiAddressLength - On output, contains the length of the TDI Transport
address structure.
Return Value:
ERROR_SUCCESS if the operation was successful.
A Windows error code otherwise.
--*/
{
DWORD status;
PTA_IP_ADDRESS taIpAddress;
ULONG ipAddress;
USHORT udpPort;
status = ClRtlTcpipStringToAddress(NetworkAddress, &ipAddress);
if (status != ERROR_SUCCESS) {
return(status);
}
status = ClRtlTcpipStringToEndpoint(TransportEndpoint, &udpPort);
if (lstrlenW(TransportEndpoint) > MAX_ENDPOINT_STRING_LENGTH) {
return(ERROR_INCORRECT_ADDRESS);
}
if (status != ERROR_SUCCESS) {
return(status);
}
taIpAddress = LocalAlloc(LMEM_FIXED, sizeof(TA_IP_ADDRESS));
if (taIpAddress == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
ZeroMemory(taIpAddress, sizeof(TA_IP_ADDRESS));
taIpAddress->TAAddressCount = 1;
taIpAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IP);
taIpAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
taIpAddress->Address[0].Address[0].in_addr = ipAddress;
taIpAddress->Address[0].Address[0].sin_port = udpPort;
*TdiAddress = taIpAddress;
*TdiAddressLength = sizeof(TA_IP_ADDRESS);
return(ERROR_SUCCESS);
} // ClRtlBuildTcpipTdiAddress
DWORD
ClRtlBuildLocalTcpipTdiAddress(
IN LPWSTR NetworkAddress,
OUT LPVOID TdiAddress,
OUT LPDWORD TdiAddressLength
)
/*++
Routine Description:
Builds a TDI Transport Address structure which can be used to open
a local TDI Address Object. The TransportEndpoint is chosen by the
transport. The memory for the TDI address is allocated by this
routine and must be freed by the caller.
Arguments:
NetworkAddress - A pointer to a unicode string containing the
network address to encode.
TdiAddress - On output, contains the address of the TDI Transport
Address structure.
TdiAddressLength - On output, contains the length of the TDI Transport
address structure.
Return Value:
ERROR_SUCCESS if the operation was successful.
A Windows error code otherwise.
--*/
{
return(ClRtlBuildTcpipTdiAddress(
NetworkAddress,
L"0",
TdiAddress,
TdiAddressLength
));
} // ClRtlBuildLocalTcpipTdiAddress
DWORD
ClRtlParseTcpipTdiAddress(
IN LPVOID TdiAddress,
OUT LPWSTR * NetworkAddress,
OUT LPWSTR * TransportEndpoint
)
/*++
Routine Description:
Extracts the NetworkAddress and TransportEndpoint values from
a TDI address.
Arguments:
TdiAddress - A pointer to the TDI TRANSPORT_ADDRESS structure to parse.
NetworkAddress - A pointer to a pointer to a unicode string into which
the parsed network address will be placed. If this
parameter is NULL, the target string buffer will be
allocated and must be freed by the caller.
TransportEndpoint - A pointer to a pointer to a unicode string into
which the parsed transport endpoint will be placed.
If this parameter is NULL, the target string buffer
will be allocated and must be freed by the caller.
Return Value:
ERROR_SUCCESS if the operation was successful.
A Windows error code otherwise.
--*/
{
LONG i;
TA_ADDRESS * currentAddr;
TDI_ADDRESS_IP UNALIGNED * validAddr = NULL;
PTRANSPORT_ADDRESS addrList = TdiAddress;
DWORD status;
BOOLEAN allocatedAddressString = FALSE;
currentAddr = (TA_ADDRESS *)addrList->Address;
for (i = 0; i < addrList->TAAddressCount; i++) {
if (currentAddr->AddressType == TDI_ADDRESS_TYPE_IP) {
if (currentAddr->AddressLength >= TDI_ADDRESS_LENGTH_IP) {
validAddr = (TDI_ADDRESS_IP UNALIGNED *) currentAddr->Address;
break;
}
} else {
currentAddr = (TA_ADDRESS *)(currentAddr->Address +
currentAddr->AddressLength);
}
}
if (validAddr == NULL) {
return(ERROR_INCORRECT_ADDRESS);
}
if (NetworkAddress == NULL) {
allocatedAddressString = TRUE;
}
status = ClRtlTcpipAddressToString(
validAddr->in_addr,
NetworkAddress
);
if (status != ERROR_SUCCESS) {
return(status);
}
status = ClRtlTcpipEndpointToString(
validAddr->sin_port,
TransportEndpoint
);
if (status != ERROR_SUCCESS) {
if (allocatedAddressString) {
LocalFree(*NetworkAddress);
*NetworkAddress = NULL;
}
return(status);
}
return(ERROR_SUCCESS);
} // ClRtlParseTcpipTdiAddress
DWORD
ClRtlParseTcpipTdiAddressInfo(
IN LPVOID TdiAddressInfo,
OUT LPWSTR * NetworkAddress,
OUT LPWSTR * TransportEndpoint
)
/*++
Routine Description:
Extracts the NetworkAddress and TransportEndpoint values from
a TDI_ADDRESS_INFO structure.
Arguments:
TdiAddressInfo - A pointer to the TDI_ADDRESS_INFO structure to parse.
NetworkAddress - A pointer to a pointer to a unicode string into which
the parsed network address will be placed. If this
parameter is NULL, the target string buffer will be
allocated and must be freed by the caller.
TransportEndpoint - A pointer to a pointer to a unicode string into
which the parsed transport endpoint will be placed.
If this parameter is NULL, the target string buffer
will be allocated and must be freed by the caller.
Return Value:
ERROR_SUCCESS if the operation was successful.
A Windows error code otherwise.
--*/
{
DWORD status;
PTDI_ADDRESS_INFO addressInfo = TdiAddressInfo;
status = ClRtlParseTcpipTdiAddress(
&(addressInfo->Address),
NetworkAddress,
TransportEndpoint
);
return(status);
} // ClRtlParseTcpipTdiAddressInfo