mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 12:54:51 +00:00
463 lines
13 KiB
C
463 lines
13 KiB
C
![]() |
/*
|
||
|
* COPYRIGHT: See COPYING in the top level directory
|
||
|
* PROJECT: ReactOS DNS Shared Library
|
||
|
* FILE: lib/dnslib/straddr.c
|
||
|
* PURPOSE: Functions for address<->string conversion.
|
||
|
*/
|
||
|
|
||
|
/* INCLUDES ******************************************************************/
|
||
|
#include "precomp.h"
|
||
|
|
||
|
/* DATA **********************************************************************/
|
||
|
|
||
|
/* FUNCTIONS *****************************************************************/
|
||
|
|
||
|
LPWSTR
|
||
|
WINAPI
|
||
|
Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name,
|
||
|
IN IN6_ADDR Address)
|
||
|
{
|
||
|
/* FIXME */
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
LPWSTR
|
||
|
WINAPI
|
||
|
Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name,
|
||
|
IN IN_ADDR Address)
|
||
|
{
|
||
|
/* Simply append the ARPA string */
|
||
|
return Name + (wsprintfW(Name,
|
||
|
L"%u.%u.%u.%u.in-addr.arpa.",
|
||
|
Address.S_un.S_addr >> 24,
|
||
|
Address.S_un.S_addr >> 10,
|
||
|
Address.S_un.S_addr >> 8,
|
||
|
Address.S_un.S_addr) * sizeof(WCHAR));
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address,
|
||
|
IN LPSTR Name)
|
||
|
{
|
||
|
/* FIXME */
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address,
|
||
|
IN LPSTR Name)
|
||
|
{
|
||
|
/* FIXME */
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address,
|
||
|
IN LPSTR Name)
|
||
|
{
|
||
|
PCHAR Terminator;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
/* Let RTL Do it for us */
|
||
|
Status = RtlIpv6StringToAddressA(Name, &Terminator, Address);
|
||
|
if (NT_SUCCESS(Status)) return TRUE;
|
||
|
|
||
|
/* We failed */
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address,
|
||
|
IN LPWSTR Name)
|
||
|
{
|
||
|
PCHAR Terminator;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
/* Let RTL Do it for us */
|
||
|
Status = RtlIpv6StringToAddressW(Name, &Terminator, Address);
|
||
|
if (NT_SUCCESS(Status)) return TRUE;
|
||
|
|
||
|
/* We failed */
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address,
|
||
|
IN LPSTR Name)
|
||
|
{
|
||
|
ULONG Addr;
|
||
|
|
||
|
/* Use inet_addr to convert it... */
|
||
|
Addr = inet_addr(Name);
|
||
|
if (Addr == -1)
|
||
|
{
|
||
|
/* Check if it's the wildcard (which is ok...) */
|
||
|
if (strcmp("255.255.255.255", Name)) return FALSE;
|
||
|
}
|
||
|
|
||
|
/* If we got here, then we suceeded... return the address */
|
||
|
Address->S_un.S_addr = Addr;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address,
|
||
|
IN LPWSTR Name)
|
||
|
{
|
||
|
CHAR AnsiName[16];
|
||
|
ULONG Size = sizeof(AnsiName);
|
||
|
INT ErrorCode;
|
||
|
|
||
|
/* Make a copy of the name in ANSI */
|
||
|
ErrorCode = Dns_StringCopy(&AnsiName,
|
||
|
&Size,
|
||
|
Name,
|
||
|
0,
|
||
|
UnicodeString,
|
||
|
AnsiString);
|
||
|
if (ErrorCode)
|
||
|
{
|
||
|
/* Copy made sucesfully, now convert it */
|
||
|
ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName);
|
||
|
}
|
||
|
|
||
|
/* Return either 0 bytes copied (failure == false) or conversion status */
|
||
|
return ErrorCode;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address,
|
||
|
IN LPWSTR Name)
|
||
|
{
|
||
|
CHAR AnsiName[32];
|
||
|
ULONG Size = sizeof(AnsiName);
|
||
|
INT ErrorCode;
|
||
|
|
||
|
/* Make a copy of the name in ANSI */
|
||
|
ErrorCode = Dns_StringCopy(&AnsiName,
|
||
|
&Size,
|
||
|
Name,
|
||
|
0,
|
||
|
UnicodeString,
|
||
|
AnsiString);
|
||
|
if (ErrorCode)
|
||
|
{
|
||
|
/* Copy made sucesfully, now convert it */
|
||
|
ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName);
|
||
|
}
|
||
|
|
||
|
/* Return either 0 bytes copied (failure == false) or conversion status */
|
||
|
return ErrorCode;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_StringToAddressEx(OUT PVOID Address,
|
||
|
IN OUT PULONG AddressSize,
|
||
|
IN PVOID AddressName,
|
||
|
IN OUT PDWORD AddressFamily,
|
||
|
IN BOOLEAN Unicode,
|
||
|
IN BOOLEAN Reverse)
|
||
|
{
|
||
|
DWORD Af = *AddressFamily;
|
||
|
ULONG AddrSize = *AddressSize;
|
||
|
IN6_ADDR Addr;
|
||
|
BOOLEAN Return;
|
||
|
INT ErrorCode;
|
||
|
CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
|
||
|
ULONG Size = sizeof(AnsiName);
|
||
|
|
||
|
/* First check if this is a reverse address string */
|
||
|
if (Reverse)
|
||
|
{
|
||
|
/* Convert it right now to ANSI as an optimization */
|
||
|
Dns_StringCopy(AnsiName,
|
||
|
&Size,
|
||
|
AddressName,
|
||
|
0,
|
||
|
UnicodeString,
|
||
|
AnsiString);
|
||
|
|
||
|
/* Use the ANSI Name instead */
|
||
|
AddressName = AnsiName;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* If the caller doesn't know what the family is, we'll assume IPv4 and
|
||
|
* check if we failed or not. If the caller told us it's IPv4, then just
|
||
|
* do IPv4...
|
||
|
*/
|
||
|
if ((Af == AF_UNSPEC) || (Af == AF_INET))
|
||
|
{
|
||
|
/* Now check if the caller gave us the reverse name or not */
|
||
|
if (Reverse)
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Check if the caller gave us unicode or not */
|
||
|
if (Unicode)
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Check if we suceeded */
|
||
|
if (Return)
|
||
|
{
|
||
|
/* Save address family */
|
||
|
Af = AF_INET;
|
||
|
|
||
|
/* Check if the address size matches */
|
||
|
if (AddrSize < sizeof(IN_ADDR))
|
||
|
{
|
||
|
/* Invalid match, set error code */
|
||
|
ErrorCode = ERROR_MORE_DATA;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* It matches, save the address! */
|
||
|
*(PIN_ADDR)Address = *(PIN_ADDR)&Addr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* If we are here, either AF_INET6 was specified or IPv4 failed */
|
||
|
if ((Af == AF_UNSPEC) || (Af == AF_INET6))
|
||
|
{
|
||
|
/* Now check if the caller gave us the reverse name or not */
|
||
|
if (Reverse)
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Check if the caller gave us unicode or not */
|
||
|
if (Unicode)
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip6StringToAddress_W(&Addr, AddressName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip6StringToAddress_A(&Addr, AddressName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Check if we suceeded */
|
||
|
if (Return)
|
||
|
{
|
||
|
/* Save address family */
|
||
|
Af = AF_INET6;
|
||
|
|
||
|
/* Check if the address size matches */
|
||
|
if (AddrSize < sizeof(IN6_ADDR))
|
||
|
{
|
||
|
/* Invalid match, set error code */
|
||
|
ErrorCode = ERROR_MORE_DATA;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* It matches, save the address! */
|
||
|
*(PIN6_ADDR)Address = Addr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (Af != AF_INET)
|
||
|
{
|
||
|
/* You're like.. ATM or something? Get outta here! */
|
||
|
Af = AF_UNSPEC;
|
||
|
ErrorCode = WSA_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
/* Set error if we had one */
|
||
|
if (ErrorCode) SetLastError(ErrorCode);
|
||
|
|
||
|
/* Return the address family and size */
|
||
|
*AddressFamily = Af;
|
||
|
*AddressSize = AddrSize;
|
||
|
|
||
|
/* Return success or failure */
|
||
|
return (ErrorCode == ERROR_SUCCESS);
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_StringToAddressW(OUT PVOID Address,
|
||
|
IN OUT PULONG AddressSize,
|
||
|
IN LPWSTR AddressName,
|
||
|
IN OUT PDWORD AddressFamily)
|
||
|
{
|
||
|
/* Call the common API */
|
||
|
return Dns_StringToAddressEx(Address,
|
||
|
AddressSize,
|
||
|
AddressName,
|
||
|
AddressFamily,
|
||
|
TRUE,
|
||
|
FALSE);
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr,
|
||
|
IN PVOID AddressName,
|
||
|
IN DWORD AddressFamily,
|
||
|
IN BOOLEAN Unicode,
|
||
|
IN BOOLEAN Reverse)
|
||
|
{
|
||
|
IN6_ADDR Addr;
|
||
|
BOOLEAN Return;
|
||
|
INT ErrorCode = ERROR_SUCCESS;
|
||
|
CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
|
||
|
ULONG Size = sizeof(AnsiName);
|
||
|
|
||
|
/* First check if this is a reverse address string */
|
||
|
if ((Reverse) && (Unicode))
|
||
|
{
|
||
|
/* Convert it right now to ANSI as an optimization */
|
||
|
Dns_StringCopy(AnsiName,
|
||
|
&Size,
|
||
|
AddressName,
|
||
|
0,
|
||
|
UnicodeString,
|
||
|
AnsiString);
|
||
|
|
||
|
/* Use the ANSI Name instead */
|
||
|
AddressName = AnsiName;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* If the caller doesn't know what the family is, we'll assume IPv4 and
|
||
|
* check if we failed or not. If the caller told us it's IPv4, then just
|
||
|
* do IPv4...
|
||
|
*/
|
||
|
if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET))
|
||
|
{
|
||
|
/* Now check if the caller gave us the reverse name or not */
|
||
|
if (Reverse)
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Check if the caller gave us unicode or not */
|
||
|
if (Unicode)
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Check if we suceeded */
|
||
|
if (Return)
|
||
|
{
|
||
|
/* Build the IPv4 Address */
|
||
|
DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0);
|
||
|
|
||
|
/* So we don't go in the code below... */
|
||
|
AddressFamily = AF_INET;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* If we are here, either AF_INET6 was specified or IPv4 failed */
|
||
|
if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6))
|
||
|
{
|
||
|
/* Now check if the caller gave us the reverse name or not */
|
||
|
if (Reverse)
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
|
||
|
if (Return)
|
||
|
{
|
||
|
/* Build the IPv6 Address */
|
||
|
DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
goto Quickie;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Check if the caller gave us unicode or not */
|
||
|
if (Unicode)
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName,
|
||
|
&DnsAddr->Ip6Address.sin6_addr,
|
||
|
&DnsAddr->Ip6Address.sin6_scope_id,
|
||
|
&DnsAddr->Ip6Address.sin6_port)))
|
||
|
Return = TRUE;
|
||
|
else
|
||
|
Return = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Get the Address */
|
||
|
if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName,
|
||
|
&DnsAddr->Ip6Address.sin6_addr,
|
||
|
&DnsAddr->Ip6Address.sin6_scope_id,
|
||
|
&DnsAddr->Ip6Address.sin6_port)))
|
||
|
Return = TRUE;
|
||
|
else
|
||
|
Return = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Check if we suceeded */
|
||
|
if (Return)
|
||
|
{
|
||
|
/* Finish setting up the structure */
|
||
|
DnsAddr->Ip6Address.sin6_family = AF_INET6;
|
||
|
DnsAddr->AddressLength = sizeof(SOCKADDR_IN6);
|
||
|
}
|
||
|
}
|
||
|
else if (AddressFamily != AF_INET)
|
||
|
{
|
||
|
/* You're like.. ATM or something? Get outta here! */
|
||
|
RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS));
|
||
|
SetLastError(WSA_INVALID_PARAMETER);
|
||
|
}
|
||
|
|
||
|
Quickie:
|
||
|
/* Return success or failure */
|
||
|
return (ErrorCode == ERROR_SUCCESS);
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
WINAPI
|
||
|
Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr,
|
||
|
IN LPWSTR Name)
|
||
|
{
|
||
|
/* Call the common API */
|
||
|
return Dns_StringToDnsAddrEx(DnsAddr,
|
||
|
Name,
|
||
|
AF_UNSPEC,
|
||
|
TRUE,
|
||
|
TRUE);
|
||
|
}
|
||
|
|