Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

576 lines
10 KiB

  1. /*++
  2. Copyright (c) 1991-2000 Microsoft Corporation
  3. Module Name:
  4. hostfile.c
  5. Abstract:
  6. Reads host file into DNS cache.
  7. Author:
  8. Glenn Curtis (glennc) Picked up from winsock.
  9. Revision History:
  10. Jim Gilroy (jamesg) Feb 2000 Cleanup
  11. --*/
  12. #include "local.h"
  13. #define HOSTS_FILE_DIRECTORY L"\\drivers\\etc"
  14. #if 0
  15. //
  16. // Sockets hosts file stuff
  17. //
  18. #define HOSTDB_SIZE (_MAX_PATH + 8) // 8 == strlen("\\hosts") + 1
  19. #define MAXALIASES 35
  20. //
  21. // Globals
  22. //
  23. // Note: that none of this is MT safe. We assume that all these
  24. // functions are called only from a single thread (at startup) or
  25. // that some higher level locking is enabled.
  26. //
  27. FILE * g_HostFile = NULL;
  28. CHAR g_HostFileName[ HOSTDB_SIZE ];
  29. CHAR g_HostLineBuf[ BUFSIZ+1 ];
  30. PCHAR g_pHostName;
  31. PCHAR g_AliasArray[ MAXALIASES ];
  32. BOOL g_IsIp6;
  33. IP_ADDRESS g_Ip4Address;
  34. DNS_IP6_ADDRESS g_Ip6Address;
  35. VOID
  36. _setfile(
  37. VOID
  38. )
  39. /*++
  40. Routine Description:
  41. Open hosts file.
  42. Arguments:
  43. None.
  44. Globals:
  45. g_HostFile -- host file ptr, tested and set
  46. Return Value:
  47. None.
  48. --*/
  49. {
  50. if ( g_HostFile == NULL )
  51. {
  52. g_HostFile = SockOpenNetworkDataBase(
  53. "hosts",
  54. g_HostFileName,
  55. HOSTDB_SIZE,
  56. "r" );
  57. }
  58. else
  59. {
  60. rewind( g_HostFile );
  61. }
  62. }
  63. VOID
  64. _endfile(
  65. VOID
  66. )
  67. /*++
  68. Routine Description:
  69. Close hosts file.
  70. Arguments:
  71. None.
  72. Globals:
  73. g_HostFile -- host file ptr, tested and cleared
  74. Return Value:
  75. None.
  76. --*/
  77. {
  78. if ( g_HostFile )
  79. {
  80. fclose( g_HostFile );
  81. g_HostFile = NULL;
  82. }
  83. }
  84. BOOL
  85. _gethost(
  86. VOID
  87. )
  88. /*++
  89. Routine Description:
  90. Reads an entry from hosts file.
  91. Arguments:
  92. None.
  93. Globals:
  94. g_HostFile -- host file ptr, tested and set
  95. g_pHostName -- name ptr is set
  96. g_AliasArray -- alias ptr array is filled
  97. g_Ip4Address -- IP4 address is set
  98. g_Ip6Address -- IP6 address is set
  99. g_IsIp6 -- IP4\IP6 flag is set
  100. Return Value:
  101. TRUE if successfully reads a host entry.
  102. FALSE if on EOF or no hosts file found.
  103. --*/
  104. {
  105. char *p;
  106. register char *cp, **q;
  107. //
  108. // open hosts file if not open
  109. //
  110. if ( g_HostFile == NULL &&
  111. (g_HostFile = fopen(g_HostFileName, "r" )) == NULL )
  112. {
  113. return FALSE;
  114. }
  115. //
  116. // loop until successfully read IP address
  117. //
  118. while( 1 )
  119. {
  120. // quit on EOF
  121. if ((p = fgets(g_HostLineBuf, BUFSIZ, g_HostFile)) == NULL)
  122. {
  123. return FALSE;
  124. }
  125. // comment line -- skip
  126. if ( *p == '#' )
  127. {
  128. continue;
  129. }
  130. // null address terminate at EOL or comment
  131. cp = strpbrk( p, "#\n" );
  132. if ( cp != NULL )
  133. {
  134. *cp = '\0';
  135. }
  136. // all whitespace -- skip
  137. cp = strpbrk( p, " \t" );
  138. if ( cp == NULL )
  139. {
  140. continue;
  141. }
  142. // NULL terminate address string
  143. *cp++ = '\0';
  144. //
  145. // read address
  146. // - try IP4
  147. // - try IP6
  148. // - otherwise skip
  149. //
  150. g_Ip4Address = inet_addr(p);
  151. if ( g_Ip4Address != INADDR_NONE ||
  152. _strnicmp( "255.255.255.255", p, 15 ) == 0 )
  153. {
  154. g_IsIp6 = FALSE;
  155. break;
  156. }
  157. // not valid IP4 -- check IP6
  158. g_IsIp6 = Dns_Ipv6StringToAddress(
  159. & g_Ip6Address,
  160. p,
  161. 0 // null terminated string
  162. );
  163. if ( g_IsIp6 )
  164. {
  165. break;
  166. }
  167. // invalid address, ignore line
  168. DNSDBG( INIT, (
  169. "Error parsing host file address %s\n",
  170. p ));
  171. continue;
  172. }
  173. //
  174. // find name
  175. // - skip leading whitespace
  176. // - set global name ptr
  177. while( *cp == ' ' || *cp == '\t' )
  178. {
  179. cp++;
  180. }
  181. g_pHostName = cp;
  182. // stop at trailing whitespace, NULL terminate
  183. cp = strpbrk(cp, " \t");
  184. if ( cp != NULL )
  185. {
  186. *cp++ = '\0';
  187. }
  188. // read aliases
  189. q = g_AliasArray;
  190. while ( cp && *cp )
  191. {
  192. // skip leading whitespace
  193. if ( *cp == ' ' || *cp == '\t' )
  194. {
  195. cp++;
  196. continue;
  197. }
  198. // save alias name to alias array
  199. if ( q < &g_AliasArray[MAXALIASES - 1] )
  200. {
  201. *q++ = cp;
  202. }
  203. cp = strpbrk( cp, " \t" );
  204. if ( cp != NULL )
  205. {
  206. *cp++ = '\0';
  207. }
  208. }
  209. *q = NULL;
  210. // successful entry read
  211. return TRUE;
  212. }
  213. VOID
  214. LoadHostFile(
  215. VOID
  216. )
  217. /*++
  218. Routine Description:
  219. Read hosts file into cache.
  220. Arguments:
  221. None.
  222. Globals:
  223. g_HostFile -- host file ptr, tested and set then cleared
  224. g_pHostName -- name ptr is read
  225. g_AliasArray -- alias ptr array is read
  226. g_Ip4Address -- IP4 address is read
  227. g_Ip6Address -- IP6 address is read
  228. g_IsIp6 -- IP4\IP6 flag is read
  229. Return Value:
  230. None.
  231. --*/
  232. {
  233. register PCHAR * cp;
  234. DNSDBG( INIT, ( "Enter LoadHostFile\n" ));
  235. //
  236. // read entries from host file until exhausted
  237. // - cache A record for each name and alias
  238. // - cache PTR to name
  239. //
  240. _setfile();
  241. while ( _gethost() )
  242. {
  243. if ( g_pHostName )
  244. {
  245. if ( g_IsIp6 )
  246. {
  247. CacheAAAARecord( g_pHostName, g_Ip6Address );
  248. }
  249. else
  250. {
  251. CacheARecord( g_pHostName, g_Ip4Address );
  252. CachePtrRecord( g_Ip4Address, g_pHostName );
  253. }
  254. }
  255. for ( cp = g_AliasArray; *cp != 0; cp++ )
  256. {
  257. if ( g_IsIp6 )
  258. {
  259. CacheAAAARecord( *cp, g_Ip6Address );
  260. }
  261. else
  262. {
  263. CacheARecord( *cp, g_Ip4Address );
  264. }
  265. }
  266. }
  267. _endfile();
  268. DNSDBG( INIT, ( "Leave LoadHostFile\n" ));
  269. }
  270. #endif
  271. VOID
  272. HostsFileMonitorThread(
  273. VOID
  274. )
  275. /*++
  276. Routine Description:
  277. Main thread that waits on and reads host file changes.
  278. Arguments:
  279. None.
  280. Globals:
  281. g_hShutdownEvent -- waits on shutdown even
  282. Return Value:
  283. None.
  284. --*/
  285. {
  286. BOOL bquitting = FALSE;
  287. HANDLE fileChangeHandle;
  288. DWORD waitResult;
  289. HANDLE changeHandles[2];
  290. DWORD lockFlag = NO_LOCK;
  291. LPWSTR psystemDirectory = NULL;
  292. UINT len;
  293. WCHAR hostDirectory[ MAX_PATH*2 ];
  294. DNSDBG( INIT, (
  295. "Enter HostFileMonitorThread\n" ));
  296. //
  297. // build host file name
  298. //
  299. len = GetSystemDirectory( hostDirectory, MAX_PATH );
  300. if ( !len || len>MAX_PATH )
  301. {
  302. DNSLOG_F1( "Error: Failed to get system directory" );
  303. DNSLOG_F1( "HostsFileMonitorThread exiting." );
  304. return;
  305. }
  306. wcscat( hostDirectory, HOSTS_FILE_DIRECTORY );
  307. //
  308. // drop change notify on host file directory
  309. //
  310. fileChangeHandle = FindFirstChangeNotification(
  311. hostDirectory,
  312. FALSE,
  313. FILE_NOTIFY_CHANGE_FILE_NAME |
  314. FILE_NOTIFY_CHANGE_LAST_WRITE );
  315. if ( fileChangeHandle == INVALID_HANDLE_VALUE )
  316. {
  317. DNSLOG_F1( "HostsFileMonitorThread failed to get handle from" );
  318. DNSLOG_F2( "FindFirstChangeNotification. Error code: <0x%.8X>",
  319. GetLastError() );
  320. DNSLOG_F1( "HostsFileMonitorThread exiting." );
  321. return;
  322. }
  323. //
  324. // wait on file notify OR shutdown
  325. // - on host file change rebuild cache and restart wait
  326. // - on shutdown, exit
  327. //
  328. changeHandles[0] = g_hShutdownEvent;
  329. changeHandles[1] = fileChangeHandle;
  330. while( 1 )
  331. {
  332. waitResult = WaitForMultipleObjects(
  333. 2,
  334. changeHandles,
  335. FALSE,
  336. INFINITE );
  337. switch( waitResult )
  338. {
  339. case WAIT_OBJECT_0 :
  340. // shutdown event -- exit
  341. DNSLOG_F1( "HostsFileMonitorThread: Got event" );
  342. DNSLOG_F1( "HostsFileMonitorStopEvent." );
  343. goto ThreadExit;
  344. case WAIT_OBJECT_0 + 1 :
  345. // change notify -- flush cache and reload
  346. DNSLOG_F1( "HostsFileMonitorThread: Got HOSTS file" );
  347. DNSLOG_F1( "directory change event." );
  348. // reset notification -- BEFORE reload
  349. if ( !FindNextChangeNotification( fileChangeHandle ) )
  350. {
  351. DNSLOG_F1( "HostsFileMonitorThread failed to get handle" );
  352. DNSLOG_F1( "from FindNextChangeNotification." );
  353. DNSLOG_F2( "Error code: <0x%.8X>", GetLastError() );
  354. goto ThreadExit;
  355. }
  356. FlushCache( TRUE ); // flush and reload
  357. break;
  358. default:
  359. DNSLOG_F1( "HostsFileMonitorThread failed to get handle" );
  360. goto ThreadExit;
  361. break;
  362. }
  363. }
  364. ThreadExit:
  365. // close change\notify handle
  366. CloseHandle( fileChangeHandle );
  367. DNSDBG( INIT, (
  368. "HostFileMonitorThread exit\n" ));
  369. DNSLOG_F1( "HostsFileMonitorThread exiting." );
  370. }
  371. VOID
  372. LoadHostFileIntoCache(
  373. IN PSTR pFileName
  374. )
  375. /*++
  376. Routine Description:
  377. Read hosts file into cache.
  378. Arguments:
  379. pFileName -- file name to load
  380. Return Value:
  381. None.
  382. --*/
  383. {
  384. HOST_FILE_INFO hostInfo;
  385. DNSDBG( INIT, ( "Enter LoadHostFile\n" ));
  386. //
  387. // read entries from host file until exhausted
  388. // - cache A record for each name and alias
  389. // - cache PTR to name
  390. //
  391. RtlZeroMemory(
  392. &hostInfo,
  393. sizeof(hostInfo) );
  394. if ( !Dns_OpenHostFile( &hostInfo ) )
  395. {
  396. return;
  397. }
  398. hostInfo.fBuildRecords = TRUE;
  399. while ( Dns_ReadHostFileLine( &hostInfo ) )
  400. {
  401. // cache all the records we sucked out
  402. //
  403. // DCR: cache answer data with CNAME data
  404. CacheAnyAdditionalRecords( hostInfo.pForwardRR, TRUE );
  405. CacheAnyAdditionalRecords( hostInfo.pReverseRR, TRUE );
  406. CacheAnyAdditionalRecords( hostInfo.pAliasRR, TRUE );
  407. }
  408. Dns_CloseHostFile( &hostInfo );
  409. DNSDBG( INIT, ( "Leave LoadHostFile\n" ));
  410. }
  411. //
  412. // End hostfile.c
  413. //