windows-nt/Source/XPSP1/NT/net/ias/services/util/inet.c
2020-09-26 16:20:57 +08:00

233 lines
5.5 KiB
C

///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997, Microsoft Corp. All rights reserved.
//
// FILE
//
// inet.c
//
// SYNOPSIS
//
// Implements the functions ias_inet_addr and ias_inet_ntoa.
//
// MODIFICATION HISTORY
//
// 09/17/1997 Original version.
// 02/04/1998 Added ias_inet_htow.
// 02/25/1998 Rewritten to use TCHAR macros.
//
///////////////////////////////////////////////////////////////////////////////
#include <tchar.h>
//////////
// Sentinel to indicate an invalid address.
//////////
#define INVALID_ADDRESS (0xFFFFFFFF)
//////////
// Macro to test if a character is a digit.
//////////
#define isdigit(p) ((_TUCHAR)(p - _T('0')) <= 9)
//////////
// Macro to strip whitespace characters
//////////
#define STRIP_WHITESPACE(p) \
(p) += _tcsspn((p), _T(" \t"))
//////////
// Macro to strip one byte of an IP address from a character string.
// 'p' pointer to the string to be parsed
// 'ul' unsigned long that will receive the result.
//////////
#define STRIP_BYTE(p,ul) { \
if (!isdigit(*p)) goto error; \
ul = *p++ - _T('0'); \
if (isdigit(*p)) { \
ul *= 10; ul += *p++ - _T('0'); \
if (isdigit(*p)) { \
ul *= 10; ul += *p++ - _T('0'); \
} \
} \
if (ul > 0xff) goto error; \
}
//////////
// Macro to strip a subnet width.
// 'p' pointer to the string to be parsed
// 'ul' unsigned long that will receive the result.
//////////
#define STRIP_WIDTH(p,ul) { \
if (!isdigit(*p)) goto error; \
ul = *p++ - _T('0'); \
if (isdigit(*p)) { \
ul *= 10; ul += *p++ - _T('0'); \
} \
if (ul > 32) goto error; \
}
//////////
// Helper function to parse a dotted decimal address.
//////////
static unsigned long __stdcall StringToAddress(
const _TCHAR* cp,
const _TCHAR** endptr
)
{
unsigned long token;
unsigned long addr;
STRIP_WHITESPACE(cp);
STRIP_BYTE(cp,addr);
if (*cp++ != _T('.')) goto error;
STRIP_BYTE(cp,token);
if (*cp++ != _T('.')) goto error;
addr <<= 8;
addr |= token;
STRIP_BYTE(cp,token);
if (*cp++ != _T('.')) goto error;
addr <<= 8;
addr |= token;
STRIP_BYTE(cp,token);
addr <<= 8;
addr |= token;
if (endptr) { *endptr = cp; }
return addr;
error:
if (endptr) { *endptr = cp; }
return INVALID_ADDRESS;
}
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION
//
// ias_inet_addr
//
// DESCRIPTION
//
// This function is similar to the WinSock inet_addr function (q.v.) except
// it returns the address in host order and it can operate on both ANSI
// and UNICODE strings.
//
///////////////////////////////////////////////////////////////////////////////
unsigned long __stdcall ias_inet_addr(const _TCHAR* cp)
{
unsigned long address;
const _TCHAR* end;
address = StringToAddress(cp, &end);
STRIP_WHITESPACE(end);
return (*end == _T('\0')) ? address : INVALID_ADDRESS;
}
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION
//
// IASStringToSubNet
//
// DESCRIPTION
//
// Similar to ias_inet_addr except it also parses an optional subnet width.
//
///////////////////////////////////////////////////////////////////////////////
unsigned long __stdcall IASStringToSubNet(
const _TCHAR* cp,
unsigned long* widthptr
)
{
unsigned long address, width;
const _TCHAR* end;
address = StringToAddress(cp, &end);
if (*end == _T('/'))
{
++end;
STRIP_WIDTH(end,width);
}
else
{
width = 32;
}
STRIP_WHITESPACE(end);
if (*end != _T('\0'))
{
goto error;
}
if (widthptr) { *widthptr = width; }
return address;
error:
return INVALID_ADDRESS;
}
//////////
// Macro to shove one byte of an IP address into a character string.
// 'p' pointer to the destination string.
// 'ul' value to be shoved.
//////////
#define SHOVE_BYTE(p, ul) { \
*--p = _T('0') + (_TCHAR)(ul % 10); \
if (ul /= 10) { \
*--p = _T('0') + (_TCHAR)(ul % 10); \
if (ul /= 10) { \
*--p = _T('0') + (_TCHAR)(ul % 10); \
} \
} \
}
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION
//
// ias_inet_ntoa
//
// DESCRIPTION
//
// This function uses the supplied buffer to convert a host order IPv4
// network address to dotted-decimal format.
//
///////////////////////////////////////////////////////////////////////////////
_TCHAR* __stdcall ias_inet_ntoa(unsigned long addr, _TCHAR* dst)
{
unsigned long token;
_TCHAR buffer[16], *p;
*(p = buffer + 15) = _T('\0');
token = (addr ) & 0xff;
SHOVE_BYTE(p, token);
*--p = _T('.');
token = (addr >> 8) & 0xff;
SHOVE_BYTE(p, token);
*--p = _T('.');
token = (addr >> 16) & 0xff;
SHOVE_BYTE(p, token);
*--p = _T('.');
token = (addr >> 24) & 0xff;
SHOVE_BYTE(p, token);
return _tcscpy(dst, p);
}