From c35ebdfeb613242eaa905230033712d43d8b0070 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 1 Dec 2019 17:17:50 +0100 Subject: [PATCH] [DNSRSLVR] Add support for IP6 hosts file entries --- base/services/dnsrslvr/hostsfile.c | 201 +++++++++++++++-------------- 1 file changed, 106 insertions(+), 95 deletions(-) diff --git a/base/services/dnsrslvr/hostsfile.c b/base/services/dnsrslvr/hostsfile.c index 1f12b87455f..98d39374d4e 100644 --- a/base/services/dnsrslvr/hostsfile.c +++ b/base/services/dnsrslvr/hostsfile.c @@ -8,11 +8,14 @@ */ #include "precomp.h" +#include +#include #define NDEBUG #include +static WCHAR szHexChar[] = L"0123456789abcdef"; static PWSTR @@ -50,104 +53,51 @@ AnsiToUnicode( static BOOL -ParseV4Address( - LPCSTR AddressString, - OUT PDWORD pAddress) +ParseIpv4Address( + _In_ PCSTR AddressString, + _Out_ PIN_ADDR pAddress) { - CHAR *cp; - DWORD val, base; - unsigned char c; - DWORD parts[4], *pp = parts; + PCSTR pTerminator = NULL; + NTSTATUS Status; - cp = (CHAR *)AddressString; + Status = RtlIpv4StringToAddressA(AddressString, + TRUE, + &pTerminator, + pAddress); + if (NT_SUCCESS(Status) && pTerminator != NULL && *pTerminator == '\0') + return TRUE; - if (!AddressString) - return FALSE; - - if (!isdigit(*cp)) - return FALSE; - -again: - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, other=decimal. - */ - val = 0; base = 10; - if (*cp == '0') - { - if (*++cp == 'x' || *cp == 'X') - base = 16, cp++; - else - base = 8; - } - - while ((c = *cp)) - { - if (isdigit(c)) - { - val = (val * base) + (c - '0'); - cp++; - continue; - } - - if (base == 16 && isxdigit(c)) - { - val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); - cp++; - continue; - } - break; - } - - if (*cp == '.') - { - /* - * Internet format: - * a.b.c.d - */ - if (pp >= parts + 4) - return FALSE; - *pp++ = val; - cp++; - goto again; - } - - /* Check for trailing characters */ - if (*cp && *cp > ' ') - return FALSE; - - if (pp >= parts + 4) - return FALSE; - - *pp++ = val; - /* - * Concoct the address according to - * the number of parts specified. - */ - if ((DWORD)(pp - parts) != 4) - return FALSE; + return FALSE; +} - if (parts[0] > 0xff || parts[1] > 0xff || parts[2] > 0xff || parts[3] > 0xff) - return FALSE; - val = (parts[3] << 24) | (parts[2] << 16) | (parts[1] << 8) | parts[0]; +static +BOOL +ParseIpv6Address( + _In_ LPCSTR AddressString, + _Out_ PIN6_ADDR pAddress) +{ + PCSTR pTerminator = NULL; + NTSTATUS Status; - if (pAddress) - *pAddress = val; + Status = RtlIpv6StringToAddressA(AddressString, + &pTerminator, + pAddress); + if (NT_SUCCESS(Status) && pTerminator != NULL && *pTerminator == '\0') + return TRUE; - return TRUE; + return FALSE; } static VOID -AddV4HostEntries( +AddIpv4HostEntries( PWSTR pszHostName, - DWORD dwIpAddress) + PIN_ADDR pAddress) { DNS_RECORDW ARecord, PtrRecord; - WCHAR szInAddrArpaName[32]; + WCHAR szReverseName[32]; /* Prepare the A record */ ZeroMemory(&ARecord, sizeof(DNS_RECORDW)); @@ -157,19 +107,19 @@ AddV4HostEntries( ARecord.wDataLength = sizeof(DNS_A_DATA); ARecord.dwTtl = 86400; - ARecord.Data.A.IpAddress = dwIpAddress; + ARecord.Data.A.IpAddress = pAddress->S_un.S_addr; - swprintf(szInAddrArpaName, + /* Prepare the PTR record */ + swprintf(szReverseName, L"%u.%u.%u.%u.in-addr.arpa", - (dwIpAddress >> 24) & 0xFF, - (dwIpAddress >> 16) & 0xFF, - (dwIpAddress >> 8) & 0xFF, - dwIpAddress & 0xFF); + pAddress->S_un.S_un_b.s_b4, + pAddress->S_un.S_un_b.s_b3, + pAddress->S_un.S_un_b.s_b2, + pAddress->S_un.S_un_b.s_b1); - /* Prepare the PTR record */ ZeroMemory(&PtrRecord, sizeof(DNS_RECORDW)); - PtrRecord.pName = szInAddrArpaName; + PtrRecord.pName = szReverseName; PtrRecord.wType = DNS_TYPE_PTR; PtrRecord.wDataLength = sizeof(DNS_PTR_DATA); PtrRecord.dwTtl = 86400; @@ -181,6 +131,56 @@ AddV4HostEntries( } +static +VOID +AddIpv6HostEntries( + PWSTR pszHostName, + PIN6_ADDR pAddress) +{ + DNS_RECORDW AAAARecord, PtrRecord; + WCHAR szReverseName[80]; + DWORD i, j, k; + + /* Prepare the AAAA record */ + ZeroMemory(&AAAARecord, sizeof(DNS_RECORDW)); + + AAAARecord.pName = pszHostName; + AAAARecord.wType = DNS_TYPE_AAAA; + AAAARecord.wDataLength = sizeof(DNS_AAAA_DATA); + AAAARecord.dwTtl = 86400; + + CopyMemory(&AAAARecord.Data.AAAA.Ip6Address, + &pAddress->u.Byte, + sizeof(IN6_ADDR)); + + /* Prepare the PTR record */ + ZeroMemory(szReverseName, sizeof(szReverseName)); + + for (i = 0; i < sizeof(IN6_ADDR); i++) + { + j = 4 * i; + k = sizeof(IN6_ADDR) - 1 - i; + szReverseName[j] = szHexChar[pAddress->u.Byte[k] & 0xF]; + szReverseName[j + 1] = L'.'; + szReverseName[j + 2] = szHexChar[(pAddress->u.Byte[k] >> 4) & 0xF]; + szReverseName[j + 3] = L'.'; + } + wcscat(szReverseName, L"ip6.arpa"); + + ZeroMemory(&PtrRecord, sizeof(DNS_RECORDW)); + + PtrRecord.pName = szReverseName; + PtrRecord.wType = DNS_TYPE_PTR; + PtrRecord.wDataLength = sizeof(DNS_PTR_DATA); + PtrRecord.dwTtl = 86400; + + PtrRecord.Data.PTR.pNameHost = pszHostName; + + DnsIntCacheAddEntry(&AAAARecord); + DnsIntCacheAddEntry(&PtrRecord); +} + + static FILE * OpenHostsFile(VOID) @@ -285,7 +285,8 @@ ReadHostsFile(VOID) CHAR szLineBuffer[512]; FILE *pHostFile = NULL; CHAR *Ptr, *NameStart, *NameEnd, *AddressStart, *AddressEnd; - DWORD Address; + struct in_addr Ipv4Address; + struct in6_addr Ipv6Address; PWSTR pszHostName; pHostFile = OpenHostsFile(); @@ -374,15 +375,25 @@ ReadHostsFile(VOID) DPRINT("%s ==> %s\n", NameStart, AddressStart); - if (ParseV4Address(AddressStart, &Address)) + if (ParseIpv4Address(AddressStart, &Ipv4Address)) { - DPRINT("IP4: %s ==> 0x%08lx\n", AddressStart, Address); + DPRINT("IPv4: %s\n", AddressStart); pszHostName = AnsiToUnicode(NameStart); if (pszHostName != NULL) { - AddV4HostEntries(pszHostName, Address); + AddIpv4HostEntries(pszHostName, &Ipv4Address); + HeapFree(GetProcessHeap(), 0, pszHostName); + } + } + else if (ParseIpv6Address(AddressStart, &Ipv6Address)) + { + DPRINT("IPv6: %s\n", AddressStart); + pszHostName = AnsiToUnicode(NameStart); + if (pszHostName != NULL) + { + AddIpv6HostEntries(pszHostName, &Ipv6Address); HeapFree(GetProcessHeap(), 0, pszHostName); } } -- 2.17.1