/* * 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 = ERROR_SUCCESS; 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); }