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.

839 lines
18 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. FwLogger.cpp
  5. Abstract:
  6. Simple console logger for the personal firewall.
  7. Author:
  8. Jonathan Burstein (jonburs) 12-April-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Name of the event trace session
  15. //
  16. _TCHAR cszLogSession[] = _T("FirewallLogSession");
  17. //
  18. // Event counters
  19. //
  20. LONG g_lDropped = 0;
  21. LONG g_lCCreated = 0;
  22. LONG g_lCDeleted = 0;
  23. //
  24. // GUIDs corresponding to the firewall trace events
  25. //
  26. GUID ConnectionCreationEventGuid = MSIPNAT_ConnectionCreationEventGuid;
  27. GUID ConnectionDeletionEventGuid = MSIPNAT_ConnectionDeletionEventGuid;
  28. GUID PacketDroppedEventGuid = MSIPNAT_PacketDroppedEventGuid;
  29. //
  30. // Event to signal for shutdown
  31. //
  32. HANDLE g_hShutdownEvent;
  33. //
  34. // Function prototypes
  35. //
  36. VOID
  37. CALLBACK
  38. ConnectionCreationCallback(
  39. PEVENT_TRACE pEvent
  40. );
  41. VOID
  42. CALLBACK
  43. ConnectionDeletionCallback(
  44. PEVENT_TRACE pEvent
  45. );
  46. BOOL
  47. WINAPI
  48. ControlHandler(
  49. DWORD dwCtrlType
  50. );
  51. VOID
  52. CALLBACK
  53. PacketDroppedCallback(
  54. PEVENT_TRACE pEvent
  55. );
  56. UINT
  57. WINAPI
  58. ProcessTraceRoutine(
  59. PVOID pvThreadParam
  60. );
  61. int
  62. __cdecl
  63. main(
  64. int argc,
  65. _TCHAR **argv
  66. )
  67. /*++
  68. Routine Description:
  69. Program entry point. Starts the logging session and launches the
  70. processing thread.
  71. Arguments:
  72. argc -- count of command line arguments.
  73. argv -- command line arguments
  74. Return Value:
  75. Error code.
  76. --*/
  77. {
  78. TRACEHANDLE hSession;
  79. HANDLE hThread;
  80. HANDLE rghWaitHandles[2];
  81. PEVENT_TRACE_PROPERTIES pProperties;
  82. ULONG ulError;
  83. ULONG ulSize;
  84. UINT uiThreadId;
  85. BOOL fWaitForThread = FALSE;
  86. //
  87. // Create the event used to signal that the program should exit
  88. //
  89. g_hShutdownEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  90. if( NULL == g_hShutdownEvent )
  91. {
  92. _tprintf( _T("FwLogger: CreateEvent returned NULL (%08x)\n"),
  93. GetLastError() );
  94. return -1;
  95. }
  96. //
  97. // Set our control handler. The handler will signal the shutdown event;
  98. //
  99. if( !SetConsoleCtrlHandler( ControlHandler, TRUE ))
  100. {
  101. _tprintf( _T("FwLogger: SetConsoleCtrlHandler failed (%08x)\n"),
  102. GetLastError() );
  103. CloseHandle( g_hShutdownEvent );
  104. return -1;
  105. }
  106. //
  107. // Initialize our trace properties and start the tracing session.
  108. //
  109. ulSize = sizeof(*pProperties)
  110. + (_tcslen( cszLogSession ) + 1) * sizeof(_TCHAR);
  111. pProperties = (PEVENT_TRACE_PROPERTIES) HeapAlloc(
  112. GetProcessHeap(),
  113. HEAP_ZERO_MEMORY,
  114. ulSize
  115. );
  116. if( NULL == pProperties )
  117. {
  118. _tprintf( _T("FwLogger: allocation failed\n" ));
  119. CloseHandle( g_hShutdownEvent );
  120. return -1;
  121. }
  122. pProperties->Wnode.BufferSize = ulSize;
  123. pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  124. pProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  125. pProperties->FlushTimer = 1;
  126. pProperties->BufferSize = 4;
  127. ulError = StartTrace( &hSession, cszLogSession, pProperties );
  128. if( ERROR_SUCCESS != ulError )
  129. {
  130. _tprintf( _T("FwLogger: StartTrace returned 0x%08x\n"), ulError );
  131. CloseHandle( g_hShutdownEvent );
  132. HeapFree( GetProcessHeap(), 0, pProperties );
  133. return -1;
  134. }
  135. //
  136. // Enable the trace control guids
  137. //
  138. ulError = EnableTrace(
  139. TRUE,
  140. 0,
  141. 0,
  142. &PacketDroppedEventGuid,
  143. hSession
  144. );
  145. if( ERROR_SUCCESS != ulError )
  146. {
  147. _tprintf( _T("FwLogger: EnableTrace (PacketDropped) returned 0x%08x\n"),
  148. ulError );
  149. goto StopTrace;
  150. }
  151. ulError = EnableTrace(
  152. TRUE,
  153. 0,
  154. 0,
  155. &ConnectionCreationEventGuid,
  156. hSession
  157. );
  158. if( ERROR_SUCCESS != ulError )
  159. {
  160. _tprintf( _T("FwLogger: EnableTrace (ConnectionCreation) returned 0x%08x\n"),
  161. ulError );
  162. goto StopTrace;
  163. }
  164. //
  165. // Launch a thread to process the trace data. This needs to happen in a
  166. // separate thread as ProcessTrace blocks.
  167. //
  168. hThread = (HANDLE) _beginthreadex(
  169. NULL,
  170. 0,
  171. ProcessTraceRoutine,
  172. NULL,
  173. 0,
  174. &uiThreadId
  175. );
  176. if( NULL == hThread )
  177. {
  178. _tprintf( _T("FwLogger: Unable to create thread (0x%08x)\n"),
  179. GetLastError() );
  180. goto StopTrace;
  181. }
  182. //
  183. // Wait for the shutdown event to be signalled, or for our
  184. // thread to exit.
  185. //
  186. rghWaitHandles[0] = g_hShutdownEvent;
  187. rghWaitHandles[1] = hThread;
  188. ulError = WaitForMultipleObjects( 2, rghWaitHandles, FALSE, INFINITE );
  189. if( WAIT_OBJECT_0 == ulError )
  190. {
  191. //
  192. // User wants program to finish. After we shutdownt the trace session,
  193. // we'll need to wait for the processing thread to cleanup and exit.
  194. //
  195. fWaitForThread = TRUE;
  196. _tprintf( _T("FwLogger: Shutdown event signaled\n") );
  197. }
  198. else if( WAIT_OBJECT_0 + 1 == ulError )
  199. {
  200. //
  201. // Thread exited early, due to some problem...
  202. //
  203. _tprintf( _T("FwLogger: Trace process thread finished early.\n") );
  204. }
  205. StopTrace:
  206. //
  207. // Disable the events we previously enabled
  208. //
  209. ulError = EnableTrace(
  210. FALSE,
  211. 0,
  212. 0,
  213. &PacketDroppedEventGuid,
  214. hSession
  215. );
  216. if( ERROR_SUCCESS != ulError )
  217. {
  218. _tprintf( _T("FwLogger: EnableTrace (PacketDropped - FALSE) returned 0x%08x\n"),
  219. ulError );
  220. }
  221. ulError = EnableTrace(
  222. FALSE,
  223. 0,
  224. 0,
  225. &ConnectionCreationEventGuid,
  226. hSession
  227. );
  228. if( ERROR_SUCCESS != ulError )
  229. {
  230. _tprintf( _T("FwLogger: EnableTrace (ConnectionCreation - FALSE) returned 0x%08x\n"),
  231. ulError );
  232. }
  233. //
  234. // Stop the trace
  235. //
  236. ZeroMemory( pProperties, ulSize );
  237. pProperties->Wnode.BufferSize = ulSize;
  238. ulError = StopTrace( hSession, NULL, pProperties );
  239. if( ERROR_SUCCESS != ulError )
  240. {
  241. _tprintf( _T("FwLogger: StopTrace returned 0x%08x\n"), ulError );
  242. }
  243. else
  244. {
  245. _tprintf( _T("FwLogger: Trace stopped\n\n") );
  246. //
  247. // Print out statistics
  248. //
  249. _tprintf( _T("**Packets dropped: %i\n"), g_lDropped );
  250. _tprintf( _T("**Connections created: %i\n"), g_lCCreated );
  251. _tprintf( _T("**Connections deleted: %i\n"), g_lCDeleted );
  252. _tprintf( _T("**Events lost: %u\n"), pProperties->EventsLost );
  253. _tprintf( _T("**Buffers lost: %u\n"), pProperties->LogBuffersLost );
  254. _tprintf( _T("**Realtime buffers lost: %u\n\n"),
  255. pProperties->RealTimeBuffersLost );
  256. }
  257. //
  258. // Give processing thread 15 seconds to finish
  259. //
  260. if( fWaitForThread )
  261. {
  262. _tprintf( _T("FwLogger: Waiting for thread to exit...\n") );
  263. ulError = WaitForSingleObject( hThread, 15 * 1000 );
  264. if( WAIT_OBJECT_0 != ulError )
  265. {
  266. _tprintf( _T("FwLogger: Wait failed (timeout = %s)\n"),
  267. WAIT_TIMEOUT == ulError ? _T("true") : _T("false") );
  268. }
  269. }
  270. CloseHandle( g_hShutdownEvent );
  271. CloseHandle( hThread );
  272. HeapFree( GetProcessHeap(), 0, pProperties );
  273. return 0;
  274. }
  275. VOID
  276. CALLBACK
  277. ConnectionCreationCallback(
  278. PEVENT_TRACE pEvent
  279. )
  280. /*++
  281. Routine Description:
  282. Called when a ConnectionCreationEvent occurs.
  283. Arguments:
  284. pEvent -- pointer to the event trace structure
  285. Return Value:
  286. None.
  287. --*/
  288. {
  289. FILETIME ftUtcTime;
  290. FILETIME ftLocalTime;
  291. SYSTEMTIME stLocalTime;
  292. PMSIPNAT_ConnectionCreationEvent pEventData;
  293. struct in_addr inAddr;
  294. InterlockedIncrement( &g_lCCreated );
  295. pEventData = (PMSIPNAT_ConnectionCreationEvent) pEvent->MofData;
  296. //
  297. // Convert the event timestamp to local systemtime structure
  298. //
  299. ftUtcTime.dwLowDateTime = pEvent->Header.TimeStamp.LowPart;
  300. ftUtcTime.dwHighDateTime = pEvent->Header.TimeStamp.HighPart;
  301. if( !FileTimeToLocalFileTime( &ftUtcTime, &ftLocalTime )
  302. || !FileTimeToSystemTime( &ftLocalTime, &stLocalTime ))
  303. {
  304. //
  305. // Conversion failed -- use zero time
  306. //
  307. ZeroMemory( &stLocalTime, sizeof( SYSTEMTIME ));
  308. }
  309. //
  310. // Print timestamp (yyyy/mm/dd hh:mm:ss)
  311. //
  312. _tprintf(
  313. _T("%i/%02i/%02i %02i:%02i:%02i ++"),
  314. stLocalTime.wYear,
  315. stLocalTime.wMonth,
  316. stLocalTime.wDay,
  317. stLocalTime.wHour,
  318. stLocalTime.wMinute,
  319. stLocalTime.wSecond
  320. );
  321. //
  322. // Connection details.
  323. //
  324. if( NAT_PROTOCOL_TCP == pEventData->Protocol )
  325. {
  326. _tprintf( _T("TCP ") );
  327. }
  328. else
  329. {
  330. _tprintf( _T("UDP ") );
  331. }
  332. if( pEventData->InboundConnection )
  333. {
  334. _tprintf( _T("inbound ") );
  335. }
  336. else
  337. {
  338. _tprintf( _T("outbound ") );
  339. }
  340. inAddr.s_addr = pEventData->LocalAddress;
  341. printf( inet_ntoa( inAddr ));
  342. _tprintf(
  343. _T("/%u :: "),
  344. ntohs( (u_short) pEventData->LocalPort )
  345. );
  346. inAddr.s_addr = pEventData->RemoteAddress;
  347. printf( inet_ntoa( inAddr ));
  348. _tprintf(
  349. _T("/%u\n"),
  350. ntohs( (u_short) pEventData->RemotePort )
  351. );
  352. }
  353. VOID
  354. CALLBACK
  355. ConnectionDeletionCallback(
  356. PEVENT_TRACE pEvent
  357. )
  358. /*++
  359. Routine Description:
  360. Called when a ConnectionDeletionEvent occurs.
  361. Arguments:
  362. pEvent -- pointer to the event trace structure
  363. Return Value:
  364. None.
  365. --*/
  366. {
  367. FILETIME ftUtcTime;
  368. FILETIME ftLocalTime;
  369. SYSTEMTIME stLocalTime;
  370. PMSIPNAT_ConnectionDeletionEvent pEventData;
  371. struct in_addr inAddr;
  372. InterlockedIncrement( &g_lCDeleted );
  373. pEventData = (PMSIPNAT_ConnectionDeletionEvent) pEvent->MofData;
  374. //
  375. // Convert the event timestamp to local systemtime structure
  376. //
  377. ftUtcTime.dwLowDateTime = pEvent->Header.TimeStamp.LowPart;
  378. ftUtcTime.dwHighDateTime = pEvent->Header.TimeStamp.HighPart;
  379. if( !FileTimeToLocalFileTime( &ftUtcTime, &ftLocalTime )
  380. || !FileTimeToSystemTime( &ftLocalTime, &stLocalTime ))
  381. {
  382. //
  383. // Conversion failed -- use zero time
  384. //
  385. ZeroMemory( &stLocalTime, sizeof( SYSTEMTIME ));
  386. }
  387. //
  388. // Print timestamp (yyyy/mm/dd hh:mm:ss)
  389. //
  390. _tprintf(
  391. _T("%i/%02i/%02i %02i:%02i:%02i --"),
  392. stLocalTime.wYear,
  393. stLocalTime.wMonth,
  394. stLocalTime.wDay,
  395. stLocalTime.wHour,
  396. stLocalTime.wMinute,
  397. stLocalTime.wSecond
  398. );
  399. //
  400. // Connection details.
  401. //
  402. if( NAT_PROTOCOL_TCP == pEventData->Protocol )
  403. {
  404. _tprintf( _T("TCP ") );
  405. }
  406. else
  407. {
  408. _tprintf( _T("UDP ") );
  409. }
  410. inAddr.s_addr = pEventData->LocalAddress;
  411. printf( inet_ntoa( inAddr ));
  412. _tprintf(
  413. _T("/%u :: "),
  414. ntohs( (u_short) pEventData->LocalPort )
  415. );
  416. inAddr.s_addr = pEventData->RemoteAddress;
  417. printf( inet_ntoa( inAddr ));
  418. _tprintf(
  419. _T("/%u\n"),
  420. ntohs( (u_short) pEventData->RemotePort )
  421. );
  422. }
  423. VOID
  424. CALLBACK
  425. PacketDroppedCallback(
  426. PEVENT_TRACE pEvent
  427. )
  428. /*++
  429. Routine Description:
  430. Called when a PacketDroppedEvent occurs.
  431. Arguments:
  432. pEvent -- pointer to the event trace structure
  433. Return Value:
  434. None.
  435. --*/
  436. {
  437. FILETIME ftUtcTime;
  438. FILETIME ftLocalTime;
  439. SYSTEMTIME stLocalTime;
  440. PMSIPNAT_PacketDroppedEvent pEventData;
  441. struct in_addr inAddr;
  442. InterlockedIncrement( &g_lDropped );
  443. pEventData = (PMSIPNAT_PacketDroppedEvent) pEvent->MofData;
  444. //
  445. // Convert the event timestamp to local systemtime structure
  446. //
  447. ftUtcTime.dwLowDateTime = pEvent->Header.TimeStamp.LowPart;
  448. ftUtcTime.dwHighDateTime = pEvent->Header.TimeStamp.HighPart;
  449. if( !FileTimeToLocalFileTime( &ftUtcTime, &ftLocalTime )
  450. || !FileTimeToSystemTime( &ftLocalTime, &stLocalTime ))
  451. {
  452. //
  453. // Conversion failed -- use zero time
  454. //
  455. ZeroMemory( &stLocalTime, sizeof( SYSTEMTIME ));
  456. }
  457. //
  458. // Print timestamp (yyyy/mm/dd hh:mm:ss)
  459. //
  460. _tprintf(
  461. _T("%i/%02i/%02i %02i:%02i:%02i - "),
  462. stLocalTime.wYear,
  463. stLocalTime.wMonth,
  464. stLocalTime.wDay,
  465. stLocalTime.wHour,
  466. stLocalTime.wMinute,
  467. stLocalTime.wSecond
  468. );
  469. switch( pEventData->Protocol )
  470. {
  471. case NAT_PROTOCOL_TCP:
  472. {
  473. _tprintf( _T("TCP: ") );
  474. inAddr.s_addr = pEventData->SourceAddress;
  475. printf( inet_ntoa( inAddr ));
  476. _tprintf(
  477. _T("/%u -> "),
  478. ntohs( (u_short) pEventData->SourceIdentifier )
  479. );
  480. inAddr.s_addr = pEventData->DestinationAddress;
  481. printf( inet_ntoa( inAddr ));
  482. _tprintf(
  483. _T("/%u "),
  484. ntohs( (u_short) pEventData->DestinationIdentifier )
  485. );
  486. if( pEventData->ProtocolData4 & TCP_FLAG_SYN )
  487. {
  488. _tprintf( _T("S") );
  489. }
  490. if( pEventData->ProtocolData4 & TCP_FLAG_FIN )
  491. {
  492. _tprintf( _T("F") );
  493. }
  494. if( pEventData->ProtocolData4 & TCP_FLAG_ACK )
  495. {
  496. _tprintf( _T("A") );
  497. }
  498. if( pEventData->ProtocolData4 & TCP_FLAG_RST )
  499. {
  500. _tprintf( _T("R") );
  501. }
  502. if( pEventData->ProtocolData4 & TCP_FLAG_URG )
  503. {
  504. _tprintf( _T("U") );
  505. }
  506. if( pEventData->ProtocolData4 & TCP_FLAG_PSH )
  507. {
  508. _tprintf( _T("P") );
  509. }
  510. _tprintf( _T("\n") );
  511. break;
  512. }
  513. case NAT_PROTOCOL_UDP:
  514. {
  515. _tprintf( _T("UDP: ") );
  516. inAddr.s_addr = pEventData->SourceAddress;
  517. printf( inet_ntoa( inAddr ));
  518. _tprintf(
  519. _T("/%u -> "),
  520. ntohs( (u_short) pEventData->SourceIdentifier )
  521. );
  522. inAddr.s_addr = pEventData->DestinationAddress;
  523. printf( inet_ntoa( inAddr ));
  524. _tprintf(
  525. _T("/%u\n"),
  526. ntohs( (u_short) pEventData->DestinationIdentifier )
  527. );
  528. break;
  529. }
  530. case NAT_PROTOCOL_ICMP:
  531. {
  532. _tprintf( _T("ICMP: ") );
  533. inAddr.s_addr = pEventData->SourceAddress;
  534. printf( inet_ntoa( inAddr ));
  535. _tprintf( _T(" -> ") );
  536. inAddr.s_addr = pEventData->DestinationAddress;
  537. printf( "%s\n", inet_ntoa( inAddr ));
  538. break;
  539. }
  540. default:
  541. {
  542. _tprintf( _T("Prot. %i: "), pEventData->Protocol );
  543. inAddr.s_addr = pEventData->SourceAddress;
  544. printf( inet_ntoa( inAddr ));
  545. _tprintf( _T(" -> ") );
  546. inAddr.s_addr = pEventData->DestinationAddress;
  547. printf( "%s\n", inet_ntoa( inAddr ));
  548. }
  549. }
  550. }
  551. UINT
  552. WINAPI
  553. ProcessTraceRoutine(
  554. PVOID pvThreadParam
  555. )
  556. /*++
  557. Routine Description:
  558. Thread routine for trace processing.
  559. Arguments:
  560. pvThreadParam -- unused.
  561. Return Value:
  562. Thread exit code.
  563. --*/
  564. {
  565. TRACEHANDLE hStream;
  566. EVENT_TRACE_LOGFILE LogFile;
  567. ULONG ulError;
  568. //
  569. // Register our trace callbacks
  570. //
  571. ulError = SetTraceCallback( &PacketDroppedEventGuid, PacketDroppedCallback );
  572. if( ERROR_SUCCESS != ulError )
  573. {
  574. _tprintf( _T("FwLogger: SetTraceCallback (PacketDropped) returned 0x%08x\n"),
  575. ulError );
  576. return -1;
  577. }
  578. ulError = SetTraceCallback( &ConnectionCreationEventGuid, ConnectionCreationCallback );
  579. if( ERROR_SUCCESS != ulError )
  580. {
  581. _tprintf( _T("FwLogger: SetTraceCallback (ConnectionCreation) returned 0x%08x\n"),
  582. ulError );
  583. return -1;
  584. }
  585. ulError = SetTraceCallback( &ConnectionDeletionEventGuid, ConnectionDeletionCallback );
  586. if( ERROR_SUCCESS != ulError )
  587. {
  588. _tprintf( _T("FwLogger: SetTraceCallback (ConnectionDeletion) returned 0x%08x\n"),
  589. ulError );
  590. return -1;
  591. }
  592. //
  593. // Open the event stream.
  594. //
  595. ZeroMemory( &LogFile, sizeof(LogFile) );
  596. LogFile.LoggerName = cszLogSession;
  597. LogFile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  598. hStream = OpenTrace( &LogFile );
  599. if( (TRACEHANDLE)INVALID_HANDLE_VALUE == hStream )
  600. {
  601. _tprintf( _T("FwLogger: OpenTrace returned 0x%08x\n"), GetLastError() );
  602. return -1;
  603. }
  604. //
  605. // Process the trace stream
  606. //
  607. _tprintf( _T("FwLogger: Calling ProcessTrace...\n") );
  608. ulError = ProcessTrace( &hStream, 1, NULL, NULL );
  609. if( ERROR_SUCCESS != ulError )
  610. {
  611. _tprintf( _T("FwLogger: ProcessTrace returned 0x%08x\n"), ulError );
  612. CloseTrace( hStream );
  613. return -1;
  614. }
  615. //
  616. // Close the stream and exit
  617. //
  618. CloseTrace( hStream );
  619. return 0;
  620. }
  621. BOOL
  622. WINAPI
  623. ControlHandler(
  624. DWORD dwCtrlType
  625. )
  626. /*++
  627. Routine Description:
  628. Signals our shutdown event when the user wants to exit.
  629. Arguments:
  630. dwCtrlType -- control signal type
  631. Return Value:
  632. TRUE if we handled the control signal.
  633. --*/
  634. {
  635. if( CTRL_LOGOFF_EVENT != dwCtrlType )
  636. {
  637. SetEvent( g_hShutdownEvent );
  638. return TRUE;
  639. }
  640. return FALSE;
  641. }