- Add support for reading the hosts file
- Fix an off-by-one error which prevented reading the last value in the services file
- Fixes bug 4410 and bug 4880

svn path=/trunk/; revision=47020
This commit is contained in:
Cameron Gutman 2010-04-25 20:01:59 +00:00
parent 318eee8241
commit 98acf217f9

View file

@ -640,7 +640,199 @@ void free_servent(struct servent* s)
HFREE(s);
}
/* This function is far from perfect but it works enough */
static
LPHOSTENT
FindEntryInHosts(IN CONST CHAR FAR* name)
{
BOOL Found = FALSE;
HANDLE HostsFile;
CHAR HostsDBData[BUFSIZ] = { 0 };
PCHAR SystemDirectory = HostsDBData;
PCHAR HostsLocation = "\\drivers\\etc\\hosts";
PCHAR AddressStr, DnsName = NULL, AddrTerm, NameSt, NextLine, ThisLine, Comment;
UINT SystemDirSize = sizeof(HostsDBData) - 1, ValidData = 0;
DWORD ReadSize;
ULONG Address;
PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
/* We assume that the parameters are valid */
if (!GetSystemDirectoryA(SystemDirectory, SystemDirSize))
{
WSASetLastError(WSANO_RECOVERY);
WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
return NULL; /* Can't get system directory */
}
strncat(SystemDirectory,
HostsLocation,
SystemDirSize );
HostsFile = CreateFileA(SystemDirectory,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (HostsFile == INVALID_HANDLE_VALUE)
{
WSASetLastError(WSANO_RECOVERY);
return NULL;
}
while(!Found &&
ReadFile(HostsFile,
HostsDBData + ValidData,
sizeof(HostsDBData) - ValidData,
&ReadSize,
NULL))
{
ValidData += ReadSize;
ReadSize = 0;
NextLine = ThisLine = HostsDBData;
/* Find the beginning of the next line */
while(NextLine < HostsDBData + ValidData &&
*NextLine != '\r' && *NextLine != '\n' )
{
NextLine++;
}
/* Zero and skip, so we can treat what we have as a string */
if( NextLine > HostsDBData + ValidData )
break;
*NextLine = 0; NextLine++;
Comment = strchr( ThisLine, '#' );
if( Comment ) *Comment = 0; /* Terminate at comment start */
AddressStr = ThisLine;
/* Find the first space separating the IP address from the DNS name */
AddrTerm = strchr(ThisLine, ' ');
if (AddrTerm)
{
/* Terminate the address string */
*AddrTerm = 0;
/* Find the last space before the DNS name */
NameSt = strrchr(ThisLine, ' ');
/* If there is only one space (the one we removed above), then just use the address terminator */
if (!NameSt)
NameSt = AddrTerm;
/* Move from the space to the first character of the DNS name */
NameSt++;
DnsName = NameSt;
if (!strcmp(name, DnsName))
{
Found = TRUE;
break;
}
}
/* Get rid of everything we read so far */
while( NextLine <= HostsDBData + ValidData &&
isspace (*NextLine))
{
NextLine++;
}
if (HostsDBData + ValidData - NextLine <= 0)
break;
WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
HostsDBData + ValidData - NextLine));
memmove(HostsDBData,
NextLine,
HostsDBData + ValidData - NextLine );
ValidData -= NextLine - HostsDBData;
WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
}
CloseHandle(HostsFile);
if (!Found)
{
WS_DbgPrint(MAX_TRACE,("Not found\n"));
WSASetLastError(WSANO_DATA);
return NULL;
}
if( !p->Hostent )
{
p->Hostent = HeapAlloc(GlobalHeap, 0, sizeof(*p->Hostent));
if( !p->Hostent )
{
WSASetLastError( WSATRY_AGAIN );
return NULL;
}
}
p->Hostent->h_name = HeapAlloc(GlobalHeap, 0, strlen(DnsName));
if( !p->Hostent->h_name )
{
WSASetLastError( WSATRY_AGAIN );
return NULL;
}
RtlCopyMemory(p->Hostent->h_name,
DnsName,
strlen(DnsName));
p->Hostent->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *));
if( !p->Hostent->h_aliases )
{
WSASetLastError( WSATRY_AGAIN );
return NULL;
}
p->Hostent->h_aliases[0] = 0;
if (strstr(AddressStr, ":"))
{
DbgPrint("AF_INET6 NOT SUPPORTED!\n");
WSASetLastError(WSAEINVAL);
return NULL;
}
else
p->Hostent->h_addrtype = AF_INET;
p->Hostent->h_addr_list = HeapAlloc(GlobalHeap, 0, sizeof(char *));
if( !p->Hostent->h_addr_list )
{
WSASetLastError( WSATRY_AGAIN );
return NULL;
}
Address = inet_addr(AddressStr);
if (Address == INADDR_NONE)
{
WSASetLastError(WSAEINVAL);
return NULL;
}
p->Hostent->h_addr_list[0] = HeapAlloc(GlobalHeap, 0, sizeof(Address));
if( !p->Hostent->h_addr_list[0] )
{
WSASetLastError( WSATRY_AGAIN );
return NULL;
}
RtlCopyMemory(p->Hostent->h_addr_list[0],
&Address,
sizeof(Address));
p->Hostent->h_length = sizeof(Address);
return p->Hostent;
}
LPHOSTENT
EXPORT
@ -661,6 +853,7 @@ gethostbyname(IN CONST CHAR FAR* name)
/* include/WinDNS.h -- look up DNS_RECORD on MSDN */
PDNS_RECORD dp = 0;
PWINSOCK_THREAD_BLOCK p;
LPHOSTENT Hostent;
addr = GH_INVALID;
@ -726,6 +919,12 @@ gethostbyname(IN CONST CHAR FAR* name)
case GH_RFC1123_DNS:
/* DNS_TYPE_A: include/WinDNS.h */
/* DnsQuery -- lib/dnsapi/dnsapi/query.c */
/* Look for the DNS name in the hosts file */
Hostent = FindEntryInHosts(name);
if (Hostent)
return Hostent;
dns_status = DnsQuery_A(name,
DNS_TYPE_A,
DNS_QUERY_STANDARD,
@ -993,7 +1192,7 @@ getservbyname(IN CONST CHAR FAR* name,
}
/* Zero and skip, so we can treat what we have as a string */
if( NextLine >= ServiceDBData + ValidData )
if( NextLine > ServiceDBData + ValidData )
break;
*NextLine = 0; NextLine++;
@ -1174,7 +1373,7 @@ getservbyport(IN INT port,
*NextLine != '\r' && *NextLine != '\n' ) NextLine++;
/* Zero and skip, so we can treat what we have as a string */
if( NextLine >= ServiceDBData + ValidData )
if( NextLine > ServiceDBData + ValidData )
break;
*NextLine = 0; NextLine++;