mirror of https://github.com/lianthony/NT4.0
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.
556 lines
13 KiB
556 lines
13 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
addrconv.c
|
|
|
|
Abstract:
|
|
|
|
This module contains address conversion routines for the Winsock 2
|
|
to Winsock 1.1 Mapper Service Provider.
|
|
|
|
The following routines are exported by this module:
|
|
|
|
WSPAddressToString()
|
|
WSPStringToAddress()
|
|
|
|
Author:
|
|
|
|
Keith Moore (keithmo) 29-May-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
// Macros for swapping the bytes in a long and a short.
|
|
//
|
|
|
|
#define SWAP_LONG(l) \
|
|
( ( ((l) >> 24) & 0x000000FFL ) | \
|
|
( ((l) >> 8) & 0x0000FF00L ) | \
|
|
( ((l) << 8) & 0x00FF0000L ) | \
|
|
( ((l) << 24) & 0xFF000000L ) )
|
|
|
|
#define SWAP_SHORT(s) \
|
|
( ( ((s) >> 8) & 0x00FF ) | \
|
|
( ((s) << 8) & 0xFF00 ) )
|
|
|
|
ULONG
|
|
MyInetAddr(
|
|
IN LPWSTR String,
|
|
OUT LPWSTR * Terminator
|
|
);
|
|
|
|
|
|
INT
|
|
WSPAPI
|
|
WSPAddressToString(
|
|
IN LPSOCKADDR lpsaAddress,
|
|
IN DWORD dwAddressLength,
|
|
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
|
|
OUT LPWSTR lpszAddressString,
|
|
IN OUT LPDWORD lpdwAddressStringLength,
|
|
OUT LPINT lpErrno
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts all components of a SOCKADDR structure into a human-
|
|
readable string representation of the address. This is used mainly for
|
|
display purposes.
|
|
|
|
Arguments:
|
|
|
|
lpsaAddress - Points to a SOCKADDR structure to translate into a string.
|
|
|
|
dwAddressLength - The length of the Address SOCKADDR.
|
|
|
|
lpProtocolInfo - The WSAPROTOCOL_INFOW struct for a particular provider.
|
|
|
|
lpszAddressString - A buffer which receives the human-readable address
|
|
string.
|
|
|
|
lpdwAddressStringLength - The length of the AddressString buffer. Returns
|
|
the length of the string actually copied into the buffer.
|
|
|
|
lpErrno - A pointer to the error code.
|
|
|
|
Return Value:
|
|
|
|
If no error occurs, WSPAddressToString() returns 0. Otherwise, it returns
|
|
SOCKET_ERROR, and a specific error code is available in lpErrno.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
INT err;
|
|
INT length;
|
|
INT result;
|
|
LPSOCKADDR_IN addr;
|
|
CHAR ansiString[sizeof("aaa.aaa.aaa.aaa:ppppp")];
|
|
|
|
SOCK_ENTER( "WSPAddressToString", lpsaAddress, (PVOID)dwAddressLength, lpProtocolInfo, lpszAddressString );
|
|
|
|
SOCK_ASSERT( lpErrno != NULL );
|
|
|
|
err = SockEnterApi( TRUE, FALSE );
|
|
|
|
if( err != NO_ERROR ) {
|
|
|
|
SOCK_EXIT( "WSPAddressToString", SOCKET_ERROR, TRUE );
|
|
*lpErrno = err;
|
|
return SOCKET_ERROR;
|
|
|
|
}
|
|
|
|
//
|
|
// Quick sanity check.
|
|
//
|
|
|
|
if( lpsaAddress == NULL ||
|
|
lpszAddressString == NULL ||
|
|
lpdwAddressStringLength == NULL ) {
|
|
|
|
err = WSAEFAULT;
|
|
goto exit;
|
|
|
|
}
|
|
|
|
if( lpsaAddress->sa_family != AF_INET ) {
|
|
|
|
err = WSA_INVALID_PARAMETER;
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Convert the address to string locally.
|
|
//
|
|
|
|
addr = (LPSOCKADDR_IN)lpsaAddress;
|
|
|
|
length = wsprintf(
|
|
ansiString,
|
|
"%d.%d.%d.%d:%u",
|
|
( addr->sin_addr.s_addr >> 0 ) && 0xFF,
|
|
( addr->sin_addr.s_addr >> 8 ) && 0xFF,
|
|
( addr->sin_addr.s_addr >> 16 ) && 0xFF,
|
|
( addr->sin_addr.s_addr >> 24 ) && 0xFF
|
|
);
|
|
|
|
if( addr->sin_port != 0 ) {
|
|
|
|
length =+ wsprintf(
|
|
ansiString + length,
|
|
":%u",
|
|
addr->sin_port
|
|
);
|
|
|
|
}
|
|
|
|
SOCK_ASSERT( length < sizeof(ansiString) );
|
|
|
|
//
|
|
// Map it to UNICODE.
|
|
//
|
|
|
|
result = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
ansiString,
|
|
-1,
|
|
lpszAddressString,
|
|
(INT)*lpdwAddressStringLength
|
|
);
|
|
|
|
if( result == 0 ) {
|
|
|
|
err = WSAEFAULT;
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
SOCK_ASSERT( err == NO_ERROR );
|
|
|
|
*lpdwAddressStringLength = (DWORD)result;
|
|
result = 0;
|
|
|
|
exit:
|
|
|
|
if( err != NO_ERROR ) {
|
|
|
|
*lpErrno = err;
|
|
result = SOCKET_ERROR;
|
|
|
|
}
|
|
|
|
SOCK_EXIT( "WSPAddressToString", result, (BOOL)( result == SOCKET_ERROR ) );
|
|
return result;
|
|
|
|
} // WSPAddressToString
|
|
|
|
|
|
|
|
INT
|
|
WSPAPI
|
|
WSPStringToAddress(
|
|
IN LPWSTR AddressString,
|
|
IN INT AddressFamily,
|
|
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
|
|
OUT LPSOCKADDR lpAddress,
|
|
IN OUT LPINT lpAddressLength,
|
|
OUT LPINT lpErrno
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts a human-readable string to a socket address
|
|
structure (SOCKADDR) suitable for pass to Windows Sockets routines which
|
|
take such a structure. Any missing components of the address will be
|
|
defaulted to a reasonable value if possible. For example, a missing port
|
|
number will be defaulted to zero.
|
|
|
|
Arguments:
|
|
|
|
AddressString - Points to the zero-terminated human-readable string to
|
|
convert.
|
|
|
|
AddressFamily - The address family to which the string belongs, or
|
|
AF_UNSPEC if it is unknown.
|
|
|
|
lpProtocolInfo - The provider's WSAPROTOCOL_INFOW struct.
|
|
|
|
lpAddress - A buffer which is filled with a single SOCKADDR structure.
|
|
|
|
lpAddressLength - The length of the Address buffer. Returns the size of
|
|
the resultant SOCKADDR structure.
|
|
|
|
lpErrno - A pointer to the error code.
|
|
|
|
Return Value:
|
|
|
|
If no error occurs, WSPStringToAddress() returns 0. Otherwise, a value
|
|
of SOCKET_ERROR is returned, and a specific error code is available
|
|
in lpErrno.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
INT err;
|
|
INT result;
|
|
LPWSTR terminator;
|
|
ULONG ipAddress;
|
|
USHORT port;
|
|
LPSOCKADDR_IN addr;
|
|
|
|
SOCK_ENTER( "WSPStringToAddress", AddressString, (PVOID)AddressFamily, lpProtocolInfo, lpAddress );
|
|
|
|
SOCK_ASSERT( lpErrno != NULL );
|
|
|
|
err = SockEnterApi( TRUE, FALSE );
|
|
|
|
if( err != NO_ERROR ) {
|
|
|
|
SOCK_EXIT( "WSPStringToAddress", SOCKET_ERROR, TRUE );
|
|
*lpErrno = err;
|
|
return SOCKET_ERROR;
|
|
|
|
}
|
|
|
|
//
|
|
// Quick sanity check.
|
|
//
|
|
|
|
if( AddressString == NULL ||
|
|
lpAddress == NULL ||
|
|
lpAddressLength == NULL ||
|
|
*lpAddressLength < sizeof(SOCKADDR_IN) ) {
|
|
|
|
err = WSAEFAULT;
|
|
goto exit;
|
|
|
|
}
|
|
|
|
if( AddressFamily != AF_INET ) {
|
|
|
|
err = WSA_INVALID_PARAMETER;
|
|
goto exit;
|
|
|
|
}
|
|
|
|
//
|
|
// Convert it.
|
|
//
|
|
|
|
//
|
|
// BUGBUG: VERIFY THE WCHAR CRT FUNCTIONS WORK UNDER WIN95!
|
|
//
|
|
|
|
ipAddress = MyInetAddr( AddressString, &terminator );
|
|
|
|
if( ipAddress == INADDR_NONE ) {
|
|
|
|
err = WSA_INVALID_PARAMETER;
|
|
goto exit;
|
|
|
|
}
|
|
|
|
if( *terminator == L':' ) {
|
|
|
|
WCHAR ch;
|
|
USHORT base;
|
|
|
|
terminator++;
|
|
|
|
port = 0;
|
|
base = 10;
|
|
|
|
if( *terminator == L'0' ) {
|
|
base = 8;
|
|
terminator++;
|
|
|
|
if( *terminator == L'x' ) {
|
|
base = 16;
|
|
terminator++;
|
|
}
|
|
}
|
|
|
|
while( ch = *terminator++ ) {
|
|
if( iswdigit(ch) ) {
|
|
port = ( port * base ) + ( ch - L'0' );
|
|
} else if( base == 16 && iswxdigit(ch) ) {
|
|
port = ( port << 4 );
|
|
port += ch + 10 - ( iswlower(ch) ? L'a' : L'A' );
|
|
} else {
|
|
return WSA_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
port = 0;
|
|
}
|
|
|
|
//
|
|
// Build the address.
|
|
//
|
|
|
|
ZeroMemory(
|
|
lpAddress,
|
|
sizeof(SOCKADDR_IN)
|
|
);
|
|
|
|
addr = (LPSOCKADDR_IN)lpAddress;
|
|
*lpAddressLength = sizeof(SOCKADDR_IN);
|
|
|
|
addr->sin_family = AF_INET;
|
|
addr->sin_port = port;
|
|
addr->sin_addr.s_addr = ipAddress;
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
SOCK_ASSERT( err == NO_ERROR );
|
|
|
|
result = 0;
|
|
|
|
exit:
|
|
|
|
if( err != NO_ERROR ) {
|
|
|
|
*lpErrno = err;
|
|
result = SOCKET_ERROR;
|
|
|
|
}
|
|
|
|
SOCK_EXIT( "WSPAddressToString", result, (BOOL)( result == SOCKET_ERROR ) );
|
|
return result;
|
|
|
|
} // WSPStringToAddress
|
|
|
|
ULONG
|
|
MyInetAddr(
|
|
IN LPWSTR String,
|
|
OUT LPWSTR * Terminator
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function interprets the character string specified by the cp
|
|
parameter. This string represents a numeric Internet address
|
|
expressed in the Internet standard ".'' notation. The value
|
|
returned is a number suitable for use as an Internet address. All
|
|
Internet addresses are returned in network order (bytes ordered from
|
|
left to right).
|
|
|
|
Internet Addresses
|
|
|
|
Values specified using the "." notation take one of the following
|
|
forms:
|
|
|
|
a.b.c.d a.b.c a.b a
|
|
|
|
When four parts are specified, each is interpreted as a byte of data
|
|
and assigned, from left to right, to the four bytes of an Internet
|
|
address. Note that when an Internet address is viewed as a 32-bit
|
|
integer quantity on the Intel architecture, the bytes referred to
|
|
above appear as "d.c.b.a''. That is, the bytes on an Intel
|
|
processor are ordered from right to left.
|
|
|
|
Note: The following notations are only used by Berkeley, and nowhere
|
|
else on the Internet. In the interests of compatibility with their
|
|
software, they are supported as specified.
|
|
|
|
When a three part address is specified, the last part is interpreted
|
|
as a 16-bit quantity and placed in the right most two bytes of the
|
|
network address. This makes the three part address format
|
|
convenient for specifying Class B network addresses as
|
|
"128.net.host''.
|
|
|
|
When a two part address is specified, the last part is interpreted
|
|
as a 24-bit quantity and placed in the right most three bytes of the
|
|
network address. This makes the two part address format convenient
|
|
for specifying Class A network addresses as "net.host''.
|
|
|
|
When only one part is given, the value is stored directly in the
|
|
network address without any byte rearrangement.
|
|
|
|
Arguments:
|
|
|
|
String - A character string representing a number expressed in the
|
|
Internet standard "." notation.
|
|
|
|
Terminator - Receives a pointer to the character that terminated
|
|
the conversion.
|
|
|
|
Return Value:
|
|
|
|
If no error occurs, inet_addr() returns an in_addr structure
|
|
containing a suitable binary representation of the Internet address
|
|
given. Otherwise, it returns the value INADDR_NONE.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG val, base, n;
|
|
WCHAR c;
|
|
ULONG parts[4], *pp = parts;
|
|
|
|
again:
|
|
/*
|
|
* Collect number up to ``.''.
|
|
* Values are specified as for C:
|
|
* 0x=hex, 0=octal, other=decimal.
|
|
*/
|
|
val = 0; base = 10;
|
|
if (*String == L'0') {
|
|
base = 8, String++;
|
|
if (*String == L'x' || *String == L'X')
|
|
base = 16, String++;
|
|
}
|
|
|
|
while (c = *String) {
|
|
if (iswdigit(c)) {
|
|
val = (val * base) + (c - L'0');
|
|
String++;
|
|
continue;
|
|
}
|
|
if (base == 16 && iswxdigit(c)) {
|
|
val = (val << 4) + (c + 10 - (islower(c) ? L'a' : L'A'));
|
|
String++;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
if (*String == L'.') {
|
|
/*
|
|
* Internet format:
|
|
* a.b.c.d
|
|
* a.b.c (with c treated as 16-bits)
|
|
* a.b (with b treated as 24 bits)
|
|
*/
|
|
/* GSS - next line was corrected on 8/5/89, was 'parts + 4' */
|
|
if (pp >= parts + 3) {
|
|
*Terminator = String;
|
|
return ((ULONG) -1);
|
|
}
|
|
*pp++ = val, String++;
|
|
goto again;
|
|
}
|
|
/*
|
|
* Check for trailing characters.
|
|
*/
|
|
if (*String && !iswspace(*String) && (*String != L':')) {
|
|
*Terminator = String;
|
|
return (INADDR_NONE);
|
|
}
|
|
*pp++ = val;
|
|
/*
|
|
* Concoct the address according to
|
|
* the number of parts specified.
|
|
*/
|
|
n = pp - parts;
|
|
switch ((int) n) {
|
|
|
|
case 1: /* a -- 32 bits */
|
|
val = parts[0];
|
|
break;
|
|
|
|
case 2: /* a.b -- 8.24 bits */
|
|
if ((parts[0] > 0xff) || (parts[1] > 0xffffff)) {
|
|
*Terminator = String;
|
|
return(INADDR_NONE);
|
|
}
|
|
val = (parts[0] << 24) | (parts[1] & 0xffffff);
|
|
break;
|
|
|
|
case 3: /* a.b.c -- 8.8.16 bits */
|
|
if ((parts[0] > 0xff) || (parts[1] > 0xff) ||
|
|
(parts[2] > 0xffff)) {
|
|
*Terminator = String;
|
|
return(INADDR_NONE);
|
|
}
|
|
val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
|
|
(parts[2] & 0xffff);
|
|
break;
|
|
|
|
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
|
if ((parts[0] > 0xff) || (parts[1] > 0xff) ||
|
|
(parts[2] > 0xff) || (parts[3] > 0xff)) {
|
|
*Terminator = String;
|
|
return(INADDR_NONE);
|
|
}
|
|
val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
|
|
((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
|
|
break;
|
|
|
|
default:
|
|
*Terminator = String;
|
|
return (INADDR_NONE);
|
|
}
|
|
|
|
val = SWAP_LONG(val);
|
|
*Terminator = String;
|
|
return (val);
|
|
}
|
|
|