233 lines
5.5 KiB
C
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);
|
|
}
|