230 lines
4.7 KiB
C
230 lines
4.7 KiB
C
|
//=============================================================================
|
||
|
// Copyright (c) Microsoft Corporation
|
||
|
// Abstract:
|
||
|
// This module implements string-address conversion functions.
|
||
|
//=============================================================================
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
WCHAR *
|
||
|
FormatIPv6Address(
|
||
|
IN IN6_ADDR *Address,
|
||
|
IN DWORD dwScopeId
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Converts an IPv6 address to a string in a static buffer.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Address - Supplies the IPv6 address.
|
||
|
dwScopeId - Supplies the scope identifier.
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
Pointer to static buffer holding address literal string.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
static WCHAR Buffer[128];
|
||
|
ULONG buflen = sizeof(Buffer);
|
||
|
SOCKADDR_IN6 sin6;
|
||
|
|
||
|
ZeroMemory(&sin6, sizeof(sin6));
|
||
|
sin6.sin6_family = AF_INET6;
|
||
|
sin6.sin6_scope_id = dwScopeId;
|
||
|
sin6.sin6_addr = *Address;
|
||
|
|
||
|
if (WSAAddressToString((SOCKADDR *) &sin6,
|
||
|
sizeof sin6,
|
||
|
NULL, // LPWSAPROTOCOL_INFO
|
||
|
Buffer,
|
||
|
&buflen) == SOCKET_ERROR) {
|
||
|
wcscpy(Buffer, L"???");
|
||
|
}
|
||
|
|
||
|
return Buffer;
|
||
|
}
|
||
|
|
||
|
|
||
|
WCHAR *
|
||
|
FormatIPv6Prefix(
|
||
|
IN IN6_ADDR *Address,
|
||
|
IN ULONG Length
|
||
|
)
|
||
|
{
|
||
|
static WCHAR Buffer[128];
|
||
|
|
||
|
swprintf(Buffer, L"%s/%d", FormatIPv6Address(Address, 0), Length);
|
||
|
|
||
|
return Buffer;
|
||
|
}
|
||
|
|
||
|
WCHAR *
|
||
|
FormatIPv4Address(
|
||
|
IN IN_ADDR *Address
|
||
|
)
|
||
|
{
|
||
|
static WCHAR Buffer[128];
|
||
|
ULONG buflen = sizeof(Buffer);
|
||
|
SOCKADDR_IN sin;
|
||
|
|
||
|
ZeroMemory(&sin, sizeof(sin));
|
||
|
sin.sin_family = AF_INET;
|
||
|
sin.sin_addr = *Address;
|
||
|
|
||
|
if (WSAAddressToString((SOCKADDR *) &sin,
|
||
|
sizeof sin,
|
||
|
NULL, // LPWSAPROTOCOL_INFO
|
||
|
Buffer,
|
||
|
&buflen) == SOCKET_ERROR) {
|
||
|
wcscpy(Buffer, L"<invalid>");
|
||
|
}
|
||
|
|
||
|
return Buffer;
|
||
|
}
|
||
|
|
||
|
WCHAR *
|
||
|
FormatLinkLayerAddress(
|
||
|
IN ULONG Length,
|
||
|
IN UCHAR *Addr
|
||
|
)
|
||
|
{
|
||
|
static WCHAR Buffer[128];
|
||
|
|
||
|
switch (Length) {
|
||
|
case 6: {
|
||
|
int i, digit;
|
||
|
WCHAR *s = Buffer;
|
||
|
|
||
|
for (i = 0; i < 6; i++) {
|
||
|
if (i != 0)
|
||
|
*s++ = '-';
|
||
|
|
||
|
digit = Addr[i] >> 4;
|
||
|
if (digit < 10)
|
||
|
*s++ = digit + '0';
|
||
|
else
|
||
|
*s++ = digit - 10 + 'a';
|
||
|
|
||
|
digit = Addr[i] & 0xf;
|
||
|
if (digit < 10)
|
||
|
*s++ = digit + '0';
|
||
|
else
|
||
|
*s++ = digit - 10 + 'a';
|
||
|
}
|
||
|
*s = '\0';
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 4:
|
||
|
//
|
||
|
// IPv4 Address (6-over-4 link)
|
||
|
//
|
||
|
wcscpy(Buffer, FormatIPv4Address((struct in_addr *)Addr));
|
||
|
break;
|
||
|
|
||
|
case 0:
|
||
|
default:
|
||
|
//
|
||
|
// Null or loop-back address
|
||
|
//
|
||
|
Buffer[0] = '\0';
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return Buffer;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
GetIpv4Address(
|
||
|
IN PWCHAR pwszArgument,
|
||
|
OUT IN_ADDR *pipAddress
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Gets the IPv4 address from the string.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pwszArgument argument specifing an ip address
|
||
|
pipAddress ip address
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NO_ERROR if success
|
||
|
Failure code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS ntStatus;
|
||
|
PWCHAR Terminator;
|
||
|
|
||
|
//
|
||
|
// Parse unicode IPv4 address with "strict" semantics (full dotted-decimal
|
||
|
// only). There's no other function that does this today other than
|
||
|
// the Rtl function below.
|
||
|
//
|
||
|
ntStatus = RtlIpv4StringToAddressW(pwszArgument, TRUE, &Terminator,
|
||
|
pipAddress);
|
||
|
|
||
|
if (!NT_SUCCESS(ntStatus) || (*Terminator != 0)) {
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GetIpv6Prefix(
|
||
|
IN PWCHAR pwszArgument,
|
||
|
OUT IN6_ADDR *pipAddress,
|
||
|
OUT DWORD *dwPrefixLength
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS ntStatus;
|
||
|
PWCHAR Terminator;
|
||
|
DWORD Length = 0;
|
||
|
|
||
|
ntStatus = RtlIpv6StringToAddressW(pwszArgument, &Terminator,
|
||
|
pipAddress);
|
||
|
|
||
|
if (!NT_SUCCESS(ntStatus) || (*Terminator++ != L'/')) {
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
while (iswdigit(*Terminator)) {
|
||
|
Length = (Length * 10) + (*Terminator++ - L'0');
|
||
|
}
|
||
|
if (*Terminator != 0) {
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
*dwPrefixLength = Length;
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
GetIpv6Address(
|
||
|
IN PWCHAR pwszArgument,
|
||
|
OUT IN6_ADDR *pipAddress
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS ntStatus;
|
||
|
PWCHAR Terminator;
|
||
|
|
||
|
ntStatus = RtlIpv6StringToAddressW(pwszArgument, &Terminator,
|
||
|
pipAddress);
|
||
|
|
||
|
if (!NT_SUCCESS(ntStatus) || (*Terminator != 0)) {
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|