577 lines
10 KiB
C
577 lines
10 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991-2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
hostfile.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Reads host file into DNS cache.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Glenn Curtis (glennc) Picked up from winsock.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Jim Gilroy (jamesg) Feb 2000 Cleanup
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#include "local.h"
|
|||
|
|
|||
|
#define HOSTS_FILE_DIRECTORY L"\\drivers\\etc"
|
|||
|
|
|||
|
|
|||
|
#if 0
|
|||
|
//
|
|||
|
// Sockets hosts file stuff
|
|||
|
//
|
|||
|
|
|||
|
#define HOSTDB_SIZE (_MAX_PATH + 8) // 8 == strlen("\\hosts") + 1
|
|||
|
#define MAXALIASES 35
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Globals
|
|||
|
//
|
|||
|
// Note: that none of this is MT safe. We assume that all these
|
|||
|
// functions are called only from a single thread (at startup) or
|
|||
|
// that some higher level locking is enabled.
|
|||
|
//
|
|||
|
|
|||
|
FILE * g_HostFile = NULL;
|
|||
|
CHAR g_HostFileName[ HOSTDB_SIZE ];
|
|||
|
CHAR g_HostLineBuf[ BUFSIZ+1 ];
|
|||
|
|
|||
|
PCHAR g_pHostName;
|
|||
|
PCHAR g_AliasArray[ MAXALIASES ];
|
|||
|
BOOL g_IsIp6;
|
|||
|
IP_ADDRESS g_Ip4Address;
|
|||
|
DNS_IP6_ADDRESS g_Ip6Address;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
_setfile(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Open hosts file.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Globals:
|
|||
|
|
|||
|
g_HostFile -- host file ptr, tested and set
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if ( g_HostFile == NULL )
|
|||
|
{
|
|||
|
g_HostFile = SockOpenNetworkDataBase(
|
|||
|
"hosts",
|
|||
|
g_HostFileName,
|
|||
|
HOSTDB_SIZE,
|
|||
|
"r" );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
rewind( g_HostFile );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
_endfile(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Close hosts file.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Globals:
|
|||
|
|
|||
|
g_HostFile -- host file ptr, tested and cleared
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if ( g_HostFile )
|
|||
|
{
|
|||
|
fclose( g_HostFile );
|
|||
|
g_HostFile = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
_gethost(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Reads an entry from hosts file.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Globals:
|
|||
|
|
|||
|
g_HostFile -- host file ptr, tested and set
|
|||
|
g_pHostName -- name ptr is set
|
|||
|
g_AliasArray -- alias ptr array is filled
|
|||
|
g_Ip4Address -- IP4 address is set
|
|||
|
g_Ip6Address -- IP6 address is set
|
|||
|
g_IsIp6 -- IP4\IP6 flag is set
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successfully reads a host entry.
|
|||
|
FALSE if on EOF or no hosts file found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
char *p;
|
|||
|
register char *cp, **q;
|
|||
|
|
|||
|
//
|
|||
|
// open hosts file if not open
|
|||
|
//
|
|||
|
|
|||
|
if ( g_HostFile == NULL &&
|
|||
|
(g_HostFile = fopen(g_HostFileName, "r" )) == NULL )
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// loop until successfully read IP address
|
|||
|
//
|
|||
|
|
|||
|
while( 1 )
|
|||
|
{
|
|||
|
// quit on EOF
|
|||
|
|
|||
|
if ((p = fgets(g_HostLineBuf, BUFSIZ, g_HostFile)) == NULL)
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// comment line -- skip
|
|||
|
|
|||
|
if ( *p == '#' )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// null address terminate at EOL or comment
|
|||
|
|
|||
|
cp = strpbrk( p, "#\n" );
|
|||
|
if ( cp != NULL )
|
|||
|
{
|
|||
|
*cp = '\0';
|
|||
|
}
|
|||
|
|
|||
|
// all whitespace -- skip
|
|||
|
|
|||
|
cp = strpbrk( p, " \t" );
|
|||
|
if ( cp == NULL )
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// NULL terminate address string
|
|||
|
|
|||
|
*cp++ = '\0';
|
|||
|
|
|||
|
//
|
|||
|
// read address
|
|||
|
// - try IP4
|
|||
|
// - try IP6
|
|||
|
// - otherwise skip
|
|||
|
//
|
|||
|
|
|||
|
g_Ip4Address = inet_addr(p);
|
|||
|
|
|||
|
if ( g_Ip4Address != INADDR_NONE ||
|
|||
|
_strnicmp( "255.255.255.255", p, 15 ) == 0 )
|
|||
|
{
|
|||
|
g_IsIp6 = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// not valid IP4 -- check IP6
|
|||
|
|
|||
|
g_IsIp6 = Dns_Ipv6StringToAddress(
|
|||
|
& g_Ip6Address,
|
|||
|
p,
|
|||
|
0 // null terminated string
|
|||
|
);
|
|||
|
if ( g_IsIp6 )
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// invalid address, ignore line
|
|||
|
|
|||
|
DNSDBG( INIT, (
|
|||
|
"Error parsing host file address %s\n",
|
|||
|
p ));
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// find name
|
|||
|
// - skip leading whitespace
|
|||
|
// - set global name ptr
|
|||
|
|
|||
|
while( *cp == ' ' || *cp == '\t' )
|
|||
|
{
|
|||
|
cp++;
|
|||
|
}
|
|||
|
g_pHostName = cp;
|
|||
|
|
|||
|
// stop at trailing whitespace, NULL terminate
|
|||
|
|
|||
|
cp = strpbrk(cp, " \t");
|
|||
|
if ( cp != NULL )
|
|||
|
{
|
|||
|
*cp++ = '\0';
|
|||
|
}
|
|||
|
|
|||
|
// read aliases
|
|||
|
|
|||
|
q = g_AliasArray;
|
|||
|
while ( cp && *cp )
|
|||
|
{
|
|||
|
// skip leading whitespace
|
|||
|
|
|||
|
if ( *cp == ' ' || *cp == '\t' )
|
|||
|
{
|
|||
|
cp++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// save alias name to alias array
|
|||
|
|
|||
|
if ( q < &g_AliasArray[MAXALIASES - 1] )
|
|||
|
{
|
|||
|
*q++ = cp;
|
|||
|
}
|
|||
|
cp = strpbrk( cp, " \t" );
|
|||
|
if ( cp != NULL )
|
|||
|
{
|
|||
|
*cp++ = '\0';
|
|||
|
}
|
|||
|
}
|
|||
|
*q = NULL;
|
|||
|
|
|||
|
// successful entry read
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
LoadHostFile(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read hosts file into cache.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Globals:
|
|||
|
|
|||
|
g_HostFile -- host file ptr, tested and set then cleared
|
|||
|
g_pHostName -- name ptr is read
|
|||
|
g_AliasArray -- alias ptr array is read
|
|||
|
g_Ip4Address -- IP4 address is read
|
|||
|
g_Ip6Address -- IP6 address is read
|
|||
|
g_IsIp6 -- IP4\IP6 flag is read
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
register PCHAR * cp;
|
|||
|
|
|||
|
DNSDBG( INIT, ( "Enter LoadHostFile\n" ));
|
|||
|
|
|||
|
//
|
|||
|
// read entries from host file until exhausted
|
|||
|
// - cache A record for each name and alias
|
|||
|
// - cache PTR to name
|
|||
|
//
|
|||
|
|
|||
|
_setfile();
|
|||
|
|
|||
|
while ( _gethost() )
|
|||
|
{
|
|||
|
if ( g_pHostName )
|
|||
|
{
|
|||
|
if ( g_IsIp6 )
|
|||
|
{
|
|||
|
CacheAAAARecord( g_pHostName, g_Ip6Address );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CacheARecord( g_pHostName, g_Ip4Address );
|
|||
|
CachePtrRecord( g_Ip4Address, g_pHostName );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for ( cp = g_AliasArray; *cp != 0; cp++ )
|
|||
|
{
|
|||
|
if ( g_IsIp6 )
|
|||
|
{
|
|||
|
CacheAAAARecord( *cp, g_Ip6Address );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CacheARecord( *cp, g_Ip4Address );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
_endfile();
|
|||
|
|
|||
|
DNSDBG( INIT, ( "Leave LoadHostFile\n" ));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HostsFileMonitorThread(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Main thread that waits on and reads host file changes.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Globals:
|
|||
|
|
|||
|
g_hShutdownEvent -- waits on shutdown even
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL bquitting = FALSE;
|
|||
|
HANDLE fileChangeHandle;
|
|||
|
DWORD waitResult;
|
|||
|
HANDLE changeHandles[2];
|
|||
|
DWORD lockFlag = NO_LOCK;
|
|||
|
LPWSTR psystemDirectory = NULL;
|
|||
|
UINT len;
|
|||
|
WCHAR hostDirectory[ MAX_PATH*2 ];
|
|||
|
|
|||
|
DNSDBG( INIT, (
|
|||
|
"Enter HostFileMonitorThread\n" ));
|
|||
|
|
|||
|
//
|
|||
|
// build host file name
|
|||
|
//
|
|||
|
|
|||
|
len = GetSystemDirectory( hostDirectory, MAX_PATH );
|
|||
|
if ( !len || len>MAX_PATH )
|
|||
|
{
|
|||
|
DNSLOG_F1( "Error: Failed to get system directory" );
|
|||
|
DNSLOG_F1( "HostsFileMonitorThread exiting." );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
wcscat( hostDirectory, HOSTS_FILE_DIRECTORY );
|
|||
|
|
|||
|
//
|
|||
|
// drop change notify on host file directory
|
|||
|
//
|
|||
|
|
|||
|
fileChangeHandle = FindFirstChangeNotification(
|
|||
|
hostDirectory,
|
|||
|
FALSE,
|
|||
|
FILE_NOTIFY_CHANGE_FILE_NAME |
|
|||
|
FILE_NOTIFY_CHANGE_LAST_WRITE );
|
|||
|
|
|||
|
if ( fileChangeHandle == INVALID_HANDLE_VALUE )
|
|||
|
{
|
|||
|
DNSLOG_F1( "HostsFileMonitorThread failed to get handle from" );
|
|||
|
DNSLOG_F2( "FindFirstChangeNotification. Error code: <0x%.8X>",
|
|||
|
GetLastError() );
|
|||
|
DNSLOG_F1( "HostsFileMonitorThread exiting." );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// wait on file notify OR shutdown
|
|||
|
// - on host file change rebuild cache and restart wait
|
|||
|
// - on shutdown, exit
|
|||
|
//
|
|||
|
|
|||
|
changeHandles[0] = g_hShutdownEvent;
|
|||
|
changeHandles[1] = fileChangeHandle;
|
|||
|
|
|||
|
while( 1 )
|
|||
|
{
|
|||
|
waitResult = WaitForMultipleObjects(
|
|||
|
2,
|
|||
|
changeHandles,
|
|||
|
FALSE,
|
|||
|
INFINITE );
|
|||
|
|
|||
|
switch( waitResult )
|
|||
|
{
|
|||
|
case WAIT_OBJECT_0 :
|
|||
|
|
|||
|
// shutdown event -- exit
|
|||
|
|
|||
|
DNSLOG_F1( "HostsFileMonitorThread: Got event" );
|
|||
|
DNSLOG_F1( "HostsFileMonitorStopEvent." );
|
|||
|
goto ThreadExit;
|
|||
|
|
|||
|
case WAIT_OBJECT_0 + 1 :
|
|||
|
|
|||
|
// change notify -- flush cache and reload
|
|||
|
|
|||
|
DNSLOG_F1( "HostsFileMonitorThread: Got HOSTS file" );
|
|||
|
DNSLOG_F1( "directory change event." );
|
|||
|
|
|||
|
// reset notification -- BEFORE reload
|
|||
|
|
|||
|
if ( !FindNextChangeNotification( fileChangeHandle ) )
|
|||
|
{
|
|||
|
DNSLOG_F1( "HostsFileMonitorThread failed to get handle" );
|
|||
|
DNSLOG_F1( "from FindNextChangeNotification." );
|
|||
|
DNSLOG_F2( "Error code: <0x%.8X>", GetLastError() );
|
|||
|
goto ThreadExit;
|
|||
|
}
|
|||
|
|
|||
|
FlushCache( TRUE ); // flush and reload
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
DNSLOG_F1( "HostsFileMonitorThread failed to get handle" );
|
|||
|
goto ThreadExit;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ThreadExit:
|
|||
|
|
|||
|
// close change\notify handle
|
|||
|
|
|||
|
CloseHandle( fileChangeHandle );
|
|||
|
|
|||
|
DNSDBG( INIT, (
|
|||
|
"HostFileMonitorThread exit\n" ));
|
|||
|
DNSLOG_F1( "HostsFileMonitorThread exiting." );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
LoadHostFileIntoCache(
|
|||
|
IN PSTR pFileName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read hosts file into cache.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pFileName -- file name to load
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HOST_FILE_INFO hostInfo;
|
|||
|
|
|||
|
DNSDBG( INIT, ( "Enter LoadHostFile\n" ));
|
|||
|
|
|||
|
//
|
|||
|
// read entries from host file until exhausted
|
|||
|
// - cache A record for each name and alias
|
|||
|
// - cache PTR to name
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory(
|
|||
|
&hostInfo,
|
|||
|
sizeof(hostInfo) );
|
|||
|
|
|||
|
if ( !Dns_OpenHostFile( &hostInfo ) )
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
hostInfo.fBuildRecords = TRUE;
|
|||
|
|
|||
|
while ( Dns_ReadHostFileLine( &hostInfo ) )
|
|||
|
{
|
|||
|
// cache all the records we sucked out
|
|||
|
//
|
|||
|
// DCR: cache answer data with CNAME data
|
|||
|
|
|||
|
CacheAnyAdditionalRecords( hostInfo.pForwardRR, TRUE );
|
|||
|
CacheAnyAdditionalRecords( hostInfo.pReverseRR, TRUE );
|
|||
|
CacheAnyAdditionalRecords( hostInfo.pAliasRR, TRUE );
|
|||
|
}
|
|||
|
|
|||
|
Dns_CloseHostFile( &hostInfo );
|
|||
|
|
|||
|
DNSDBG( INIT, ( "Leave LoadHostFile\n" ));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// End hostfile.c
|
|||
|
//
|