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.
2542 lines
52 KiB
2542 lines
52 KiB
/*++
|
|
|
|
Copyright (c) 1996-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
straddr.c
|
|
|
|
Abstract:
|
|
|
|
Domain Name System (DNS) Library
|
|
|
|
Routines to string to\from address conversions.
|
|
|
|
Author:
|
|
|
|
Jim Gilroy (jamesg) December 1996
|
|
|
|
Revision History:
|
|
|
|
jamesg June 2000 New IP6 parsing.
|
|
jamesg Oct 2000 Created this module.
|
|
|
|
--*/
|
|
|
|
|
|
#include "local.h"
|
|
#include "ws2tcpip.h" // IP6 inaddr definitions
|
|
|
|
|
|
|
|
|
|
//
|
|
// String to address
|
|
//
|
|
|
|
BOOL
|
|
Dns_Ip6StringToAddress_A(
|
|
OUT PIP6_ADDRESS pIp6Addr,
|
|
IN PCSTR pString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert string to IP6 address.
|
|
|
|
Arguments:
|
|
|
|
pAddress -- ptr to IP6 address to be filled in
|
|
|
|
pString -- string with IP6 address
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful.
|
|
FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
PCHAR pstringEnd = NULL;
|
|
|
|
|
|
DNSDBG( PARSE2, (
|
|
"Dns_Ip6StringToAddress_A( %s )\n",
|
|
pString ));
|
|
|
|
//
|
|
// convert to IP6 address
|
|
//
|
|
|
|
status = RtlIpv6StringToAddressA(
|
|
pString,
|
|
& pstringEnd,
|
|
(PIN6_ADDR) pIp6Addr );
|
|
|
|
return( status == NO_ERROR && *pstringEnd==0 );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_Ip6StringToAddressEx_A(
|
|
OUT PIP6_ADDRESS pIp6Addr,
|
|
IN PCSTR pchString,
|
|
IN DWORD dwStringLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert string to IP6 address.
|
|
|
|
This version handles non-NULL-terminated strings
|
|
for DNS server file load.
|
|
|
|
Arguments:
|
|
|
|
pAddress -- ptr to IP6 address to be filled in
|
|
|
|
pchString -- string with IP6 address
|
|
|
|
dwStringLength -- string length
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful.
|
|
FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
CHAR tempBuf[ IP6_ADDRESS_STRING_BUFFER_LENGTH ];
|
|
PCSTR pstring;
|
|
|
|
DNSDBG( PARSE2, (
|
|
"Dns_Ip6StringToAddressEx_A( %.*s )\n"
|
|
"\tpchString = %p\n",
|
|
dwStringLength,
|
|
pchString,
|
|
pchString ));
|
|
|
|
//
|
|
// copy string if given length
|
|
// if no length assume NULL terminated
|
|
//
|
|
|
|
pstring = pchString;
|
|
|
|
if ( dwStringLength )
|
|
{
|
|
DWORD bufLength = IP6_ADDRESS_STRING_BUFFER_LENGTH;
|
|
|
|
if ( ! Dns_StringCopy(
|
|
tempBuf,
|
|
& bufLength,
|
|
(PCHAR) pstring,
|
|
dwStringLength,
|
|
DnsCharSetAnsi,
|
|
DnsCharSetAnsi ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
pstring = tempBuf;
|
|
}
|
|
|
|
// convert to IP6 address
|
|
|
|
return Dns_Ip6StringToAddress_A(
|
|
pIp6Addr,
|
|
pstring );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_Ip6StringToAddress_W(
|
|
OUT PIP6_ADDRESS pIp6Addr,
|
|
IN PCWSTR pwString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build IP6 address from wide string.
|
|
|
|
Arguments:
|
|
|
|
pwString -- unicode IP6 string
|
|
|
|
pIp6Addr -- addr to recv IP6 address
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful conversion.
|
|
FALSE on bad string.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
PWCHAR pstringEnd = NULL;
|
|
|
|
DNSDBG( PARSE2, (
|
|
"Dns_Ip6StringToAddress_W( %S )\n",
|
|
pwString ));
|
|
|
|
//
|
|
// convert to IP6 address
|
|
//
|
|
|
|
status = RtlIpv6StringToAddressW(
|
|
pwString,
|
|
& pstringEnd,
|
|
(PIN6_ADDR) pIp6Addr );
|
|
|
|
return( status == NO_ERROR && *pstringEnd==0 );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_Ip4StringToAddress_A(
|
|
OUT PIP4_ADDRESS pIp4Addr,
|
|
IN PCSTR pString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build IP4 address from narrow string.
|
|
|
|
Arguments:
|
|
|
|
pIp4Addr -- addr to recv IP6 address
|
|
|
|
pString -- unicode IP4 string
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful conversion.
|
|
FALSE on bad string.
|
|
|
|
--*/
|
|
{
|
|
IP4_ADDRESS ip;
|
|
|
|
// if inet_addr() returns error, verify then error out
|
|
|
|
ip = inet_addr( pString );
|
|
|
|
if ( ip == INADDR_BROADCAST &&
|
|
strcmp( pString, "255.255.255.255" ) != 0 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
*pIp4Addr = ip;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_Ip4StringToAddressEx_A(
|
|
OUT PIP4_ADDRESS pIp4Addr,
|
|
IN PCSTR pchString,
|
|
IN DWORD dwStringLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build IP4 address from narrow string.
|
|
|
|
This version handles non-NULL terminated strings
|
|
|
|
Arguments:
|
|
|
|
pIp4Addr -- addr to recv IP6 address
|
|
|
|
pString -- unicode IP4 string
|
|
|
|
dwStringLength -- string length; 0 if NULL terminated
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful conversion.
|
|
FALSE on bad string.
|
|
|
|
--*/
|
|
{
|
|
CHAR tempBuf[ IP4_ADDRESS_STRING_BUFFER_LENGTH ];
|
|
PCSTR pstring;
|
|
|
|
DNSDBG( PARSE2, (
|
|
"Dns_Ip4StringToAddressEx_A( %.*s )\n"
|
|
"\tpchString = %p\n",
|
|
dwStringLength,
|
|
pchString,
|
|
pchString ));
|
|
|
|
//
|
|
// copy string if given length
|
|
// if no length assume NULL terminated
|
|
//
|
|
|
|
pstring = pchString;
|
|
|
|
if ( dwStringLength )
|
|
{
|
|
DWORD bufLength = IP4_ADDRESS_STRING_BUFFER_LENGTH;
|
|
|
|
if ( ! Dns_StringCopy(
|
|
tempBuf,
|
|
& bufLength,
|
|
(PCHAR) pstring,
|
|
dwStringLength,
|
|
DnsCharSetAnsi,
|
|
DnsCharSetAnsi ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
pstring = tempBuf;
|
|
}
|
|
|
|
return Dns_Ip4StringToAddress_A(
|
|
pIp4Addr,
|
|
pstring );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_Ip4StringToAddress_W(
|
|
OUT PIP4_ADDRESS pIp4Addr,
|
|
IN PCWSTR pwString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build IP4 address from wide string.
|
|
|
|
Arguments:
|
|
|
|
pIp4Addr -- addr to recv IP6 address
|
|
|
|
pwString -- unicode IP6 string
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful conversion.
|
|
FALSE on bad string.
|
|
|
|
--*/
|
|
{
|
|
CHAR bufAddr[ IP4_ADDRESS_STRING_BUFFER_LENGTH ];
|
|
DWORD bufLength = IP4_ADDRESS_STRING_BUFFER_LENGTH;
|
|
|
|
// convert to narrow string
|
|
// - UTF8 quicker and just fine for numeric
|
|
|
|
if ( ! Dns_StringCopy(
|
|
bufAddr,
|
|
& bufLength,
|
|
(PCHAR) pwString,
|
|
0, // length unknown
|
|
DnsCharSetUnicode,
|
|
DnsCharSetUtf8
|
|
) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
return Dns_Ip4StringToAddress_A(
|
|
pIp4Addr,
|
|
bufAddr );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Combined IP4/IP6 string-to-address
|
|
//
|
|
|
|
BOOL
|
|
Dns_StringToDnsAddr_W(
|
|
OUT PDNS_ADDR pAddr,
|
|
IN PCWSTR pString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build address (IP4 or IP6) from reverse lookup name.
|
|
|
|
Arguments:
|
|
|
|
pAddr -- DNS_ADDR to receive address
|
|
|
|
pString -- address string
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful.
|
|
FALSE on error. GetLastError() for status.
|
|
|
|
--*/
|
|
{
|
|
return Dns_StringToDnsAddrEx(
|
|
pAddr,
|
|
(PCSTR) pString,
|
|
0, // any family
|
|
TRUE, // unicode
|
|
FALSE // forward
|
|
);
|
|
}
|
|
|
|
BOOL
|
|
Dns_StringToDnsAddr_A(
|
|
OUT PDNS_ADDR pAddr,
|
|
IN PCSTR pString
|
|
)
|
|
{
|
|
return Dns_StringToDnsAddrEx(
|
|
pAddr,
|
|
pString,
|
|
0, // any family
|
|
FALSE, // not unicode
|
|
FALSE // forward
|
|
);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_StringToAddress_W(
|
|
OUT PCHAR pAddrBuf,
|
|
IN OUT PDWORD pBufLength,
|
|
IN PCWSTR pString,
|
|
IN OUT PDWORD pAddrFamily
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build address (IP4 or IP6) from address string.
|
|
|
|
Arguments:
|
|
|
|
pAddrBuf -- buffer to receive address
|
|
|
|
pBufLength -- ptr to address length
|
|
input - length of buffer
|
|
output - length of address found
|
|
|
|
pString -- address string
|
|
|
|
pAddrFamily -- ptr to address family
|
|
input - zero for any family or particular family to check
|
|
output - family found; zero if no conversion
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful.
|
|
FALSE on error. GetLastError() for status.
|
|
|
|
--*/
|
|
{
|
|
return Dns_StringToAddressEx(
|
|
pAddrBuf,
|
|
pBufLength,
|
|
(PCSTR) pString,
|
|
pAddrFamily,
|
|
TRUE, // unicode
|
|
FALSE // forward
|
|
);
|
|
}
|
|
|
|
BOOL
|
|
Dns_StringToAddress_A(
|
|
OUT PCHAR pAddrBuf,
|
|
IN OUT PDWORD pBufLength,
|
|
IN PCSTR pString,
|
|
IN OUT PDWORD pAddrFamily
|
|
)
|
|
{
|
|
return Dns_StringToAddressEx(
|
|
pAddrBuf,
|
|
pBufLength,
|
|
pString,
|
|
pAddrFamily,
|
|
FALSE, // ANSI
|
|
FALSE // forward
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Address to string
|
|
//
|
|
|
|
PWCHAR
|
|
Dns_Ip6AddressToString_W(
|
|
OUT PWCHAR pwString,
|
|
IN PIP6_ADDRESS pIp6Addr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert IP6 address to string format.
|
|
|
|
Arguments:
|
|
|
|
pwString -- buffer to hold string; MUST be at least
|
|
IPV6_ADDRESS_STRING_LENGTH+1 in length
|
|
|
|
pAddress -- IP6 address to convert to string
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer (the terminating NULL).
|
|
|
|
--*/
|
|
{
|
|
// DCR: could be macro
|
|
|
|
return RtlIpv6AddressToStringW(
|
|
(PIN6_ADDR) pIp6Addr,
|
|
pwString );
|
|
}
|
|
|
|
|
|
|
|
PCHAR
|
|
Dns_Ip6AddressToString_A(
|
|
OUT PCHAR pchString,
|
|
IN PIP6_ADDRESS pIp6Addr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert IP6 address to string format.
|
|
|
|
Arguments:
|
|
|
|
pchString -- buffer to hold string; MUST be at least
|
|
IPV6_ADDRESS_STRING_LENGTH+1 in length
|
|
|
|
pAddress -- IP6 address to convert to string
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer (the terminating NULL).
|
|
|
|
--*/
|
|
{
|
|
// DCR: could be macro
|
|
|
|
return RtlIpv6AddressToStringA(
|
|
(PIN6_ADDR) pIp6Addr,
|
|
pchString );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Address to string -- IP4
|
|
//
|
|
|
|
PWCHAR
|
|
Dns_Ip4AddressToString_W(
|
|
OUT PWCHAR pwString,
|
|
IN PIP4_ADDRESS pIp4Addr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert IP4 address to string format.
|
|
|
|
Arguments:
|
|
|
|
pwString -- buffer to hold string; MUST be at least
|
|
IPV6_ADDRESS_STRING_LENGTH+1 in length
|
|
|
|
pAddress -- IP4 address to convert to string
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer (the terminating NULL).
|
|
|
|
--*/
|
|
{
|
|
IP4_ADDRESS ip = *pIp4Addr;
|
|
|
|
//
|
|
// convert IP4 address to string
|
|
// - address is in net order, lead byte in low memory
|
|
//
|
|
|
|
pwString += wsprintfW(
|
|
pwString,
|
|
L"%u.%u.%u.%u",
|
|
(UCHAR) (ip & 0x000000ff),
|
|
(UCHAR) ((ip & 0x0000ff00) >> 8),
|
|
(UCHAR) ((ip & 0x00ff0000) >> 16),
|
|
(UCHAR) ((ip & 0xff000000) >> 24)
|
|
);
|
|
|
|
return( pwString );
|
|
}
|
|
|
|
|
|
|
|
PCHAR
|
|
Dns_Ip4AddressToString_A(
|
|
OUT PCHAR pString,
|
|
IN PIP4_ADDRESS pIp4Addr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert IP4 address to string format.
|
|
|
|
Arguments:
|
|
|
|
pchString -- buffer to hold string; MUST be at least
|
|
IPV6_ADDRESS_STRING_LENGTH+1 in length
|
|
|
|
pAddress -- IP4 address to convert to string
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer (the terminating NULL).
|
|
|
|
--*/
|
|
{
|
|
IP4_ADDRESS ip = *pIp4Addr;
|
|
|
|
//
|
|
// convert IP4 address to string
|
|
// - address is in net order, lead byte in low memory
|
|
//
|
|
|
|
pString += sprintf(
|
|
pString,
|
|
"%u.%u.%u.%u",
|
|
(UCHAR) (ip & 0x000000ff),
|
|
(UCHAR) ((ip & 0x0000ff00) >> 8),
|
|
(UCHAR) ((ip & 0x00ff0000) >> 16),
|
|
(UCHAR) ((ip & 0xff000000) >> 24)
|
|
);
|
|
|
|
return( pString );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Address-to-string -- combined IP4/6
|
|
//
|
|
|
|
PCHAR
|
|
Dns_AddressToString_A(
|
|
OUT PCHAR pchString,
|
|
IN OUT PDWORD pStringLength,
|
|
IN PBYTE pAddr,
|
|
IN DWORD AddrLength,
|
|
IN DWORD AddrFamily
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert address to string format.
|
|
|
|
Arguments:
|
|
|
|
pchString -- buffer to hold string; MUST be at least
|
|
IPV6_ADDRESS_STRING_LENGTH+1 in length
|
|
|
|
pStringLength -- string buffer length
|
|
|
|
pAddr -- ptr to address
|
|
|
|
AddrLength -- address length
|
|
|
|
AddrFamily -- address family (AF_INET, AF_INET6)
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer (the terminating NULL).
|
|
NULL if no conversion.
|
|
|
|
--*/
|
|
{
|
|
DWORD length = *pStringLength;
|
|
|
|
// dispatch to conversion routine for this type
|
|
|
|
if ( AddrFamily == AF_INET )
|
|
{
|
|
if ( length < IP4_ADDRESS_STRING_LENGTH+1 )
|
|
{
|
|
length = IP4_ADDRESS_STRING_LENGTH+1;
|
|
goto Failed;
|
|
}
|
|
return Dns_Ip4AddressToString_A(
|
|
pchString,
|
|
(PIP4_ADDRESS) pAddr );
|
|
}
|
|
|
|
if ( AddrFamily == AF_INET6 )
|
|
{
|
|
if ( length < IP6_ADDRESS_STRING_LENGTH+1 )
|
|
{
|
|
length = IP6_ADDRESS_STRING_LENGTH+1;
|
|
goto Failed;
|
|
}
|
|
return Dns_Ip6AddressToString_A(
|
|
pchString,
|
|
(PIP6_ADDRESS) pAddr );
|
|
}
|
|
|
|
Failed:
|
|
|
|
*pStringLength = length;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// DNS_ADDR-to-string
|
|
//
|
|
|
|
PCHAR
|
|
Dns_DnsAddrToString_A(
|
|
OUT PCHAR pBuffer,
|
|
IN OUT PDWORD pBufLength,
|
|
IN PDNS_ADDR pAddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert address to string format.
|
|
|
|
Arguments:
|
|
|
|
pBuffer -- buffer to hold string;
|
|
if pBufLength not given, then MUST be at least
|
|
IPV6_ADDRESS_STRING_LENGTH+1 in length
|
|
|
|
pBufLength -- ptr to string buffer length
|
|
|
|
pAddr -- ptr to address
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer (the terminating NULL).
|
|
NULL if no conversion.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
|
|
//
|
|
// DCR: handle no buffer length given -- handles IP6 default?
|
|
//
|
|
|
|
//
|
|
// print support for IP4/IP6
|
|
//
|
|
|
|
if ( DnsAddr_IsIp4(pAddr) )
|
|
{
|
|
status = RtlIpv4AddressToStringExA(
|
|
&pAddr->SockaddrIn.sin_addr,
|
|
pAddr->SockaddrIn.sin_port,
|
|
pBuffer,
|
|
pBufLength );
|
|
}
|
|
else if ( DnsAddr_IsIp6(pAddr) )
|
|
{
|
|
status = RtlIpv6AddressToStringExA(
|
|
&pAddr->SockaddrIn6.sin6_addr,
|
|
pAddr->SockaddrIn6.sin6_scope_id,
|
|
pAddr->SockaddrIn6.sin6_port,
|
|
pBuffer,
|
|
pBufLength );
|
|
}
|
|
else
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
|
|
if ( !pBufLength || *pBufLength > 40 )
|
|
{
|
|
sprintf(
|
|
pBuffer,
|
|
"Invalid DNS_ADDR at %p",
|
|
pAddr );
|
|
}
|
|
pBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// return ptr to next char in buffer
|
|
//
|
|
|
|
if ( status == NO_ERROR )
|
|
{
|
|
pBuffer += *pBufLength;
|
|
}
|
|
else
|
|
{
|
|
pBuffer = NULL;
|
|
}
|
|
|
|
return pBuffer;
|
|
}
|
|
|
|
|
|
|
|
PWCHAR
|
|
Dns_DnsAddrToString_W(
|
|
OUT PWCHAR pBuffer,
|
|
IN PDWORD pBufLength,
|
|
IN PDNS_ADDR pAddr
|
|
)
|
|
{
|
|
DNS_STATUS status;
|
|
|
|
//
|
|
// print support for IP4/IP6
|
|
//
|
|
|
|
if ( DnsAddr_IsIp4(pAddr) )
|
|
{
|
|
status = RtlIpv4AddressToStringExW(
|
|
&pAddr->SockaddrIn.sin_addr,
|
|
pAddr->SockaddrIn.sin_port,
|
|
pBuffer,
|
|
pBufLength );
|
|
}
|
|
else if ( DnsAddr_IsIp6(pAddr) )
|
|
{
|
|
status = RtlIpv6AddressToStringExW(
|
|
&pAddr->SockaddrIn6.sin6_addr,
|
|
pAddr->SockaddrIn6.sin6_scope_id,
|
|
pAddr->SockaddrIn6.sin6_port,
|
|
pBuffer,
|
|
pBufLength );
|
|
}
|
|
else
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
|
|
if ( !pBufLength || *pBufLength > 40 )
|
|
{
|
|
wsprintfW(
|
|
pBuffer,
|
|
L"Invalid DNS_ADDR at %p",
|
|
pAddr );
|
|
}
|
|
pBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// return ptr to next char in buffer
|
|
//
|
|
|
|
if ( status == NO_ERROR )
|
|
{
|
|
pBuffer += *pBufLength;
|
|
}
|
|
else
|
|
{
|
|
pBuffer = NULL;
|
|
}
|
|
|
|
return pBuffer;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Reverse lookup address-to-name IP4
|
|
//
|
|
|
|
PCHAR
|
|
Dns_Ip4AddressToReverseName_A(
|
|
OUT PCHAR pBuffer,
|
|
IN IP4_ADDRESS IpAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write reverse lookup name, given corresponding IP
|
|
|
|
Arguments:
|
|
|
|
pBuffer -- ptr to buffer for reverse lookup name;
|
|
MUST contain at least DNS_MAX_REVERSE_NAME_BUFFER_LENGTH bytes
|
|
|
|
IpAddress -- IP address to create
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer.
|
|
|
|
--*/
|
|
{
|
|
DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseName_A()\n" ));
|
|
|
|
//
|
|
// write digits for each octect in IP address
|
|
// - note, it is in net order so lowest octect, is in highest memory
|
|
//
|
|
|
|
pBuffer += sprintf(
|
|
pBuffer,
|
|
"%u.%u.%u.%u.in-addr.arpa.",
|
|
(UCHAR) ((IpAddress & 0xff000000) >> 24),
|
|
(UCHAR) ((IpAddress & 0x00ff0000) >> 16),
|
|
(UCHAR) ((IpAddress & 0x0000ff00) >> 8),
|
|
(UCHAR) (IpAddress & 0x000000ff) );
|
|
|
|
return( pBuffer );
|
|
}
|
|
|
|
|
|
|
|
PWCHAR
|
|
Dns_Ip4AddressToReverseName_W(
|
|
OUT PWCHAR pBuffer,
|
|
IN IP4_ADDRESS IpAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write reverse lookup name, given corresponding IP
|
|
|
|
Arguments:
|
|
|
|
pBuffer -- ptr to buffer for reverse lookup name;
|
|
MUST contain at least DNS_MAX_REVERSE_NAME_BUFFER_LENGTH wide chars
|
|
|
|
IpAddress -- IP address to create
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer.
|
|
|
|
--*/
|
|
{
|
|
DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseName_W()\n" ));
|
|
|
|
//
|
|
// write digits for each octect in IP address
|
|
// - note, it is in net order so lowest octect, is in highest memory
|
|
//
|
|
|
|
pBuffer += wsprintfW(
|
|
pBuffer,
|
|
L"%u.%u.%u.%u.in-addr.arpa.",
|
|
(UCHAR) ((IpAddress & 0xff000000) >> 24),
|
|
(UCHAR) ((IpAddress & 0x00ff0000) >> 16),
|
|
(UCHAR) ((IpAddress & 0x0000ff00) >> 8),
|
|
(UCHAR) (IpAddress & 0x000000ff) );
|
|
|
|
return( pBuffer );
|
|
}
|
|
|
|
|
|
|
|
PCHAR
|
|
Dns_Ip4AddressToReverseNameAlloc_A(
|
|
IN IP4_ADDRESS IpAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create reverse lookup name string, given corresponding IP.
|
|
|
|
Caller must free the string.
|
|
|
|
Arguments:
|
|
|
|
IpAddress -- IP address to create
|
|
|
|
Return Value:
|
|
|
|
Ptr to new reverse lookup string.
|
|
|
|
--*/
|
|
{
|
|
PCHAR pch;
|
|
PCHAR pchend;
|
|
|
|
DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseNameAlloc_A()\n" ));
|
|
|
|
//
|
|
// allocate space for string
|
|
//
|
|
|
|
pch = ALLOCATE_HEAP( DNS_MAX_REVERSE_NAME_BUFFER_LENGTH );
|
|
if ( !pch )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// write string for IP
|
|
//
|
|
|
|
pchend = Dns_Ip4AddressToReverseName_A( pch, IpAddress );
|
|
if ( !pchend )
|
|
{
|
|
FREE_HEAP( pch );
|
|
return( NULL );
|
|
}
|
|
|
|
return( pch );
|
|
}
|
|
|
|
|
|
|
|
PWCHAR
|
|
Dns_Ip4AddressToReverseNameAlloc_W(
|
|
IN IP4_ADDRESS IpAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create reverse lookup name string, given corresponding IP.
|
|
|
|
Caller must free the string.
|
|
|
|
Arguments:
|
|
|
|
IpAddress -- IP address to create
|
|
|
|
Return Value:
|
|
|
|
Ptr to new reverse lookup string.
|
|
|
|
--*/
|
|
{
|
|
PWCHAR pch;
|
|
PWCHAR pchend;
|
|
|
|
DNSDBG( TRACE, ( "Dns_Ip4AddressToReverseNameAlloc_W()\n" ));
|
|
|
|
//
|
|
// allocate space for string
|
|
//
|
|
|
|
pch = ALLOCATE_HEAP( DNS_MAX_REVERSE_NAME_BUFFER_LENGTH * sizeof(WCHAR) );
|
|
if ( !pch )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// write string for IP
|
|
//
|
|
|
|
pchend = Dns_Ip4AddressToReverseName_W( pch, IpAddress );
|
|
if ( !pchend )
|
|
{
|
|
FREE_HEAP( pch );
|
|
return( NULL );
|
|
}
|
|
|
|
return( pch );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Reverse lookup address-to-name -- IP6
|
|
//
|
|
|
|
PCHAR
|
|
Dns_Ip6AddressToReverseName_A(
|
|
OUT PCHAR pBuffer,
|
|
IN IP6_ADDRESS Ip6Addr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write reverse lookup name, given corresponding IP6 address
|
|
|
|
Arguments:
|
|
|
|
pBuffer -- ptr to buffer for reverse lookup name;
|
|
MUST contain at least DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH bytes
|
|
|
|
Ip6Addr -- IP6 address to create reverse string for
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseName_A()\n" ));
|
|
|
|
//
|
|
// write digit for each nibble in IP6 address
|
|
//
|
|
// note we are reversing net order here
|
|
// since address is in net order and we are filling
|
|
// in least to most significant order
|
|
// - go DOWN through DWORDS
|
|
// - go DOWN through the BYTES
|
|
// - but we must put the lowest (least significant) nibble
|
|
// first as our bits are not in "bit net order"
|
|
// which is sending the highest bit in the byte first
|
|
//
|
|
|
|
#if 0
|
|
i = 4;
|
|
|
|
while ( i-- )
|
|
{
|
|
DWORD thisDword = Ip6Address.IP6Dword[i];
|
|
|
|
pBuffer += sprintf(
|
|
pBuffer,
|
|
"%u.%u.%u.%u.%u.%u.%u.%u.",
|
|
(thisDword & 0x0f000000) >> 24,
|
|
(thisDword & 0xf0000000) >> 28,
|
|
(thisDword & 0x000f0000) >> 16,
|
|
(thisDword & 0x00f00000) >> 20,
|
|
(thisDword & 0x00000f00) >> 8,
|
|
(thisDword & 0x0000f000) >> 12,
|
|
(thisDword & 0x0000000f) ,
|
|
(thisDword & 0x000000f0) >> 4
|
|
);
|
|
}
|
|
#endif
|
|
i = 16;
|
|
|
|
while ( i-- )
|
|
{
|
|
BYTE thisByte = Ip6Addr.IP6Byte[i];
|
|
|
|
pBuffer += sprintf(
|
|
pBuffer,
|
|
"%x.%x.",
|
|
(thisByte & 0x0f),
|
|
(thisByte & 0xf0) >> 4
|
|
);
|
|
}
|
|
|
|
pBuffer += sprintf(
|
|
pBuffer,
|
|
DNS_IP6_REVERSE_DOMAIN_STRING );
|
|
|
|
return( pBuffer );
|
|
}
|
|
|
|
|
|
|
|
PWCHAR
|
|
Dns_Ip6AddressToReverseName_W(
|
|
OUT PWCHAR pBuffer,
|
|
IN IP6_ADDRESS Ip6Addr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write reverse lookup name, given corresponding IP6 address
|
|
|
|
Arguments:
|
|
|
|
pBuffer -- ptr to buffer for reverse lookup name;
|
|
MUST contain at least DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH wide chars
|
|
|
|
Ip6Addr -- IP6 address to create reverse string for
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseName_W()\n" ));
|
|
|
|
//
|
|
// write digit for each nibble in IP6 address
|
|
// - in net order so lowest nibble is in highest memory
|
|
//
|
|
|
|
i = 16;
|
|
|
|
while ( i-- )
|
|
{
|
|
BYTE thisByte = Ip6Addr.IP6Byte[i];
|
|
|
|
pBuffer += wsprintfW(
|
|
pBuffer,
|
|
L"%x.%x.",
|
|
(thisByte & 0x0f),
|
|
(thisByte & 0xf0) >> 4
|
|
);
|
|
}
|
|
|
|
pBuffer += wsprintfW(
|
|
pBuffer,
|
|
DNS_IP6_REVERSE_DOMAIN_STRING_W );
|
|
|
|
return( pBuffer );
|
|
}
|
|
|
|
|
|
|
|
PCHAR
|
|
Dns_Ip6AddressToReverseNameAlloc_A(
|
|
IN IP6_ADDRESS Ip6Addr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create reverse lookup name given corresponding IP.
|
|
|
|
Caller must free the string.
|
|
|
|
Arguments:
|
|
|
|
Ip6Addr -- IP6 address to create reverse name for
|
|
|
|
Return Value:
|
|
|
|
Ptr to new reverse lookup name string.
|
|
|
|
--*/
|
|
{
|
|
PCHAR pch;
|
|
PCHAR pchend;
|
|
|
|
DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseNameAlloc_A()\n" ));
|
|
|
|
//
|
|
// allocate space for string
|
|
//
|
|
|
|
pch = ALLOCATE_HEAP( DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH );
|
|
if ( !pch )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// write string for IP
|
|
//
|
|
|
|
pchend = Dns_Ip6AddressToReverseName_A( pch, Ip6Addr );
|
|
if ( !pchend )
|
|
{
|
|
FREE_HEAP( pch );
|
|
return( NULL );
|
|
}
|
|
|
|
return( pch );
|
|
}
|
|
|
|
|
|
|
|
PWCHAR
|
|
Dns_Ip6AddressToReverseNameAlloc_W(
|
|
IN IP6_ADDRESS Ip6Addr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create reverse lookup name given corresponding IP.
|
|
|
|
Caller must free the string.
|
|
|
|
Arguments:
|
|
|
|
Ip6Addr -- IP6 address to create reverse name for
|
|
|
|
Return Value:
|
|
|
|
Ptr to new reverse lookup name string.
|
|
|
|
--*/
|
|
{
|
|
PWCHAR pch;
|
|
PWCHAR pchend;
|
|
|
|
DNSDBG( TRACE, ( "Dns_Ip6AddressToReverseNameAlloc_W()\n" ));
|
|
|
|
//
|
|
// allocate space for string
|
|
//
|
|
|
|
pch = (PWCHAR) ALLOCATE_HEAP(
|
|
DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH * sizeof(WCHAR) );
|
|
if ( !pch )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// write string for IP
|
|
//
|
|
|
|
pchend = Dns_Ip6AddressToReverseName_W( pch, Ip6Addr );
|
|
if ( !pchend )
|
|
{
|
|
FREE_HEAP( pch );
|
|
return( NULL );
|
|
}
|
|
|
|
return( pch );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Reverse name-to-address -- IP4
|
|
//
|
|
|
|
BOOL
|
|
Dns_Ip4ReverseNameToAddress_A(
|
|
OUT PIP4_ADDRESS pIp4Addr,
|
|
IN PCSTR pszName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get IP for reverse lookup name.
|
|
|
|
Arguments:
|
|
|
|
pIp4Addr -- addr to receive IP address if found
|
|
|
|
pszName -- name to lookup
|
|
|
|
Return Value:
|
|
|
|
TRUE -- if reverse lookup name converted to IP
|
|
FALSE -- if not IP4 reverse lookup name
|
|
|
|
--*/
|
|
{
|
|
#define SIZE_IP4REV (sizeof(".in-addr.arpa")-1)
|
|
|
|
CHAR nameBuffer[ DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH+1 ];
|
|
DWORD nameLength;
|
|
IP4_ADDRESS ip;
|
|
PCHAR pch;
|
|
DWORD i;
|
|
DWORD byte;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Dns_Ip4ReverseNameToAddress_A( %s )\n",
|
|
pszName ));
|
|
|
|
//
|
|
// validate name
|
|
// fail if
|
|
// - too long
|
|
// - too short
|
|
// - not in in-addr.arpa domain
|
|
//
|
|
|
|
nameLength = strlen( pszName );
|
|
|
|
if ( nameLength > DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
if ( pszName[nameLength-1] == '.' )
|
|
{
|
|
nameLength--;
|
|
}
|
|
if ( nameLength <= SIZE_IP4REV )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
nameLength -= SIZE_IP4REV;
|
|
|
|
if ( _strnicmp( ".in-addr.arpa", &pszName[nameLength], SIZE_IP4REV ) != 0 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
//
|
|
// copy reverse dotted decimal piece of name
|
|
//
|
|
|
|
RtlCopyMemory(
|
|
nameBuffer,
|
|
pszName,
|
|
nameLength );
|
|
|
|
nameBuffer[nameLength] = 0;
|
|
|
|
//
|
|
// read digits
|
|
//
|
|
|
|
ip = 0;
|
|
i = 0;
|
|
|
|
pch = nameBuffer + nameLength;
|
|
|
|
while ( 1 )
|
|
{
|
|
--pch;
|
|
|
|
if ( *pch == '.' )
|
|
{
|
|
*pch = 0;
|
|
pch++;
|
|
}
|
|
else if ( pch == nameBuffer )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// convert byte
|
|
|
|
byte = strtoul( pch, NULL, 10 );
|
|
if ( byte > 255 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
if ( i > 3 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
ip |= byte << (8*i);
|
|
|
|
// terminate at string beginning
|
|
// or continue back up string
|
|
|
|
if ( pch == nameBuffer )
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
pch--;
|
|
}
|
|
|
|
*pIp4Addr = ip;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Success on Dns_Ip4ReverseNameToAddress_A( %s ) => %s\n",
|
|
pszName,
|
|
IP4_STRING(ip) ));
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_Ip4ReverseNameToAddress_W(
|
|
OUT PIP4_ADDRESS pIp4Addr,
|
|
IN PCWSTR pwsName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get IP for reverse lookup name.
|
|
|
|
Arguments:
|
|
|
|
pIp4Addr -- addr to receive IP address if found
|
|
|
|
pszName -- name to lookup
|
|
|
|
Return Value:
|
|
|
|
TRUE -- if reverse lookup name converted to IP
|
|
FALSE -- if not IP4 reverse lookup name
|
|
|
|
--*/
|
|
{
|
|
CHAR nameBuffer[ DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH+1 ];
|
|
DWORD bufLength;
|
|
DWORD nameLengthUtf8;
|
|
|
|
|
|
DNSDBG( TRACE, (
|
|
"Dns_Ip4ReverseNameToAddress_W( %S )\n",
|
|
pwsName ));
|
|
|
|
//
|
|
// convert to UTF8
|
|
// - use UTF8 since conversion to it is trivial and it
|
|
// is identical to ANSI for all reverse lookup names
|
|
//
|
|
|
|
bufLength = DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH + 1;
|
|
|
|
nameLengthUtf8 = Dns_StringCopy(
|
|
nameBuffer,
|
|
& bufLength,
|
|
(PCHAR) pwsName,
|
|
0, // NULL terminated
|
|
DnsCharSetUnicode,
|
|
DnsCharSetUtf8 );
|
|
if ( nameLengthUtf8 == 0 )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// call ANSI routine to do conversion
|
|
//
|
|
|
|
return Dns_Ip4ReverseNameToAddress_A(
|
|
pIp4Addr,
|
|
(PCSTR) nameBuffer );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Reverse name-to-address -- IP6
|
|
//
|
|
|
|
BOOL
|
|
Dns_Ip6ReverseNameToAddress_A(
|
|
OUT PIP6_ADDRESS pIp6Addr,
|
|
IN PCSTR pszName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get IP6 address for reverse lookup name.
|
|
|
|
Arguments:
|
|
|
|
pIp6Addr -- addr to receive IP address if found
|
|
|
|
pszName -- name to lookup
|
|
|
|
Return Value:
|
|
|
|
TRUE -- if reverse lookup name converted to IP
|
|
FALSE -- if not IP4 reverse lookup name
|
|
|
|
--*/
|
|
{
|
|
#define SIZE_IP6REV (sizeof(".ip6.arpa")-1)
|
|
|
|
CHAR nameBuffer[ DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH+1 ];
|
|
DWORD nameLength;
|
|
PCHAR pch;
|
|
BYTE byteArray[16];
|
|
DWORD byteCount;
|
|
DWORD nibble;
|
|
DWORD highNibble;
|
|
BOOL fisLow;
|
|
|
|
DNSDBG( TRACE, ( "Dns_Ip6ReverseNameToAddress_A()\n" ));
|
|
|
|
//
|
|
// validate name
|
|
// fail if
|
|
// - too long
|
|
// - too short
|
|
// - not in in6.int domain
|
|
//
|
|
|
|
nameLength = strlen( pszName );
|
|
|
|
if ( nameLength > DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
if ( pszName[nameLength-1] == '.' )
|
|
{
|
|
nameLength--;
|
|
}
|
|
if ( nameLength <= SIZE_IP6REV )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
nameLength -= SIZE_IP6REV;
|
|
|
|
if ( _strnicmp( ".ip6.arpa", &pszName[nameLength], SIZE_IP6REV ) != 0 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
//
|
|
// copy name
|
|
//
|
|
|
|
RtlCopyMemory(
|
|
nameBuffer,
|
|
pszName,
|
|
nameLength );
|
|
|
|
nameBuffer[nameLength] = 0;
|
|
|
|
//
|
|
// clear IP6 address
|
|
// - need for partial reverse lookup name
|
|
//
|
|
|
|
RtlZeroMemory(
|
|
byteArray,
|
|
sizeof(byteArray) );
|
|
|
|
//
|
|
// read digits
|
|
//
|
|
|
|
byteCount = 0;
|
|
fisLow = FALSE;
|
|
|
|
pch = nameBuffer + nameLength;
|
|
|
|
while ( 1 )
|
|
{
|
|
if ( byteCount > 15 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
--pch;
|
|
|
|
if ( *pch == '.' )
|
|
{
|
|
*pch = 0;
|
|
pch++;
|
|
}
|
|
else if ( pch == nameBuffer )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
// DCR: multi-digit nibbles in reverse name -- error?
|
|
continue;
|
|
}
|
|
|
|
// convert nibble
|
|
// - zero test special as
|
|
// A) faster
|
|
// B) strtoul() uses for error case
|
|
|
|
if ( *pch == '0' )
|
|
{
|
|
nibble = 0;
|
|
}
|
|
else
|
|
{
|
|
nibble = strtoul( pch, NULL, 16 );
|
|
if ( nibble == 0 || nibble > 15 )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
// save high nibble
|
|
// on low nibble, write byte to IP6 address
|
|
|
|
if ( !fisLow )
|
|
{
|
|
highNibble = nibble;
|
|
fisLow = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//byteArray[byteCount++] = (BYTE) (lowNibble | (nibble << 4));
|
|
|
|
pIp6Addr->IP6Byte[byteCount++] = (BYTE) ( (highNibble<<4) | nibble );
|
|
fisLow = FALSE;
|
|
}
|
|
|
|
// terminate at string beginning
|
|
// or continue back up string
|
|
|
|
if ( pch == nameBuffer )
|
|
{
|
|
break;
|
|
}
|
|
pch--;
|
|
}
|
|
|
|
//*pIp6Addr = *(PIP6_ADDRESS) byteArray;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Success on Dns_Ip6ReverseNameToAddress_A( %s )\n",
|
|
pszName ));
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_Ip6ReverseNameToAddress_W(
|
|
OUT PIP6_ADDRESS pIp6Addr,
|
|
IN PCWSTR pwsName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get IP for reverse lookup name.
|
|
|
|
Arguments:
|
|
|
|
pIp6Addr -- addr to receive IP address if found
|
|
|
|
pszName -- name to lookup
|
|
|
|
Return Value:
|
|
|
|
TRUE -- if reverse lookup name converted to IP
|
|
FALSE -- if not IP6 reverse lookup name
|
|
|
|
--*/
|
|
{
|
|
CHAR nameBuffer[ DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH+1 ];
|
|
DWORD bufLength;
|
|
DWORD nameLengthUtf8;
|
|
|
|
|
|
DNSDBG( TRACE, (
|
|
"Dns_Ip6ReverseNameToAddress_W( %S )\n",
|
|
pwsName ));
|
|
|
|
//
|
|
// convert to UTF8
|
|
// - use UTF8 since conversion to it is trivial and it
|
|
// is identical to ANSI for all reverse lookup names
|
|
//
|
|
|
|
bufLength = DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH + 1;
|
|
|
|
nameLengthUtf8 = Dns_StringCopy(
|
|
nameBuffer,
|
|
& bufLength,
|
|
(PCHAR) pwsName,
|
|
0, // NULL terminated
|
|
DnsCharSetUnicode,
|
|
DnsCharSetUtf8 );
|
|
if ( nameLengthUtf8 == 0 )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// call ANSI routine to do conversion
|
|
//
|
|
|
|
return Dns_Ip6ReverseNameToAddress_A(
|
|
pIp6Addr,
|
|
(PCSTR) nameBuffer );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Combined IP4/IP6 reverse-name-to-address
|
|
//
|
|
|
|
BOOL
|
|
Dns_ReverseNameToDnsAddr_W(
|
|
OUT PDNS_ADDR pAddr,
|
|
IN PCWSTR pString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build address (IP4 or IP6) from reverse lookup name.
|
|
|
|
Arguments:
|
|
|
|
pAddr -- DNS_ADDR to receive address
|
|
|
|
pString -- address string
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful.
|
|
FALSE on error. GetLastError() for status.
|
|
|
|
--*/
|
|
{
|
|
return Dns_StringToDnsAddrEx(
|
|
pAddr,
|
|
(PCSTR) pString,
|
|
0, // any family
|
|
TRUE, // unicode
|
|
TRUE // reverse
|
|
);
|
|
}
|
|
|
|
BOOL
|
|
Dns_ReverseNameToDnsAddr_A(
|
|
OUT PDNS_ADDR pAddr,
|
|
IN PCSTR pString
|
|
)
|
|
{
|
|
return Dns_StringToDnsAddrEx(
|
|
pAddr,
|
|
pString,
|
|
0, // any family
|
|
FALSE, // not unicode
|
|
TRUE // reverse
|
|
);
|
|
}
|
|
|
|
//
|
|
// Could discontinue these and use DnsAddr
|
|
// version as NameToAddress_X version
|
|
//
|
|
|
|
BOOL
|
|
Dns_ReverseNameToAddress_W(
|
|
OUT PCHAR pAddrBuf,
|
|
IN OUT PDWORD pBufLength,
|
|
IN PCWSTR pString,
|
|
IN OUT PDWORD pAddrFamily
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build address (IP4 or IP6) from reverse lookup name.
|
|
|
|
Arguments:
|
|
|
|
pAddrBuf -- buffer to receive address
|
|
|
|
pBufLength -- ptr to address length
|
|
input - length of buffer
|
|
output - length of address found
|
|
|
|
pString -- address string
|
|
|
|
pAddrFamily -- ptr to address family
|
|
input - zero for any family or particular family to check
|
|
output - family found; zero if no conversion
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful.
|
|
FALSE on error. GetLastError() for status.
|
|
|
|
--*/
|
|
{
|
|
return Dns_StringToAddressEx(
|
|
pAddrBuf,
|
|
pBufLength,
|
|
(PCSTR) pString,
|
|
pAddrFamily,
|
|
TRUE, // unicode
|
|
TRUE // reverse
|
|
);
|
|
}
|
|
|
|
BOOL
|
|
Dns_ReverseNameToAddress_A(
|
|
OUT PCHAR pAddrBuf,
|
|
IN OUT PDWORD pBufLength,
|
|
IN PCSTR pString,
|
|
IN OUT PDWORD pAddrFamily
|
|
)
|
|
{
|
|
return Dns_StringToAddressEx(
|
|
pAddrBuf,
|
|
pBufLength,
|
|
pString,
|
|
pAddrFamily,
|
|
FALSE, // ANSI
|
|
TRUE // reverse
|
|
);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Combined string-to-address private workhorse
|
|
//
|
|
|
|
BOOL
|
|
Dns_StringToAddressEx(
|
|
OUT PCHAR pAddrBuf,
|
|
IN OUT PDWORD pBufLength,
|
|
IN PCSTR pString,
|
|
IN OUT PDWORD pAddrFamily,
|
|
IN BOOL fUnicode,
|
|
IN BOOL fReverse
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build address (IP4 or IP6 from string)
|
|
|
|
This routine is capable of all string-to-address
|
|
conversions and is the backbone of all the
|
|
combined string-to-address conversion routines.
|
|
|
|
Arguments:
|
|
|
|
pAddrBuf -- buffer to receive address
|
|
|
|
pBufLength -- ptr to address length
|
|
input - length of buffer
|
|
output - length of address found
|
|
|
|
pString -- address string
|
|
|
|
pAddrFamily -- ptr to address family
|
|
input - zero for any family or particular family to check
|
|
output - family found; zero if no conversion
|
|
|
|
fUnicode -- unicode string
|
|
|
|
fReverse -- reverse lookup string
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful.
|
|
FALSE on error.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
DWORD length = 0;
|
|
INT family = *pAddrFamily;
|
|
DWORD bufLength = *pBufLength;
|
|
BOOL fconvert;
|
|
PCSTR preverseString;
|
|
CHAR nameBuffer[ DNS_MAX_REVERSE_NAME_BUFFER_LENGTH+1 ];
|
|
|
|
DNSDBG( TRACE, (
|
|
"Dns_StringToAddressEx( %S%s )\n",
|
|
fUnicode ? pString : "",
|
|
fUnicode ? "" : pString ));
|
|
|
|
//
|
|
// convert reverse to ANSI
|
|
//
|
|
// reverse lookups are done in ANSI; convert here to avoid
|
|
// double string conversion to check both IP4 and IP6
|
|
//
|
|
|
|
if ( fReverse )
|
|
{
|
|
preverseString = pString;
|
|
|
|
if ( fUnicode )
|
|
{
|
|
DWORD reverseLength = DNS_MAX_REVERSE_NAME_BUFFER_LENGTH;
|
|
|
|
if ( ! Dns_StringCopy(
|
|
nameBuffer,
|
|
& reverseLength,
|
|
(PCHAR) pString,
|
|
0, // NULL terminated
|
|
DnsCharSetUnicode,
|
|
DnsCharSetUtf8 ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
preverseString = nameBuffer;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check IP4
|
|
//
|
|
|
|
if ( family == 0 ||
|
|
family == AF_INET )
|
|
{
|
|
IP4_ADDRESS ip;
|
|
|
|
if ( fReverse )
|
|
{
|
|
fconvert = Dns_Ip4ReverseNameToAddress_A(
|
|
& ip,
|
|
preverseString );
|
|
}
|
|
else
|
|
{
|
|
if ( fUnicode )
|
|
{
|
|
fconvert = Dns_Ip4StringToAddress_W(
|
|
& ip,
|
|
(PCWSTR)pString );
|
|
}
|
|
else
|
|
{
|
|
fconvert = Dns_Ip4StringToAddress_A(
|
|
& ip,
|
|
pString );
|
|
}
|
|
}
|
|
if ( fconvert )
|
|
{
|
|
length = sizeof(IP4_ADDRESS);
|
|
family = AF_INET;
|
|
|
|
if ( bufLength < length )
|
|
{
|
|
status = ERROR_MORE_DATA;
|
|
}
|
|
else
|
|
{
|
|
* (PIP4_ADDRESS) pAddrBuf = ip;
|
|
}
|
|
|
|
DNSDBG( INIT2, (
|
|
"Converted string to IP4 address %s\n",
|
|
IP4_STRING(ip) ));
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check IP6
|
|
//
|
|
|
|
if ( family == 0 ||
|
|
family == AF_INET6 )
|
|
{
|
|
IP6_ADDRESS ip;
|
|
|
|
if ( fReverse )
|
|
{
|
|
fconvert = Dns_Ip6ReverseNameToAddress_A(
|
|
& ip,
|
|
preverseString );
|
|
}
|
|
else
|
|
{
|
|
if ( fUnicode )
|
|
{
|
|
fconvert = Dns_Ip6StringToAddress_W(
|
|
& ip,
|
|
(PCWSTR)pString );
|
|
}
|
|
else
|
|
{
|
|
fconvert = Dns_Ip6StringToAddress_A(
|
|
& ip,
|
|
pString );
|
|
}
|
|
}
|
|
if ( fconvert )
|
|
{
|
|
length = sizeof(IP6_ADDRESS);
|
|
|
|
if ( bufLength < length )
|
|
{
|
|
status = ERROR_MORE_DATA;
|
|
}
|
|
else
|
|
{
|
|
family = AF_INET6;
|
|
* (PIP6_ADDRESS) pAddrBuf = ip;
|
|
}
|
|
|
|
IF_DNSDBG( INIT2 )
|
|
{
|
|
DnsDbg_Ip6Address(
|
|
"Converted string to IP6 address: ",
|
|
(PIP6_ADDRESS) pAddrBuf,
|
|
"\n" );
|
|
}
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
length = 0;
|
|
family = 0;
|
|
status = DNS_ERROR_INVALID_IP_ADDRESS;
|
|
|
|
Done:
|
|
|
|
if ( status )
|
|
{
|
|
SetLastError( status );
|
|
}
|
|
|
|
*pAddrFamily = family;
|
|
*pBufLength = length;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave Dns_StringToAddressEx()\n"
|
|
"\tstatus = %d\n"
|
|
"\tptr = %p\n"
|
|
"\tlength = %d\n"
|
|
"\tfamily = %d\n",
|
|
status,
|
|
pAddrBuf,
|
|
length,
|
|
family ));
|
|
|
|
return( status==ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_StringToDnsAddrEx(
|
|
OUT PDNS_ADDR pAddr,
|
|
IN PCSTR pString,
|
|
IN DWORD Family, OPTIONAL
|
|
IN BOOL fUnicode,
|
|
IN BOOL fReverse
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build address (IP4 or IP6 from string)
|
|
|
|
This routine is capable of all string-to-address
|
|
conversions and is the backbone of all the
|
|
combined string-to-address conversion routines.
|
|
|
|
Arguments:
|
|
|
|
pAddr -- ptr to DNS_ADDR to receive address
|
|
|
|
pString -- address string
|
|
|
|
Family -- if only accepting specific family; zero for any
|
|
|
|
fUnicode -- unicode string
|
|
|
|
fReverse -- reverse lookup string
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful.
|
|
FALSE on error.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
DWORD length = 0;
|
|
BOOL fconvert;
|
|
PCSTR preverseString;
|
|
CHAR nameBuffer[ DNS_MAX_REVERSE_NAME_BUFFER_LENGTH+1 ];
|
|
|
|
DNSDBG( TRACE, (
|
|
"Dns_StringToDnsAddrEx( %S%s, rev=%d, unicode=%d )\n",
|
|
fUnicode ? pString : "",
|
|
fUnicode ? "" : pString,
|
|
fReverse,
|
|
fUnicode ));
|
|
|
|
//
|
|
// convert reverse to ANSI
|
|
//
|
|
// reverse lookups are done in ANSI; convert here to avoid
|
|
// double string conversion to check both IP4 and IP6
|
|
//
|
|
|
|
if ( fReverse )
|
|
{
|
|
preverseString = pString;
|
|
|
|
if ( fUnicode )
|
|
{
|
|
DWORD bufLength = DNS_MAX_REVERSE_NAME_BUFFER_LENGTH;
|
|
|
|
if ( ! Dns_StringCopy(
|
|
nameBuffer,
|
|
& bufLength,
|
|
(PCHAR) pString,
|
|
0, // NULL terminated
|
|
DnsCharSetUnicode,
|
|
DnsCharSetUtf8 ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
preverseString = nameBuffer;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check IP4
|
|
//
|
|
|
|
if ( Family == 0 || Family == AF_INET )
|
|
{
|
|
IP4_ADDRESS ip;
|
|
|
|
if ( fReverse )
|
|
{
|
|
fconvert = Dns_Ip4ReverseNameToAddress_A(
|
|
& ip,
|
|
preverseString );
|
|
}
|
|
else
|
|
{
|
|
if ( fUnicode )
|
|
{
|
|
fconvert = Dns_Ip4StringToAddress_W(
|
|
& ip,
|
|
(PCWSTR)pString );
|
|
}
|
|
else
|
|
{
|
|
fconvert = Dns_Ip4StringToAddress_A(
|
|
& ip,
|
|
pString );
|
|
}
|
|
}
|
|
if ( fconvert )
|
|
{
|
|
DnsAddr_BuildFromIp4(
|
|
pAddr,
|
|
ip,
|
|
0 // no port
|
|
);
|
|
DNSDBG( INIT2, (
|
|
"Converted string to IP4 address %s\n",
|
|
IP4_STRING(ip) ));
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check IP6
|
|
//
|
|
|
|
if ( Family == 0 || Family == AF_INET6 )
|
|
{
|
|
if ( fReverse )
|
|
{
|
|
IP6_ADDRESS ip;
|
|
|
|
fconvert = Dns_Ip6ReverseNameToAddress_A(
|
|
& ip,
|
|
preverseString );
|
|
if ( fconvert )
|
|
{
|
|
DnsAddr_BuildFromIp6(
|
|
pAddr,
|
|
&ip,
|
|
0, // no scope
|
|
0 // no port
|
|
);
|
|
IF_DNSDBG( INIT2 )
|
|
{
|
|
DnsDbg_Ip6Address(
|
|
"Converted string to IP6 address: ",
|
|
(PIP6_ADDRESS) &ip,
|
|
"\n" );
|
|
}
|
|
goto Done;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DnsAddr_Clear( pAddr );
|
|
|
|
if ( fUnicode )
|
|
{
|
|
status = RtlIpv6StringToAddressExW(
|
|
(PCWSTR) pString,
|
|
& pAddr->SockaddrIn6.sin6_addr,
|
|
& pAddr->SockaddrIn6.sin6_scope_id,
|
|
& pAddr->SockaddrIn6.sin6_port
|
|
);
|
|
}
|
|
else
|
|
{
|
|
status = RtlIpv6StringToAddressExA(
|
|
(PCSTR) pString,
|
|
& pAddr->SockaddrIn6.sin6_addr,
|
|
& pAddr->SockaddrIn6.sin6_scope_id,
|
|
& pAddr->SockaddrIn6.sin6_port
|
|
);
|
|
}
|
|
if ( status == NO_ERROR )
|
|
{
|
|
pAddr->SockaddrIn6.sin6_family = AF_INET6;
|
|
pAddr->SockaddrLength = sizeof(SOCKADDR_IN6);
|
|
goto Done;
|
|
}
|
|
}
|
|
}
|
|
|
|
DnsAddr_Clear( pAddr );
|
|
status = DNS_ERROR_INVALID_IP_ADDRESS;
|
|
|
|
Done:
|
|
|
|
if ( status )
|
|
{
|
|
SetLastError( status );
|
|
}
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave Dns_StringToDnsAddrEx()\n"
|
|
"\tstatus = %d\n",
|
|
status ));
|
|
|
|
return( status==ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// UPNP IP6 literal hack
|
|
//
|
|
|
|
WCHAR g_Ip6LiteralDomain[] = L".ipv6-literal.net";
|
|
|
|
DWORD g_Ip6LiteralDomainSize = sizeof(g_Ip6LiteralDomain);
|
|
|
|
|
|
VOID
|
|
Dns_Ip6AddressToLiteralName(
|
|
OUT PWCHAR pBuffer,
|
|
IN PIP6_ADDRESS pIp6
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write UPNP-hack-literal.
|
|
|
|
Arguments:
|
|
|
|
pBuffer -- ptr to buffer for reverse lookup name;
|
|
MUST contain DNS_MAX_NAME_LENGTH characters.
|
|
|
|
pIp6 -- IP6 address to create reverse string for
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DWORD length;
|
|
|
|
DNSDBG( TRACE, ( "Dns_Ip6AddressToLiteralName()\n" ));
|
|
|
|
//
|
|
// convert IP6 to address
|
|
//
|
|
|
|
Dns_Ip6AddressToString_W(
|
|
pBuffer,
|
|
pIp6 );
|
|
|
|
length = wcslen( pBuffer );
|
|
|
|
//
|
|
// replace all colons with dashes
|
|
//
|
|
|
|
String_ReplaceCharW(
|
|
pBuffer,
|
|
L':',
|
|
L'-' );
|
|
|
|
//
|
|
// write ip6 literal domain immediately after
|
|
//
|
|
|
|
wcscpy(
|
|
pBuffer + length,
|
|
g_Ip6LiteralDomain );
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave Dns_Ip6AddressToLiteralName() => %S\n",
|
|
pBuffer ));
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Dns_Ip6LiteralNameToAddress(
|
|
OUT PSOCKADDR_IN6 pSockAddr,
|
|
IN PCWSTR pwsString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
IP6 literal to IP6 sockaddr.
|
|
|
|
Arguments:
|
|
|
|
pSock6Addr -- address to fill with IP6 corresponding to literal
|
|
|
|
pwsString -- literal string
|
|
|
|
Return Value:
|
|
|
|
TRUE if IP6 literal found and convert.
|
|
FALSE if not IP6 literal.
|
|
|
|
--*/
|
|
{
|
|
WCHAR nameBuf[ DNS_MAX_NAME_LENGTH ];
|
|
DWORD iter;
|
|
DWORD length;
|
|
DWORD size;
|
|
PWCHAR pch;
|
|
PWCHAR pdomain;
|
|
DNS_STATUS status;
|
|
|
|
|
|
DNSDBG( TRACE, (
|
|
"Dns_Ip6LiteralNameToAddress( %S )\n",
|
|
pwsString ));
|
|
|
|
//
|
|
// test for literal
|
|
// - test undotted
|
|
// - test as FQDN
|
|
// note that even FQDN test is safe, as we insist
|
|
// that string size is GREATER than literal size
|
|
//
|
|
|
|
length = wcslen( pwsString );
|
|
size = (length+1) * sizeof(WCHAR);
|
|
|
|
if ( size <= g_Ip6LiteralDomainSize )
|
|
{
|
|
DNSDBG( INIT2, (
|
|
"Stopped UPNP parse -- short string.\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
pdomain = (PWSTR) ((PBYTE)pwsString + size - g_Ip6LiteralDomainSize);
|
|
|
|
if ( ! RtlEqualMemory(
|
|
pdomain,
|
|
g_Ip6LiteralDomain,
|
|
g_Ip6LiteralDomainSize-sizeof(WCHAR) ) )
|
|
{
|
|
pdomain--;
|
|
|
|
if ( pwsString[length-1] != L'.'
|
|
||
|
|
! RtlEqualMemory(
|
|
pdomain,
|
|
g_Ip6LiteralDomain,
|
|
g_Ip6LiteralDomainSize-sizeof(WCHAR) ) )
|
|
{
|
|
DNSDBG( INIT2, (
|
|
"Stopped UPNP parse -- no tag match.\n" ));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// copy literal to buffer
|
|
//
|
|
|
|
if ( length >= DNS_MAX_NAME_LENGTH )
|
|
{
|
|
DNSDBG( INIT2, (
|
|
"Stopped UPNP parse -- big string.\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
length = (DWORD) ((PWSTR)pdomain - pwsString);
|
|
|
|
RtlCopyMemory(
|
|
nameBuf,
|
|
pwsString,
|
|
length*sizeof(WCHAR) );
|
|
|
|
nameBuf[ length ] = 0;
|
|
|
|
//
|
|
// replace dashes with colons
|
|
// replace 's' with % for scope
|
|
//
|
|
|
|
String_ReplaceCharW(
|
|
nameBuf,
|
|
L'-',
|
|
L':' );
|
|
|
|
String_ReplaceCharW(
|
|
nameBuf,
|
|
L's',
|
|
L'%' );
|
|
|
|
DNSDBG( INIT2, (
|
|
"Reconverted IP6 literal %S\n",
|
|
nameBuf ));
|
|
|
|
//
|
|
// convert to IP6 address
|
|
//
|
|
|
|
status = RtlIpv6StringToAddressExW(
|
|
(PCWSTR) nameBuf,
|
|
& pSockAddr->sin6_addr,
|
|
& pSockAddr->sin6_scope_id,
|
|
& pSockAddr->sin6_port
|
|
);
|
|
|
|
if ( status == NO_ERROR )
|
|
{
|
|
if ( IN6_IS_ADDR_LINKLOCAL( &pSockAddr->sin6_addr )
|
|
||
|
|
IN6_IS_ADDR_SITELOCAL( &pSockAddr->sin6_addr ) )
|
|
{
|
|
pSockAddr->sin6_flowinfo = 0;
|
|
pSockAddr->sin6_family = AF_INET6;
|
|
}
|
|
else
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
return( status == NO_ERROR );
|
|
}
|
|
|
|
//
|
|
// End straddr.c
|
|
//
|