mirror of
https://github.com/reactos/reactos.git
synced 2024-09-16 07:39:32 +00:00
495 lines
11 KiB
C
495 lines
11 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS WinSock 2 API
|
|
* FILE: dll/win32/ws2_32/src/addrconv.c
|
|
* PURPOSE: Address and Port Conversion Support
|
|
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <ws2_32.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* DEFINES *******************************************************************/
|
|
|
|
#ifndef BE
|
|
|
|
/* DWORD network to host byte order conversion for little endian machines */
|
|
#define DN2H(dw) \
|
|
((((dw) & 0xFF000000L) >> 24) | \
|
|
(((dw) & 0x00FF0000L) >> 8) | \
|
|
(((dw) & 0x0000FF00L) << 8) | \
|
|
(((dw) & 0x000000FFL) << 24))
|
|
|
|
/* DWORD host to network byte order conversion for little endian machines */
|
|
#define DH2N(dw) \
|
|
((((dw) & 0xFF000000L) >> 24) | \
|
|
(((dw) & 0x00FF0000L) >> 8) | \
|
|
(((dw) & 0x0000FF00L) << 8) | \
|
|
(((dw) & 0x000000FFL) << 24))
|
|
|
|
/* WORD network to host order conversion for little endian machines */
|
|
#define WN2H(w) \
|
|
((((w) & 0xFF00) >> 8) | \
|
|
(((w) & 0x00FF) << 8))
|
|
|
|
/* WORD host to network byte order conversion for little endian machines */
|
|
#define WH2N(w) \
|
|
((((w) & 0xFF00) >> 8) | \
|
|
(((w) & 0x00FF) << 8))
|
|
|
|
#else /* BE */
|
|
|
|
/* DWORD network to host byte order conversion for big endian machines */
|
|
#define DN2H(dw) \
|
|
(dw)
|
|
|
|
/* DWORD host to network byte order conversion big endian machines */
|
|
#define DH2N(dw) \
|
|
(dw)
|
|
|
|
/* WORD network to host order conversion for big endian machines */
|
|
#define WN2H(w) \
|
|
(w)
|
|
|
|
/* WORD host to network byte order conversion for big endian machines */
|
|
#define WH2N(w) \
|
|
(w)
|
|
|
|
#endif /* BE */
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ULONG
|
|
WSAAPI
|
|
inet_addr(IN CONST CHAR FAR* cp)
|
|
{
|
|
register u_long val, base, n;
|
|
register unsigned char c;
|
|
u_long parts[4], *pp = parts;
|
|
if (!cp) return INADDR_ANY;
|
|
if (!isdigit(*cp)) return INADDR_NONE;
|
|
|
|
again:
|
|
/*
|
|
* Collect number up to ``.''.
|
|
* Values are specified as for C:
|
|
* 0x=hex, 0=octal, other=decimal.
|
|
*/
|
|
val = 0; base = 10;
|
|
if (*cp == '0') {
|
|
if (*++cp == 'x' || *cp == 'X')
|
|
base = 16, cp++;
|
|
else
|
|
base = 8;
|
|
}
|
|
while ((c = *cp)) {
|
|
if (isdigit(c)) {
|
|
val = (val * base) + (c - '0');
|
|
cp++;
|
|
continue;
|
|
}
|
|
if (base == 16 && isxdigit(c)) {
|
|
val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
|
|
cp++;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
if (*cp == '.') {
|
|
/*
|
|
* Internet format:
|
|
* a.b.c.d
|
|
* a.b.c (with c treated as 16-bits)
|
|
* a.b (with b treated as 24 bits)
|
|
*/
|
|
if (pp >= parts + 4) return (INADDR_NONE);
|
|
*pp++ = val;
|
|
cp++;
|
|
goto again;
|
|
}
|
|
/*
|
|
* Check for trailing characters.
|
|
*/
|
|
if (*cp && !isspace((UCHAR)*cp)) return (INADDR_NONE);
|
|
|
|
*pp++ = val;
|
|
/*
|
|
* Concoct the address according to
|
|
* the number of parts specified.
|
|
*/
|
|
n = (u_long)(pp - parts);
|
|
switch (n) {
|
|
|
|
case 1: /* a -- 32 bits */
|
|
val = parts[0];
|
|
break;
|
|
|
|
case 2: /* a.b -- 8.24 bits */
|
|
val = (parts[0] << 24) | (parts[1] & 0xffffff);
|
|
break;
|
|
|
|
case 3: /* a.b.c -- 8.8.16 bits */
|
|
val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
|
|
(parts[2] & 0xffff);
|
|
break;
|
|
|
|
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
|
val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
|
|
((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
|
|
break;
|
|
|
|
default:
|
|
return (INADDR_NONE);
|
|
}
|
|
val = htonl(val);
|
|
return (val);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
CHAR FAR*
|
|
WSAAPI
|
|
inet_ntoa(IN IN_ADDR in)
|
|
{
|
|
PWSPROCESS Process;
|
|
PWSTHREAD Thread;
|
|
INT ErrorCode;
|
|
WSADATA WsaData;
|
|
BOOL ManualLoad = FALSE;
|
|
CHAR b[10];
|
|
PCHAR p;
|
|
DPRINT("inet_ntoa: %lx\n", in);
|
|
|
|
/* Enter prolog */
|
|
if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
|
|
{
|
|
DPRINT("MANUAL LOAD\n");
|
|
|
|
/* Only fail if the error wasn't related to a missing WSAStartup */
|
|
if (ErrorCode != WSANOTINITIALISED)
|
|
{
|
|
/* Fail */
|
|
SetLastError(ErrorCode);
|
|
return NULL;
|
|
}
|
|
|
|
/* Apps aren't expected to call WSAStartup for this API, so we will */
|
|
if ((ErrorCode = WSAStartup(MAKEWORD(2,2), &WsaData)) != ERROR_SUCCESS)
|
|
{
|
|
/* We failed */
|
|
SetLastError(ErrorCode);
|
|
return NULL;
|
|
}
|
|
|
|
/* Try the prolog again */
|
|
ManualLoad = TRUE;
|
|
if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
|
|
{
|
|
/* Failed again... */
|
|
WSACleanup();
|
|
SetLastError(ErrorCode);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
p = Thread->Buffer;
|
|
_itoa(in.S_un.S_addr & 0xFF, b, 10);
|
|
strcpy(p, b);
|
|
_itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10);
|
|
strcat(p, ".");
|
|
strcat(p, b);
|
|
_itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10);
|
|
strcat(p, ".");
|
|
strcat(p, b);
|
|
_itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10);
|
|
strcat(p, ".");
|
|
strcat(p, b);
|
|
|
|
/* Cleanup the manual load */
|
|
if (ManualLoad) WSACleanup();
|
|
|
|
/* Return the buffer */
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ULONG
|
|
WSAAPI
|
|
htonl(IN ULONG hostlong)
|
|
{
|
|
return DH2N(hostlong);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
USHORT
|
|
WSAAPI
|
|
htons(IN USHORT hostshort)
|
|
{
|
|
return WH2N(hostshort);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ULONG
|
|
WSAAPI
|
|
ntohl(IN ULONG netlong)
|
|
{
|
|
return DN2H(netlong);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
USHORT
|
|
WSAAPI
|
|
ntohs(IN USHORT netshort)
|
|
{
|
|
return WN2H(netshort);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
INT
|
|
WSAAPI
|
|
WSAHtonl(IN SOCKET s,
|
|
IN ULONG hostlong,
|
|
OUT ULONG FAR* lpnetlong)
|
|
{
|
|
INT ErrorCode;
|
|
PWSSOCKET Socket;
|
|
DPRINT("WSAHtonl: %p, %lx, %p\n", s, hostlong, lpnetlong);
|
|
|
|
/* Check for WSAStartup */
|
|
if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
|
|
{
|
|
/* Make sure we got a parameter */
|
|
if (!lpnetlong)
|
|
{
|
|
/* Fail */
|
|
SetLastError(WSAEFAULT);
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
/* Get the Socket Context */
|
|
if ((Socket = WsSockGetSocket(s)))
|
|
{
|
|
/* Check which byte order to use */
|
|
if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
|
|
LITTLEENDIAN)
|
|
{
|
|
/* No conversion needed */
|
|
*lpnetlong = hostlong;
|
|
}
|
|
else
|
|
{
|
|
/* Use a swap */
|
|
*lpnetlong = DN2H(hostlong);
|
|
}
|
|
|
|
/* Dereference the socket */
|
|
WsSockDereference(Socket);
|
|
|
|
/* Return success */
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
/* Set the error code */
|
|
ErrorCode = WSAENOTSOCK;
|
|
}
|
|
}
|
|
|
|
/* Return with error */
|
|
SetLastError(ErrorCode);
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
INT
|
|
WSAAPI
|
|
WSAHtons(IN SOCKET s,
|
|
IN USHORT hostshort,
|
|
OUT USHORT FAR* lpnetshort)
|
|
{
|
|
INT ErrorCode;
|
|
PWSSOCKET Socket;
|
|
DPRINT("WSAHtons: %p, %lx, %p\n", s, hostshort, lpnetshort);
|
|
|
|
/* Check for WSAStartup */
|
|
if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
|
|
{
|
|
/* Make sure we got a parameter */
|
|
if (!lpnetshort)
|
|
{
|
|
/* Fail */
|
|
SetLastError(WSAEFAULT);
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
/* Get the Socket Context */
|
|
if ((Socket = WsSockGetSocket(s)))
|
|
{
|
|
/* Check which byte order to use */
|
|
if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
|
|
LITTLEENDIAN)
|
|
{
|
|
/* No conversion needed */
|
|
*lpnetshort = hostshort;
|
|
}
|
|
else
|
|
{
|
|
/* Use a swap */
|
|
*lpnetshort = WN2H(hostshort);
|
|
}
|
|
|
|
/* Dereference the socket */
|
|
WsSockDereference(Socket);
|
|
|
|
/* Return success */
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
/* Set the error code */
|
|
ErrorCode = WSAENOTSOCK;
|
|
}
|
|
}
|
|
|
|
/* Return with error */
|
|
SetLastError(ErrorCode);
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
INT
|
|
WSAAPI
|
|
WSANtohl(IN SOCKET s,
|
|
IN ULONG netlong,
|
|
OUT ULONG FAR* lphostlong)
|
|
{
|
|
INT ErrorCode;
|
|
PWSSOCKET Socket;
|
|
DPRINT("WSANtohl: %p, %lx, %p\n", s, netlong, lphostlong);
|
|
|
|
/* Check for WSAStartup */
|
|
if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
|
|
{
|
|
/* Make sure we got a parameter */
|
|
if (!lphostlong)
|
|
{
|
|
/* Fail */
|
|
SetLastError(WSAEFAULT);
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
/* Get the Socket Context */
|
|
if ((Socket = WsSockGetSocket(s)))
|
|
{
|
|
/* Check which byte order to use */
|
|
if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
|
|
LITTLEENDIAN)
|
|
{
|
|
/* No conversion needed */
|
|
*lphostlong = netlong;
|
|
}
|
|
else
|
|
{
|
|
/* Use a swap */
|
|
*lphostlong = DN2H(netlong);
|
|
}
|
|
|
|
/* Dereference the socket */
|
|
WsSockDereference(Socket);
|
|
|
|
/* Return success */
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
/* Set the error code */
|
|
ErrorCode = WSAENOTSOCK;
|
|
}
|
|
}
|
|
|
|
/* Return with error */
|
|
SetLastError(ErrorCode);
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
INT
|
|
WSAAPI
|
|
WSANtohs(IN SOCKET s,
|
|
IN USHORT netshort,
|
|
OUT USHORT FAR* lphostshort)
|
|
{
|
|
INT ErrorCode;
|
|
PWSSOCKET Socket;
|
|
DPRINT("WSANtohs: %p, %lx, %p\n", s, netshort, lphostshort);
|
|
|
|
/* Check for WSAStartup */
|
|
if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
|
|
{
|
|
/* Make sure we got a parameter */
|
|
if (!lphostshort)
|
|
{
|
|
/* Fail */
|
|
SetLastError(WSAEFAULT);
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
/* Get the Socket Context */
|
|
if ((Socket = WsSockGetSocket(s)))
|
|
{
|
|
/* Check which byte order to use */
|
|
if (Socket->CatalogEntry->ProtocolInfo.iNetworkByteOrder ==
|
|
LITTLEENDIAN)
|
|
{
|
|
/* No conversion needed */
|
|
*lphostshort = netshort;
|
|
}
|
|
else
|
|
{
|
|
/* Use a swap */
|
|
*lphostshort = WN2H(netshort);
|
|
}
|
|
|
|
/* Dereference the socket */
|
|
WsSockDereference(Socket);
|
|
|
|
/* Return success */
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
/* Set the error code */
|
|
ErrorCode = WSAENOTSOCK;
|
|
}
|
|
}
|
|
|
|
/* Return with error */
|
|
SetLastError(ErrorCode);
|
|
return SOCKET_ERROR;
|
|
}
|
|
|