Leaked source code of windows server 2003
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.

2938 lines
70 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. fwlogger.cpp
  5. Abstract:
  6. Support for firewall logging to a text file.
  7. Author:
  8. Jonathan Burstein (jonburs) 18 September 2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #if DBG
  14. //
  15. // Module state -- interlocked access only. This information
  16. // is only used on debug builds.
  17. //
  18. typedef enum {
  19. FwUninitialized = 0,
  20. FwInitialized
  21. } FW_MODULE_STATE;
  22. FW_MODULE_STATE FwpModuleState = FwUninitialized;
  23. #endif // DBG
  24. //
  25. // Globals. If both locks need to be held at the same time,
  26. // g_FwFileLock must be acquired first.
  27. //
  28. CRITICAL_SECTION g_FwLock;
  29. HNET_FW_LOGGING_SETTINGS *g_pSettings;
  30. TRACEHANDLE g_hSession;
  31. HANDLE g_hThread;
  32. BOOLEAN g_fTracingActive;
  33. ULONG g_ulKernelEventsLostAtShutdown;
  34. CRITICAL_SECTION g_FwFileLock;
  35. HANDLE g_hFile;
  36. DWORD g_dwFileOffset;
  37. PFW_LOG_BUFFER g_pCurrentBuffer;
  38. PFW_LOG_BUFFER g_pReserveBuffer;
  39. BOOLEAN g_fIOPending;
  40. HANDLE g_hIOEvent;
  41. ULONG g_ulDroppedEventCount;
  42. ULONG g_ulKernelEventsLost;
  43. HANDLE g_hDroppedEventTimer;
  44. //
  45. // Constants
  46. //
  47. GUID c_ConnectionCreationEventGuid = MSIPNAT_ConnectionCreationEventGuid;
  48. GUID c_ConnectionDeletionEventGuid = MSIPNAT_ConnectionDeletionEventGuid;
  49. GUID c_PacketDroppedEventGuid = MSIPNAT_PacketDroppedEventGuid;
  50. WCHAR c_wszLogSessionName[] = L"FirewallLogSession";
  51. WCHAR c_wszBackupFileExtension[] = L".old";
  52. CHAR c_szConnectionFormat[] = "%04d-%02d-%02d %02d:%02d:%02d %s %s %s %s %u %u - - - - - - - -\r\n";
  53. CHAR c_szTcpPacketFormat[] = "%04d-%02d-%02d %02d:%02d:%02d DROP TCP %s %s %u %u %u %s %u %u %u - - -\r\n";
  54. CHAR c_szUdpPacketFormat[] = "%04d-%02d-%02d %02d:%02d:%02d DROP UDP %s %s %u %u %u - - - - - - -\r\n";
  55. CHAR c_szIcmpPacketFormat[] = "%04d-%02d-%02d %02d:%02d:%02d DROP ICMP %s %s - - %u - - - - %u %u -\r\n";
  56. CHAR c_szDroppedPacketFormat[] = "%04d-%02d-%02d %02d:%02d:%02d DROP %u %s %s - - %u - - - - - - -\r\n";
  57. CHAR c_szEventsLostFormat[] = "%04d-%02d-%02d %02d:%02d:%02d INFO-EVENTS-LOST - - - - - - - - - - - - %u\r\n";
  58. CHAR c_szAcceptInbound[] = "OPEN-INBOUND";
  59. CHAR c_szAcceptOutbound[] = "OPEN";
  60. CHAR c_szTcp[] = "TCP";
  61. CHAR c_szUdp[] = "UDP";
  62. CHAR c_szLogFileHeader[]
  63. = "#Verson: 1.0\r\n#Software: Microsoft Internet Connection Firewall\r\n#Time Format: Local\r\n#Fields: date time action protocol src-ip dst-ip src-port dst-port size tcpflags tcpsyn tcpack tcpwin icmptype icmpcode info\r\n\r\n";
  64. //
  65. // Function Prototypes
  66. //
  67. DWORD
  68. FwpAllocateBuffer(
  69. PFW_LOG_BUFFER *ppBuffer
  70. );
  71. PEVENT_TRACE_PROPERTIES
  72. FwpAllocateTraceProperties(
  73. VOID
  74. );
  75. DWORD
  76. FwpBackupFile(
  77. LPWSTR pszwPath
  78. );
  79. VOID
  80. FwpCleanupTraceThreadResources(
  81. VOID
  82. );
  83. VOID
  84. CALLBACK
  85. FwpCompletionRoutine(
  86. DWORD dwErrorCode,
  87. DWORD dwBytesTransferred,
  88. LPOVERLAPPED pOverlapped
  89. );
  90. VOID
  91. WINAPI
  92. FwpConnectionCreationCallback(
  93. PEVENT_TRACE pEvent
  94. );
  95. VOID
  96. WINAPI
  97. FwpConnectionDeletionCallback(
  98. PEVENT_TRACE pEvent
  99. );
  100. VOID
  101. FwpConvertUtcFiletimeToLocalSystemtime(
  102. FILETIME *pFiletime,
  103. SYSTEMTIME *pSystemtime
  104. );
  105. VOID
  106. CALLBACK
  107. FwpDroppedEventTimerRoutine(
  108. PVOID pvParameter,
  109. BOOLEAN fWaitTimeout
  110. );
  111. DWORD
  112. FwpFlushCurrentBuffer(
  113. VOID
  114. );
  115. DWORD
  116. FwpOpenLogFile(
  117. HANDLE *phFile,
  118. BOOLEAN *pfNewFile
  119. );
  120. VOID
  121. WINAPI
  122. FwpPacketDroppedCallback(
  123. PEVENT_TRACE pEvent
  124. );
  125. DWORD
  126. FwpLaunchTraceSession(
  127. HNET_FW_LOGGING_SETTINGS *pSettings,
  128. TRACEHANDLE *phSession
  129. );
  130. HRESULT
  131. FwpLoadSettings(
  132. HNET_FW_LOGGING_SETTINGS **ppSettings
  133. );
  134. DWORD
  135. WINAPI
  136. FwpTraceProcessingThreadRoutine(
  137. LPVOID pvParam
  138. );
  139. DWORD
  140. FwpWriteLogHeaderToBuffer(
  141. PFW_LOG_BUFFER pBuffer
  142. );
  143. VOID
  144. FwCleanupLogger(
  145. VOID
  146. )
  147. /*++
  148. Routine Description:
  149. This routine is called to cleanup the logging subsystem. All
  150. resources in use will be freed. After this call, the only valid
  151. routine in this module is FwInitializeLogger.
  152. Arguments:
  153. none.
  154. Return Value:
  155. none.
  156. Environment:
  157. Caller must not be holding g_FwFileLock or g_FwLock
  158. --*/
  159. {
  160. PROFILE("FwCleanupLogger");
  161. //
  162. // Make sure the logging is stopped
  163. //
  164. FwStopLogging();
  165. ASSERT(FwInitialized ==
  166. (FW_MODULE_STATE) InterlockedExchange(
  167. (LPLONG) &FwpModuleState,
  168. (LONG) FwUninitialized
  169. ));
  170. EnterCriticalSection(&g_FwLock);
  171. ASSERT(NULL == g_hSession);
  172. ASSERT(NULL == g_hThread);
  173. ASSERT(INVALID_HANDLE_VALUE == g_hFile);
  174. if (g_pSettings) HNetFreeFirewallLoggingSettings(g_pSettings);
  175. LeaveCriticalSection(&g_FwLock);
  176. DeleteCriticalSection(&g_FwLock);
  177. DeleteCriticalSection(&g_FwFileLock);
  178. } // FwCleanupLogger
  179. DWORD
  180. FwInitializeLogger(
  181. VOID
  182. )
  183. /*++
  184. Routine Description:
  185. This routine is called to control to initialize the logging subsystem.
  186. It must be called before any of the other routines in this module, and
  187. may not be called again until after a call to FwCleanupLogger.
  188. Arguments:
  189. none.
  190. Return Value:
  191. DWORD -- Win32 error code
  192. --*/
  193. {
  194. DWORD dwError = NO_ERROR;
  195. BOOLEAN fFirstLockInitialized = FALSE;
  196. PROFILE("FwInitializeLogger");
  197. ASSERT(FwUninitialized ==
  198. (FW_MODULE_STATE) InterlockedExchange(
  199. (LPLONG) &FwpModuleState,
  200. (LONG) FwInitialized
  201. ));
  202. __try
  203. {
  204. InitializeCriticalSection(&g_FwLock);
  205. fFirstLockInitialized = TRUE;
  206. InitializeCriticalSection(&g_FwFileLock);
  207. }
  208. __except(EXCEPTION_EXECUTE_HANDLER)
  209. {
  210. NhTrace(
  211. TRACE_FLAG_FWLOG,
  212. "FwInitializeLogger: exception %d creating lock",
  213. dwError = GetExceptionCode()
  214. );
  215. if (fFirstLockInitialized)
  216. {
  217. DeleteCriticalSection(&g_FwLock);
  218. }
  219. #if DBG
  220. InterlockedExchange(
  221. (LPLONG) &FwpModuleState,
  222. (LONG) FwUninitialized
  223. );
  224. #endif
  225. }
  226. g_pSettings = NULL;
  227. g_hSession = NULL;
  228. g_hThread = NULL;
  229. g_fTracingActive = FALSE;
  230. g_ulKernelEventsLostAtShutdown = 0;
  231. g_hFile = INVALID_HANDLE_VALUE;
  232. g_dwFileOffset = 0;
  233. g_pCurrentBuffer = NULL;
  234. g_pReserveBuffer = NULL;
  235. g_fIOPending = FALSE;
  236. g_hIOEvent = NULL;
  237. g_ulDroppedEventCount = 0;
  238. g_ulKernelEventsLost = 0;
  239. g_hDroppedEventTimer = NULL;
  240. return dwError;
  241. } // FwInitializeLogger
  242. DWORD
  243. FwpAllocateBuffer(
  244. PFW_LOG_BUFFER *ppBuffer
  245. )
  246. /*++
  247. Routine Description:
  248. Allocates an initializes an FW_LOG_BUFFER structure
  249. Arguments:
  250. ppBuffer - receives a pointer to the newly-allocated structure
  251. Return Value:
  252. DWORD - Win32 error code
  253. --*/
  254. {
  255. DWORD dwError = ERROR_SUCCESS;
  256. PROFILE("FwpAllocateBuffer");
  257. ASSERT(NULL != ppBuffer);
  258. *ppBuffer =
  259. reinterpret_cast<PFW_LOG_BUFFER>(
  260. NH_ALLOCATE(sizeof(**ppBuffer))
  261. );
  262. if (NULL != *ppBuffer)
  263. {
  264. ZeroMemory(&(*ppBuffer)->Overlapped, sizeof(OVERLAPPED));
  265. (*ppBuffer)->pChar = (*ppBuffer)->Buffer;
  266. }
  267. else
  268. {
  269. dwError = ERROR_NOT_ENOUGH_MEMORY;
  270. }
  271. return dwError;
  272. } // FwpAllocateBuffer
  273. PEVENT_TRACE_PROPERTIES
  274. FwpAllocateTraceProperties(
  275. VOID
  276. )
  277. /*++
  278. Routine Description:
  279. Allocates and partially initializes an EVENT_TRACE_PROPERTIES structure.
  280. Arguments:
  281. none.
  282. Return Value:
  283. PEVENT_TRACE_PROPERTIES - pointer to the allocated structure. The caller
  284. must call HeapFree(GetProcessHeap(),...) on this pointer.
  285. --*/
  286. {
  287. PEVENT_TRACE_PROPERTIES pProperties = NULL;
  288. ULONG ulSize;
  289. ulSize = sizeof(*pProperties)
  290. + ((wcslen(c_wszLogSessionName) + 1) * sizeof(WCHAR));
  291. pProperties = (PEVENT_TRACE_PROPERTIES) HeapAlloc(
  292. GetProcessHeap(),
  293. HEAP_ZERO_MEMORY,
  294. ulSize
  295. );
  296. if (NULL == pProperties)
  297. {
  298. NhTrace(
  299. TRACE_FLAG_FWLOG,
  300. "FwpAllocateTraceProperties: Unable to allocate %d bytes",
  301. ulSize
  302. );
  303. return NULL;
  304. }
  305. pProperties->Wnode.BufferSize = ulSize;
  306. pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  307. pProperties->Wnode.ClientContext = EVENT_TRACE_CLOCK_SYSTEMTIME;
  308. pProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  309. pProperties->LoggerNameOffset = sizeof(*pProperties);
  310. return pProperties;
  311. } // FwpAllocateTraceProperties
  312. DWORD
  313. FwpBackupFile(
  314. LPWSTR pszwPath
  315. )
  316. /*++
  317. Routine Description:
  318. Backs-up a file to filename.xxx.old
  319. Arguments:
  320. pszwPath - path to the file to backup
  321. Return Value:
  322. DWORD - Win32 error code
  323. --*/
  324. {
  325. DWORD dwError = ERROR_SUCCESS;
  326. BOOL fResult;
  327. LPWSTR wszBuffer;
  328. ASSERT(NULL != pszwPath);
  329. //
  330. // Allocate buffer to hold new filename
  331. //
  332. wszBuffer =
  333. new WCHAR[wcslen(pszwPath) + wcslen(c_wszBackupFileExtension) + 1];
  334. if (NULL != wszBuffer)
  335. {
  336. lstrcpyW(wszBuffer, pszwPath);
  337. lstrcatW(wszBuffer, c_wszBackupFileExtension);
  338. fResult = MoveFileEx(pszwPath, wszBuffer, MOVEFILE_REPLACE_EXISTING);
  339. if (FALSE == fResult)
  340. {
  341. dwError = GetLastError();
  342. NhTrace(
  343. TRACE_FLAG_FWLOG,
  344. "FwpBackupFile: MoveFileEx = %d",
  345. dwError
  346. );
  347. }
  348. }
  349. else
  350. {
  351. dwError = ERROR_NOT_ENOUGH_MEMORY;
  352. NhTrace(
  353. TRACE_FLAG_FWLOG,
  354. "FwpBackupFile: Unable to allolcate buffer"
  355. );
  356. }
  357. return dwError;
  358. } // FwpBackupFile
  359. VOID
  360. FwpCleanupTraceThreadResources(
  361. VOID
  362. )
  363. /*++
  364. Routine Description:
  365. Cleans up resources used by the trace processing thread:
  366. * revokes event callbacks
  367. * waits for IO to complete, if pending
  368. * closes the log file
  369. * frees buffers
  370. Arguments:
  371. none.
  372. Return Value:
  373. none.
  374. Environment:
  375. The caller must not hold g_FwFileLock or g_FwLock.
  376. --*/
  377. {
  378. DWORD dwError;
  379. HANDLE hDroppedEventTimer;
  380. PROFILE("FwpCleanupTraceThreadResources");
  381. //
  382. // Unregister the trace callbacks. It is safe to call these even
  383. // if the callbacks weren't registered to begin with.
  384. //
  385. RemoveTraceCallback(&c_PacketDroppedEventGuid);
  386. RemoveTraceCallback(&c_ConnectionCreationEventGuid);
  387. RemoveTraceCallback(&c_ConnectionDeletionEventGuid);
  388. EnterCriticalSection(&g_FwFileLock);
  389. //
  390. // Cancel the dropped packet timer
  391. //
  392. hDroppedEventTimer = g_hDroppedEventTimer;
  393. g_hDroppedEventTimer = NULL;
  394. //
  395. // Since we're doing a blocking delete of the timer we can't
  396. // hold the lock when for the call to DeleteTimerQueueTimer --
  397. // a deadlock could result if the timer routine has been queued but
  398. // not yet executed when we make the call.
  399. //
  400. LeaveCriticalSection(&g_FwFileLock);
  401. if (NULL != hDroppedEventTimer)
  402. {
  403. DeleteTimerQueueTimer(
  404. NULL,
  405. hDroppedEventTimer,
  406. INVALID_HANDLE_VALUE
  407. );
  408. }
  409. EnterCriticalSection(&g_FwFileLock);
  410. //
  411. // If necessary, wait for any pending IO operations to complete
  412. //
  413. if (g_fIOPending)
  414. {
  415. g_hIOEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  416. if (NULL != g_hIOEvent)
  417. {
  418. HANDLE hEvent = g_hIOEvent;
  419. LeaveCriticalSection(&g_FwFileLock);
  420. dwError = WaitForSingleObject(hEvent, 20 * 1000);
  421. if (WAIT_OBJECT_0 != dwError)
  422. {
  423. NhTrace(
  424. TRACE_FLAG_FWLOG,
  425. "FwpTraceProcessingRoutine: Wait(g_hIOEvent) = %d/%d",
  426. dwError,
  427. GetLastError()
  428. );
  429. //
  430. // It should never take 20 seconds for an IO to complete,
  431. // so let's get immediate notification of this on debug
  432. // builds.
  433. //
  434. ASSERT(WAIT_OBJECT_0 == dwError);
  435. }
  436. EnterCriticalSection(&g_FwFileLock);
  437. CloseHandle(g_hIOEvent);
  438. g_hIOEvent = NULL;
  439. }
  440. }
  441. g_fIOPending = FALSE;
  442. //
  443. // Close the log file
  444. //
  445. if (INVALID_HANDLE_VALUE != g_hFile)
  446. {
  447. CloseHandle(g_hFile);
  448. g_hFile = INVALID_HANDLE_VALUE;
  449. }
  450. g_dwFileOffset = 0;
  451. //
  452. // Clean up our buffers
  453. //
  454. if (NULL != g_pCurrentBuffer)
  455. {
  456. NH_FREE(g_pCurrentBuffer);
  457. g_pCurrentBuffer = NULL;
  458. }
  459. if (NULL != g_pReserveBuffer)
  460. {
  461. NH_FREE(g_pReserveBuffer);
  462. g_pReserveBuffer = NULL;
  463. }
  464. //
  465. // Reset dropped event counts
  466. //
  467. g_ulDroppedEventCount = 0;
  468. g_ulKernelEventsLost = 0;
  469. LeaveCriticalSection(&g_FwFileLock);
  470. } // FwpCleanupTraceThreadResources
  471. VOID
  472. CALLBACK
  473. FwpCompletionRoutine(
  474. DWORD dwErrorCode,
  475. DWORD dwBytesTransferred,
  476. LPOVERLAPPED pOverlapped
  477. )
  478. /*++
  479. Routine Description:
  480. Completion routine called by the system thread pool when our
  481. IO operation is finished. Responsible for updating the file
  482. position and starting a new IO operation if necessary.
  483. Arguments:
  484. dwErrorCode - result of the IO operation
  485. dwBytesTransferred - number of bytes transferred during the operation
  486. pOverlapped - pointer to the overlapped structure for the operation. We
  487. can recover the FW_LOG_BUFFER structure from this pointer.
  488. Return Value:
  489. none.
  490. --*/
  491. {
  492. PFW_LOG_BUFFER pBuffer;
  493. EnterCriticalSection(&g_FwFileLock);
  494. //
  495. // Adjust our file offset
  496. //
  497. if (ERROR_SUCCESS == dwErrorCode)
  498. {
  499. g_dwFileOffset += dwBytesTransferred;
  500. }
  501. else
  502. {
  503. NhTrace(
  504. TRACE_FLAG_FWLOG,
  505. "FwpCompletionRoutine: dwErrorCode = %d",
  506. dwErrorCode
  507. );
  508. }
  509. g_fIOPending = FALSE;
  510. //
  511. // Reset the buffer that was passed in
  512. //
  513. ASSERT(NULL != pOverlapped);
  514. pBuffer = CONTAINING_RECORD(pOverlapped, FW_LOG_BUFFER, Overlapped);
  515. ZeroMemory(&pBuffer->Overlapped, sizeof(OVERLAPPED));
  516. pBuffer->pChar = pBuffer->Buffer;
  517. //
  518. // Check if the file is at the size limit
  519. //
  520. EnterCriticalSection(&g_FwLock);
  521. ASSERT(NULL != g_pSettings);
  522. if (g_dwFileOffset >= g_pSettings->ulMaxFileSize)
  523. {
  524. DWORD dwError;
  525. BOOLEAN fNewFile;
  526. CloseHandle(g_hFile);
  527. g_hFile = INVALID_HANDLE_VALUE;
  528. //
  529. // If FwpBackupFile fails, FwpOpenFile will still do
  530. // the right thing.
  531. //
  532. FwpBackupFile(g_pSettings->pszwPath);
  533. g_dwFileOffset = 0;
  534. dwError = FwpOpenLogFile(&g_hFile, &fNewFile);
  535. if (ERROR_SUCCESS != dwError)
  536. {
  537. NhTrace(
  538. TRACE_FLAG_FWLOG,
  539. "FwpCompletionRoutine: FwpOpenLogFile = %d",
  540. dwError
  541. );
  542. NH_FREE(pBuffer);
  543. LeaveCriticalSection(&g_FwLock);
  544. LeaveCriticalSection(&g_FwFileLock);
  545. FwStopLogging();
  546. return;
  547. }
  548. else if (TRUE == fNewFile)
  549. {
  550. //
  551. // Need to write header.
  552. //
  553. if (ERROR_SUCCESS == FwpWriteLogHeaderToBuffer(pBuffer))
  554. {
  555. PFW_LOG_BUFFER pTempBuffer = g_pCurrentBuffer;
  556. g_pCurrentBuffer = pBuffer;
  557. FwpFlushCurrentBuffer();
  558. g_pCurrentBuffer = pTempBuffer;
  559. pBuffer = NULL;
  560. }
  561. }
  562. else
  563. {
  564. g_dwFileOffset = GetFileSize(g_hFile, NULL);
  565. if ((DWORD)-1 == g_dwFileOffset)
  566. {
  567. NhTrace(
  568. TRACE_FLAG_FWLOG,
  569. "FwpCompletionRoutine: GetFileSize = %d",
  570. GetLastError()
  571. );
  572. NH_FREE(pBuffer);
  573. LeaveCriticalSection(&g_FwLock);
  574. LeaveCriticalSection(&g_FwFileLock);
  575. FwStopLogging();
  576. return;
  577. }
  578. }
  579. }
  580. LeaveCriticalSection(&g_FwLock);
  581. //
  582. // See if we need to start a new operation.
  583. //
  584. if (FALSE == g_fIOPending && NULL != g_pCurrentBuffer)
  585. {
  586. if (g_pCurrentBuffer->pChar != g_pCurrentBuffer->Buffer)
  587. {
  588. //
  589. // Current buffer needs to be flushed
  590. //
  591. FwpFlushCurrentBuffer();
  592. }
  593. }
  594. //
  595. // Place buffer into storage. If we're using the buffer
  596. // to write the log header, it will be NULL at this point
  597. //
  598. if (NULL != pBuffer)
  599. {
  600. if (NULL == g_pCurrentBuffer)
  601. {
  602. g_pCurrentBuffer = pBuffer;
  603. }
  604. else if (NULL == g_pReserveBuffer)
  605. {
  606. g_pReserveBuffer = pBuffer;
  607. }
  608. else
  609. {
  610. //
  611. // Both buffer slots are already in use -- unexpected.
  612. // Assert and free the extra buffer
  613. //
  614. ASSERT(NULL == g_pCurrentBuffer || NULL == g_pReserveBuffer);
  615. NH_FREE(pBuffer);
  616. }
  617. }
  618. //
  619. // Check to see if we need to signal the IO finished event
  620. //
  621. if (!g_fIOPending && NULL != g_hIOEvent)
  622. {
  623. if (!SetEvent(g_hIOEvent))
  624. {
  625. NhTrace(
  626. TRACE_FLAG_FWLOG,
  627. "FwpCompletionRoutine: SetEvent = %d",
  628. GetLastError()
  629. );
  630. }
  631. }
  632. LeaveCriticalSection(&g_FwFileLock);
  633. } // FwpCompletionRoutine
  634. VOID
  635. WINAPI
  636. FwpConnectionCreationCallback(
  637. PEVENT_TRACE pEvent
  638. )
  639. /*++
  640. Routine Description:
  641. This routine is called to process a connection creation event.
  642. Arguments:
  643. pEvent - pointer to the event structure
  644. Return Value:
  645. none.
  646. --*/
  647. {
  648. PMSIPNAT_ConnectionCreationEvent pEventData;
  649. FILETIME ftUtcTime;
  650. SYSTEMTIME stLocalTime;
  651. PCHAR pszAction;
  652. PCHAR pszProtocol;
  653. CHAR szSrcAddress[16];
  654. CHAR szDstAddress[16];
  655. USHORT usSrcPort;
  656. USHORT usDstPort;
  657. int cch;
  658. EnterCriticalSection(&g_FwFileLock);
  659. //
  660. // Get a buffer to write to.
  661. //
  662. if (NULL == g_pCurrentBuffer)
  663. {
  664. if (NULL == g_pReserveBuffer)
  665. {
  666. if (ERROR_SUCCESS != FwpAllocateBuffer(&g_pCurrentBuffer))
  667. {
  668. NhTrace(
  669. TRACE_FLAG_FWLOG,
  670. "FwpConnectionCreationCallback: Unable to allocate buffer"
  671. );
  672. //
  673. // Record the dropped event
  674. //
  675. g_ulDroppedEventCount += 1;
  676. LeaveCriticalSection(&g_FwFileLock);
  677. return;
  678. }
  679. }
  680. else
  681. {
  682. g_pCurrentBuffer = g_pReserveBuffer;
  683. g_pReserveBuffer = NULL;
  684. }
  685. }
  686. ASSERT(NULL != g_pCurrentBuffer);
  687. //
  688. // Crack logging data
  689. //
  690. pEventData = (PMSIPNAT_ConnectionCreationEvent) pEvent->MofData;
  691. ftUtcTime.dwLowDateTime = pEvent->Header.TimeStamp.LowPart;
  692. ftUtcTime.dwHighDateTime = pEvent->Header.TimeStamp.HighPart;
  693. FwpConvertUtcFiletimeToLocalSystemtime(&ftUtcTime, &stLocalTime);
  694. if (pEventData->InboundConnection)
  695. {
  696. pszAction = c_szAcceptInbound;
  697. lstrcpyA(szSrcAddress, INET_NTOA(pEventData->RemoteAddress));
  698. usSrcPort = ntohs(pEventData->RemotePort);
  699. lstrcpyA(szDstAddress, INET_NTOA(pEventData->LocalAddress));
  700. usDstPort = ntohs(pEventData->LocalPort);
  701. }
  702. else
  703. {
  704. pszAction = c_szAcceptOutbound;
  705. lstrcpyA(szSrcAddress, INET_NTOA(pEventData->LocalAddress));
  706. usSrcPort = ntohs(pEventData->LocalPort);
  707. lstrcpyA(szDstAddress, INET_NTOA(pEventData->RemoteAddress));
  708. usDstPort = ntohs(pEventData->RemotePort);
  709. }
  710. pszProtocol =
  711. NAT_PROTOCOL_TCP == pEventData->Protocol ?
  712. c_szTcp :
  713. c_szUdp;
  714. //
  715. // Write the event data to the buffer
  716. //
  717. cch =
  718. _snprintf(
  719. g_pCurrentBuffer->pChar,
  720. FW_LOG_BUFFER_REMAINING(g_pCurrentBuffer),
  721. c_szConnectionFormat,
  722. stLocalTime.wYear,
  723. stLocalTime.wMonth,
  724. stLocalTime.wDay,
  725. stLocalTime.wHour,
  726. stLocalTime.wMinute,
  727. stLocalTime.wSecond,
  728. pszAction,
  729. pszProtocol,
  730. szSrcAddress,
  731. szDstAddress,
  732. usSrcPort,
  733. usDstPort
  734. );
  735. if (cch > 0)
  736. {
  737. //
  738. // Move the buffer pointer to the end of the data we just wrote.
  739. // If cch were negative, then there wasn't enough room to write
  740. // then entire entry; by not adjusting the pointer, we essentially
  741. // drop this event.
  742. //
  743. g_pCurrentBuffer->pChar += cch;
  744. }
  745. else
  746. {
  747. //
  748. // Record the dropped event
  749. //
  750. g_ulDroppedEventCount += 1;
  751. }
  752. //
  753. // If there is no current IO, flush the buffer
  754. //
  755. if (FALSE == g_fIOPending)
  756. {
  757. FwpFlushCurrentBuffer();
  758. }
  759. LeaveCriticalSection(&g_FwFileLock);
  760. } // FwpConnectionCreationCallback
  761. VOID
  762. WINAPI
  763. FwpConnectionDeletionCallback(
  764. PEVENT_TRACE pEvent
  765. )
  766. /*++
  767. Routine Description:
  768. This routine is called to process a connection deletion event.
  769. Arguments:
  770. pEvent - pointer to the event structure
  771. Return Value:
  772. none.
  773. --*/
  774. {
  775. PMSIPNAT_ConnectionDeletionEvent pEventData;
  776. FILETIME ftUtcTime;
  777. SYSTEMTIME stLocalTime;
  778. PCHAR pszProtocol;
  779. CHAR szSrcAddress[16];
  780. CHAR szDstAddress[16];
  781. USHORT usSrcPort;
  782. USHORT usDstPort;
  783. int cch;
  784. EnterCriticalSection(&g_FwFileLock);
  785. //
  786. // Get a buffer to write to.
  787. //
  788. if (NULL == g_pCurrentBuffer)
  789. {
  790. if (NULL == g_pReserveBuffer)
  791. {
  792. if (ERROR_SUCCESS != FwpAllocateBuffer(&g_pCurrentBuffer))
  793. {
  794. NhTrace(
  795. TRACE_FLAG_FWLOG,
  796. "FwpConnectionDeletionCallback: Unable to allocate buffer"
  797. );
  798. //
  799. // Record the dropped event
  800. //
  801. g_ulDroppedEventCount += 1;
  802. LeaveCriticalSection(&g_FwFileLock);
  803. return;
  804. }
  805. }
  806. else
  807. {
  808. g_pCurrentBuffer = g_pReserveBuffer;
  809. g_pReserveBuffer = NULL;
  810. }
  811. }
  812. ASSERT(NULL != g_pCurrentBuffer);
  813. //
  814. // Crack logging data
  815. //
  816. pEventData = (PMSIPNAT_ConnectionDeletionEvent) pEvent->MofData;
  817. ftUtcTime.dwLowDateTime = pEvent->Header.TimeStamp.LowPart;
  818. ftUtcTime.dwHighDateTime = pEvent->Header.TimeStamp.HighPart;
  819. FwpConvertUtcFiletimeToLocalSystemtime(&ftUtcTime, &stLocalTime);
  820. if (pEventData->InboundConnection)
  821. {
  822. lstrcpyA(szSrcAddress, INET_NTOA(pEventData->RemoteAddress));
  823. usSrcPort = ntohs(pEventData->RemotePort);
  824. lstrcpyA(szDstAddress, INET_NTOA(pEventData->LocalAddress));
  825. usDstPort = ntohs(pEventData->LocalPort);
  826. }
  827. else
  828. {
  829. lstrcpyA(szSrcAddress, INET_NTOA(pEventData->LocalAddress));
  830. usSrcPort = ntohs(pEventData->LocalPort);
  831. lstrcpyA(szDstAddress, INET_NTOA(pEventData->RemoteAddress));
  832. usDstPort = ntohs(pEventData->RemotePort);
  833. }
  834. pszProtocol =
  835. NAT_PROTOCOL_TCP == pEventData->Protocol ?
  836. c_szTcp :
  837. c_szUdp;
  838. //
  839. // Write the event data to the buffer
  840. //
  841. cch =
  842. _snprintf(
  843. g_pCurrentBuffer->pChar,
  844. FW_LOG_BUFFER_REMAINING(g_pCurrentBuffer),
  845. c_szConnectionFormat,
  846. stLocalTime.wYear,
  847. stLocalTime.wMonth,
  848. stLocalTime.wDay,
  849. stLocalTime.wHour,
  850. stLocalTime.wMinute,
  851. stLocalTime.wSecond,
  852. "CLOSE",
  853. pszProtocol,
  854. szSrcAddress,
  855. szDstAddress,
  856. usSrcPort,
  857. usDstPort
  858. );
  859. if (cch > 0)
  860. {
  861. //
  862. // Move the buffer pointer to the end of the data we just wrote.
  863. // If cch were negative, then there wasn't enough room to write
  864. // then entire entry; by not adjusting the pointer, we essentially
  865. // drop this event.
  866. //
  867. g_pCurrentBuffer->pChar += cch;
  868. }
  869. else
  870. {
  871. //
  872. // Record the dropped event
  873. //
  874. g_ulDroppedEventCount += 1;
  875. }
  876. //
  877. // If there is no current IO, flush the buffer
  878. //
  879. if (FALSE == g_fIOPending)
  880. {
  881. FwpFlushCurrentBuffer();
  882. }
  883. LeaveCriticalSection(&g_FwFileLock);
  884. } // FwpConnectionDeletionCallback
  885. VOID
  886. FwpConvertUtcFiletimeToLocalSystemtime(
  887. FILETIME *pFiletime,
  888. SYSTEMTIME *pSystemtime
  889. )
  890. /*++
  891. Routine Description:
  892. Converts UTC time in a FILETIME struct to local time in
  893. a SYSTEMTIME struct
  894. Arguments:
  895. pFiletime - pointer to UTC filetime structure
  896. pSystemtime - pointer to systemtime structure that is to receive
  897. the local time
  898. Return Value:
  899. none.
  900. --*/
  901. {
  902. FILETIME ftLocalTime;
  903. ASSERT(NULL != pFiletime);
  904. ASSERT(NULL != pSystemtime);
  905. if (!FileTimeToLocalFileTime(pFiletime, &ftLocalTime)
  906. || !FileTimeToSystemTime(&ftLocalTime, pSystemtime))
  907. {
  908. //
  909. // Conversion failed -- use zero time
  910. //
  911. ZeroMemory( pSystemtime, sizeof(*pSystemtime));
  912. }
  913. } // FwpConvertUtcFiletimeToLocalSystemtime
  914. VOID
  915. CALLBACK
  916. FwpDroppedEventTimerRoutine(
  917. PVOID pvParameter,
  918. BOOLEAN fWaitTimeout
  919. )
  920. /*++
  921. Routine Description:
  922. Checks if there are any dropped events, and, if so, writes
  923. an event to the log.
  924. Arguments:
  925. pvParameter -- NULL if called by the timer. If called directly, a PULONG
  926. to the number of events dropped by WMI. In the later situation, this
  927. routine will not query the trace session for the number of dropped
  928. events.
  929. fWaitTimeout -- unused
  930. Return Value:
  931. none.
  932. --*/
  933. {
  934. ULONG ulKernelEvents = 0;
  935. PEVENT_TRACE_PROPERTIES pProperties;
  936. SYSTEMTIME stLocalTime;
  937. DWORD dwError;
  938. int cch;
  939. EnterCriticalSection(&g_FwFileLock);
  940. //
  941. // Check to see if we we're given the kernel mode drop count, as
  942. // would happen during shutdown
  943. //
  944. if (NULL != pvParameter)
  945. {
  946. ulKernelEvents = *((PULONG)pvParameter);
  947. }
  948. else
  949. {
  950. //
  951. // Query the trace session for number of events dropped
  952. // in kernel mode. If g_hSession is NULL, then we are shutting
  953. // down and should exit w/o logging -- this call is the result
  954. // of the timer firing after FwStopLogging has stopped the
  955. // trace session.
  956. //
  957. EnterCriticalSection(&g_FwLock);
  958. if (NULL != g_hSession)
  959. {
  960. pProperties = FwpAllocateTraceProperties();
  961. if (NULL != pProperties)
  962. {
  963. dwError =
  964. ControlTrace(
  965. g_hSession,
  966. NULL,
  967. pProperties,
  968. EVENT_TRACE_CONTROL_QUERY
  969. );
  970. if (ERROR_SUCCESS == dwError)
  971. {
  972. ulKernelEvents = pProperties->EventsLost;
  973. }
  974. else
  975. {
  976. NhTrace(
  977. TRACE_FLAG_FWLOG,
  978. "FwpDroppedEventTimerRoutine: ControlTrace = %d",
  979. dwError
  980. );
  981. }
  982. HeapFree(GetProcessHeap(), 0, pProperties);
  983. }
  984. }
  985. else
  986. {
  987. //
  988. // Timer callback after trace session stopped - exit
  989. //
  990. LeaveCriticalSection(&g_FwLock);
  991. LeaveCriticalSection(&g_FwFileLock);
  992. return;
  993. }
  994. LeaveCriticalSection(&g_FwLock);
  995. }
  996. //
  997. // Record the dropped events, if there are any
  998. //
  999. if (ulKernelEvents > g_ulKernelEventsLost
  1000. || g_ulDroppedEventCount > 0)
  1001. {
  1002. //
  1003. // Get a buffer to write to.
  1004. //
  1005. if (NULL == g_pCurrentBuffer)
  1006. {
  1007. if (NULL == g_pReserveBuffer)
  1008. {
  1009. if (ERROR_SUCCESS != FwpAllocateBuffer(&g_pCurrentBuffer))
  1010. {
  1011. NhTrace(
  1012. TRACE_FLAG_FWLOG,
  1013. "FwpDroppedEventTimerRoutine: Unable to allocate buffer"
  1014. );
  1015. LeaveCriticalSection(&g_FwFileLock);
  1016. return;
  1017. }
  1018. }
  1019. else
  1020. {
  1021. g_pCurrentBuffer = g_pReserveBuffer;
  1022. g_pReserveBuffer = NULL;
  1023. }
  1024. }
  1025. ASSERT(NULL != g_pCurrentBuffer);
  1026. //
  1027. // Get the current time
  1028. //
  1029. GetLocalTime(&stLocalTime);
  1030. //
  1031. // Write the dropped packet event to the buffer. The actual number of
  1032. // dropped events that we're logging is:
  1033. //
  1034. // ulKernelEvents - g_ulKernelEventsLost + g_ulDroppedEventCount
  1035. //
  1036. cch =
  1037. _snprintf(
  1038. g_pCurrentBuffer->pChar,
  1039. FW_LOG_BUFFER_REMAINING(g_pCurrentBuffer),
  1040. c_szEventsLostFormat,
  1041. stLocalTime.wYear,
  1042. stLocalTime.wMonth,
  1043. stLocalTime.wDay,
  1044. stLocalTime.wHour,
  1045. stLocalTime.wMinute,
  1046. stLocalTime.wSecond,
  1047. ulKernelEvents - g_ulKernelEventsLost + g_ulDroppedEventCount
  1048. );
  1049. if (cch > 0)
  1050. {
  1051. //
  1052. // Move the buffer pointer to the end of the data we just wrote.
  1053. // If cch were negative, then there wasn't enough room to write
  1054. // then entire entry; by not adjusting the pointer, we essentially
  1055. // drop this event.
  1056. //
  1057. g_pCurrentBuffer->pChar += cch;
  1058. //
  1059. // Adjust the dropped event counter
  1060. //
  1061. g_ulKernelEventsLost = ulKernelEvents;
  1062. g_ulDroppedEventCount = 0;
  1063. }
  1064. else
  1065. {
  1066. //
  1067. // This doesn't count as a dropped event.
  1068. //
  1069. }
  1070. //
  1071. // If there is no current IO, flush the buffer
  1072. //
  1073. if (FALSE == g_fIOPending)
  1074. {
  1075. FwpFlushCurrentBuffer();
  1076. }
  1077. }
  1078. LeaveCriticalSection(&g_FwFileLock);
  1079. } // FwpDroppedEventTimerRoutine
  1080. DWORD
  1081. FwpFlushCurrentBuffer(
  1082. VOID
  1083. )
  1084. /*++
  1085. Routine Description:
  1086. Writes the current buffer to disk.
  1087. Arguments:
  1088. none.
  1089. Return Value:
  1090. DWORD - Win32 error code
  1091. --*/
  1092. {
  1093. DWORD dwError;
  1094. DWORD dwBytesWritten;
  1095. DWORD dwBytesToWrite;
  1096. BOOL fResult;
  1097. EnterCriticalSection(&g_FwFileLock);
  1098. ASSERT(FALSE == g_fIOPending);
  1099. ASSERT(NULL != g_pCurrentBuffer);
  1100. ASSERT(0 == g_pCurrentBuffer->Overlapped.Internal);
  1101. ASSERT(0 == g_pCurrentBuffer->Overlapped.InternalHigh);
  1102. ASSERT(0 == g_pCurrentBuffer->Overlapped.Offset);
  1103. ASSERT(0 == g_pCurrentBuffer->Overlapped.OffsetHigh);
  1104. ASSERT(0 == g_pCurrentBuffer->Overlapped.hEvent);
  1105. g_pCurrentBuffer->Overlapped.Offset = g_dwFileOffset;
  1106. dwBytesToWrite = (DWORD)(g_pCurrentBuffer->pChar - g_pCurrentBuffer->Buffer);
  1107. fResult =
  1108. WriteFile(
  1109. g_hFile,
  1110. g_pCurrentBuffer->Buffer,
  1111. dwBytesToWrite,
  1112. &dwBytesWritten,
  1113. &g_pCurrentBuffer->Overlapped
  1114. );
  1115. dwError = GetLastError();
  1116. if (FALSE != fResult || ERROR_IO_PENDING == dwError)
  1117. {
  1118. //
  1119. // The write succeeded or is pending; our completion routine
  1120. // is therefore guaranteed to be called.
  1121. //
  1122. g_fIOPending = TRUE;
  1123. g_pCurrentBuffer = g_pReserveBuffer;
  1124. g_pReserveBuffer = NULL;
  1125. }
  1126. else
  1127. {
  1128. //
  1129. // Unexpected error. Reset the buffer for future use.
  1130. //
  1131. NhTrace(
  1132. TRACE_FLAG_FWLOG,
  1133. "FwpFlushCurrentBuffer: WriteFile = %d",
  1134. dwError
  1135. );
  1136. ZeroMemory(&g_pCurrentBuffer->Overlapped, sizeof(OVERLAPPED));
  1137. g_pCurrentBuffer->pChar = g_pCurrentBuffer->Buffer;
  1138. }
  1139. LeaveCriticalSection(&g_FwFileLock);
  1140. return dwError;
  1141. } // FwpFlushCurrentBuffer
  1142. DWORD
  1143. FwpOpenLogFile(
  1144. HANDLE *phFile,
  1145. BOOLEAN *pfNewFile
  1146. )
  1147. /*++
  1148. Routine Description:
  1149. Opens the file used for logging and associates it with the thread pool's
  1150. IO completion port.
  1151. Arguments:
  1152. phFile - receives the file handle for the opened log file.
  1153. pfNewFile - receives TRUE if a new file was created; false otherwise
  1154. Return Value:
  1155. DWORD - Win32 error code
  1156. --*/
  1157. {
  1158. DWORD dwError;
  1159. DWORD dwFileSize;
  1160. ASSERT(NULL != phFile);
  1161. ASSERT(NULL != pfNewFile);
  1162. EnterCriticalSection(&g_FwLock);
  1163. ASSERT(NULL != g_pSettings);
  1164. ASSERT(NULL != g_pSettings->pszwPath);
  1165. *pfNewFile = FALSE;
  1166. dwError = ERROR_SUCCESS;
  1167. *phFile =
  1168. CreateFile(
  1169. g_pSettings->pszwPath,
  1170. GENERIC_READ | GENERIC_WRITE,
  1171. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1172. NULL,
  1173. OPEN_ALWAYS,
  1174. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  1175. NULL
  1176. );
  1177. if (INVALID_HANDLE_VALUE != *phFile)
  1178. {
  1179. //
  1180. // Check if this is a new or existing file
  1181. //
  1182. if (ERROR_ALREADY_EXISTS == GetLastError())
  1183. {
  1184. //
  1185. // Check to see if existing file size is > 95% of
  1186. // our max; if so, backup now and create new file
  1187. //
  1188. dwFileSize = GetFileSize(*phFile, NULL);
  1189. if ((DWORD)-1 == dwFileSize)
  1190. {
  1191. //
  1192. // Unable to get file size. This is quite unexpected...
  1193. //
  1194. dwError = GetLastError();
  1195. CloseHandle(*phFile);
  1196. *phFile = INVALID_HANDLE_VALUE;
  1197. NhTrace(
  1198. TRACE_FLAG_FWLOG,
  1199. "FwpOpenLogFile: GetFileSize = %d",
  1200. dwError
  1201. );
  1202. }
  1203. else if (dwFileSize > 0.95 * g_pSettings->ulMaxFileSize)
  1204. {
  1205. //
  1206. // Close the current file handle
  1207. //
  1208. CloseHandle(*phFile);
  1209. //
  1210. // Rename the current log file. This call will delete any
  1211. // previous backups. If this fails, we'll just overwrite
  1212. // the current log file.
  1213. //
  1214. FwpBackupFile(g_pSettings->pszwPath);
  1215. //
  1216. // Open again
  1217. //
  1218. *pfNewFile = TRUE;
  1219. *phFile =
  1220. CreateFile(
  1221. g_pSettings->pszwPath,
  1222. GENERIC_READ | GENERIC_WRITE,
  1223. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1224. NULL,
  1225. CREATE_ALWAYS,
  1226. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  1227. NULL
  1228. );
  1229. if (INVALID_HANDLE_VALUE == *phFile)
  1230. {
  1231. dwError = GetLastError();
  1232. NhTrace(
  1233. TRACE_FLAG_FWLOG,
  1234. "FwpOpenLogFile: Error %d creating %S after backup",
  1235. dwError,
  1236. g_pSettings->pszwPath
  1237. );
  1238. }
  1239. }
  1240. }
  1241. else
  1242. {
  1243. *pfNewFile = TRUE;
  1244. }
  1245. }
  1246. else
  1247. {
  1248. dwError = GetLastError();
  1249. NhTrace(
  1250. TRACE_FLAG_FWLOG,
  1251. "FwpOpenLogFile: Error %d opening %S",
  1252. dwError,
  1253. g_pSettings->pszwPath
  1254. );
  1255. }
  1256. if (INVALID_HANDLE_VALUE != *phFile)
  1257. {
  1258. //
  1259. // Associate the file handle w/ the thread pool completion port
  1260. //
  1261. if (!BindIoCompletionCallback(*phFile, FwpCompletionRoutine, 0))
  1262. {
  1263. dwError = GetLastError();
  1264. CloseHandle(*phFile);
  1265. *phFile = INVALID_HANDLE_VALUE;
  1266. }
  1267. }
  1268. LeaveCriticalSection(&g_FwLock);
  1269. return dwError;
  1270. } // FwpOpenLogFile
  1271. VOID
  1272. WINAPI
  1273. FwpPacketDroppedCallback(
  1274. PEVENT_TRACE pEvent
  1275. )
  1276. /*++
  1277. Routine Description:
  1278. This routine is called to process a dropped packet event.
  1279. Arguments:
  1280. pEvent - pointer to the event structure
  1281. Return Value:
  1282. none.
  1283. --*/
  1284. {
  1285. PMSIPNAT_PacketDroppedEvent pEventData;
  1286. FILETIME ftUtcTime;
  1287. SYSTEMTIME stLocalTime;
  1288. CHAR szSrcAddress[16];
  1289. CHAR szDstAddress[16];
  1290. int cch;
  1291. EnterCriticalSection(&g_FwFileLock);
  1292. //
  1293. // Get a buffer to write to.
  1294. //
  1295. if (NULL == g_pCurrentBuffer)
  1296. {
  1297. if (NULL == g_pReserveBuffer)
  1298. {
  1299. if (ERROR_SUCCESS != FwpAllocateBuffer(&g_pCurrentBuffer))
  1300. {
  1301. NhTrace(
  1302. TRACE_FLAG_FWLOG,
  1303. "FwpPacketDroppedCallback: Unable to allocate buffer"
  1304. );
  1305. //
  1306. // Record the dropped event
  1307. //
  1308. g_ulDroppedEventCount += 1;
  1309. LeaveCriticalSection(&g_FwFileLock);
  1310. return;
  1311. }
  1312. }
  1313. else
  1314. {
  1315. g_pCurrentBuffer = g_pReserveBuffer;
  1316. g_pReserveBuffer = NULL;
  1317. }
  1318. }
  1319. ASSERT(NULL != g_pCurrentBuffer);
  1320. //
  1321. // Crack logging data
  1322. //
  1323. pEventData = (PMSIPNAT_PacketDroppedEvent) pEvent->MofData;
  1324. ftUtcTime.dwLowDateTime = pEvent->Header.TimeStamp.LowPart;
  1325. ftUtcTime.dwHighDateTime = pEvent->Header.TimeStamp.HighPart;
  1326. FwpConvertUtcFiletimeToLocalSystemtime(&ftUtcTime, &stLocalTime);
  1327. lstrcpyA(szSrcAddress, INET_NTOA(pEventData->SourceAddress));
  1328. lstrcpyA(szDstAddress, INET_NTOA(pEventData->DestinationAddress));
  1329. //
  1330. // Write the event data to the buffer
  1331. //
  1332. if (NAT_PROTOCOL_TCP == pEventData->Protocol)
  1333. {
  1334. CHAR szBuffer[10];
  1335. UINT i = 0;
  1336. if (pEventData->ProtocolData4 & TCP_FLAG_SYN)
  1337. {
  1338. szBuffer[i++] = 'S';
  1339. }
  1340. if (pEventData->ProtocolData4 & TCP_FLAG_FIN)
  1341. {
  1342. szBuffer[i++] = 'F';
  1343. }
  1344. if (pEventData->ProtocolData4 & TCP_FLAG_ACK)
  1345. {
  1346. szBuffer[i++] = 'A';
  1347. }
  1348. if (pEventData->ProtocolData4 & TCP_FLAG_RST)
  1349. {
  1350. szBuffer[i++] = 'R';
  1351. }
  1352. if (pEventData->ProtocolData4 & TCP_FLAG_URG)
  1353. {
  1354. szBuffer[i++] = 'U';
  1355. }
  1356. if (pEventData->ProtocolData4 & TCP_FLAG_PSH)
  1357. {
  1358. szBuffer[i++] = 'P';
  1359. }
  1360. if (0 == i)
  1361. {
  1362. //
  1363. // No flags on this packet
  1364. //
  1365. szBuffer[i++] = '-';
  1366. }
  1367. szBuffer[i] = NULL;
  1368. cch =
  1369. _snprintf(
  1370. g_pCurrentBuffer->pChar,
  1371. FW_LOG_BUFFER_REMAINING(g_pCurrentBuffer),
  1372. c_szTcpPacketFormat,
  1373. stLocalTime.wYear,
  1374. stLocalTime.wMonth,
  1375. stLocalTime.wDay,
  1376. stLocalTime.wHour,
  1377. stLocalTime.wMinute,
  1378. stLocalTime.wSecond,
  1379. szSrcAddress,
  1380. szDstAddress,
  1381. ntohs(pEventData->SourceIdentifier),
  1382. ntohs(pEventData->DestinationIdentifier),
  1383. pEventData->PacketSize,
  1384. szBuffer,
  1385. ntohl(pEventData->ProtocolData1),
  1386. ntohl(pEventData->ProtocolData2),
  1387. ntohs((USHORT)pEventData->ProtocolData3)
  1388. );
  1389. }
  1390. else if (NAT_PROTOCOL_UDP == pEventData->Protocol)
  1391. {
  1392. cch =
  1393. _snprintf(
  1394. g_pCurrentBuffer->pChar,
  1395. FW_LOG_BUFFER_REMAINING(g_pCurrentBuffer),
  1396. c_szUdpPacketFormat,
  1397. stLocalTime.wYear,
  1398. stLocalTime.wMonth,
  1399. stLocalTime.wDay,
  1400. stLocalTime.wHour,
  1401. stLocalTime.wMinute,
  1402. stLocalTime.wSecond,
  1403. szSrcAddress,
  1404. szDstAddress,
  1405. ntohs(pEventData->SourceIdentifier),
  1406. ntohs(pEventData->DestinationIdentifier),
  1407. pEventData->PacketSize
  1408. );
  1409. }
  1410. else if (NAT_PROTOCOL_ICMP == pEventData->Protocol)
  1411. {
  1412. cch =
  1413. _snprintf(
  1414. g_pCurrentBuffer->pChar,
  1415. FW_LOG_BUFFER_REMAINING(g_pCurrentBuffer),
  1416. c_szIcmpPacketFormat,
  1417. stLocalTime.wYear,
  1418. stLocalTime.wMonth,
  1419. stLocalTime.wDay,
  1420. stLocalTime.wHour,
  1421. stLocalTime.wMinute,
  1422. stLocalTime.wSecond,
  1423. szSrcAddress,
  1424. szDstAddress,
  1425. pEventData->PacketSize,
  1426. pEventData->ProtocolData1,
  1427. pEventData->ProtocolData2
  1428. );
  1429. }
  1430. else
  1431. {
  1432. cch =
  1433. _snprintf(
  1434. g_pCurrentBuffer->pChar,
  1435. FW_LOG_BUFFER_REMAINING(g_pCurrentBuffer),
  1436. c_szDroppedPacketFormat,
  1437. stLocalTime.wYear,
  1438. stLocalTime.wMonth,
  1439. stLocalTime.wDay,
  1440. stLocalTime.wHour,
  1441. stLocalTime.wMinute,
  1442. stLocalTime.wSecond,
  1443. pEventData->Protocol,
  1444. szSrcAddress,
  1445. szDstAddress,
  1446. pEventData->PacketSize
  1447. );
  1448. }
  1449. if (cch > 0)
  1450. {
  1451. //
  1452. // Move the buffer pointer to the end of the data we just wrote.
  1453. // If cch were negative, then there wasn't enough room to write
  1454. // then entire entry; by not adjusting the pointer, we essentially
  1455. // drop this event.
  1456. //
  1457. g_pCurrentBuffer->pChar += cch;
  1458. }
  1459. else
  1460. {
  1461. //
  1462. // Record the dropped event
  1463. //
  1464. g_ulDroppedEventCount += 1;
  1465. }
  1466. //
  1467. // If there is no current IO, flush the buffer
  1468. //
  1469. if (FALSE == g_fIOPending)
  1470. {
  1471. FwpFlushCurrentBuffer();
  1472. }
  1473. LeaveCriticalSection(&g_FwFileLock);
  1474. } // FwpPacketDroppedCallback
  1475. DWORD
  1476. FwpLaunchTraceSession(
  1477. HNET_FW_LOGGING_SETTINGS *pSettings,
  1478. TRACEHANDLE *phSession
  1479. )
  1480. /*++
  1481. Routine Description:
  1482. This routine is called to start a trace session.
  1483. Arguments:
  1484. pSettings - pointer to an fw logging settings structure. Only
  1485. fLogDroppedPackets and fLogConnections are examined,
  1486. and at least one of the two must be true.
  1487. phSession - on success, receives the trace handle for the session
  1488. Return Value:
  1489. DWORD -- win32 error code
  1490. --*/
  1491. {
  1492. DWORD dwError;
  1493. PEVENT_TRACE_PROPERTIES pProperties = NULL;
  1494. PROFILE("FwpLaunchTraceSession");
  1495. ASSERT(NULL != pSettings);
  1496. ASSERT(pSettings->fLogDroppedPackets || pSettings->fLogConnections);
  1497. ASSERT(NULL != phSession);
  1498. do
  1499. {
  1500. //
  1501. // Allocate the tracing properties. We need to include space for
  1502. // the name of the logging session, even though we don't have
  1503. // to copy the string into the properties ourselves
  1504. //
  1505. pProperties = FwpAllocateTraceProperties();
  1506. if (NULL == pProperties)
  1507. {
  1508. dwError = ERROR_NOT_ENOUGH_MEMORY;
  1509. break;
  1510. }
  1511. //
  1512. // Initialize the trace properties. When events are coming at a
  1513. // low rate (which is expected), there will be at most a 13 second
  1514. // latency for event delivery. During high event rate periods, our
  1515. // memory usage for trace buffering is capped at 60k.
  1516. //
  1517. pProperties->FlushTimer = 13;
  1518. pProperties->BufferSize = 4;
  1519. pProperties->MaximumBuffers = 15;
  1520. //
  1521. // Start the trace
  1522. //
  1523. dwError = StartTrace(phSession, c_wszLogSessionName, pProperties);
  1524. if (ERROR_SUCCESS != dwError)
  1525. {
  1526. NhTrace(
  1527. TRACE_FLAG_FWLOG,
  1528. "FwpLaunchTraceSession: StartTrace = %d",
  1529. dwError
  1530. );
  1531. *phSession = NULL;
  1532. break;
  1533. }
  1534. //
  1535. // Enable the appropriate events
  1536. //
  1537. if (pSettings->fLogDroppedPackets)
  1538. {
  1539. dwError = EnableTrace(
  1540. TRUE,
  1541. 0,
  1542. 0,
  1543. &c_PacketDroppedEventGuid,
  1544. *phSession
  1545. );
  1546. if (ERROR_SUCCESS != dwError)
  1547. {
  1548. NhTrace(
  1549. TRACE_FLAG_FWLOG,
  1550. "FwpLaunchTraceSession: EnableTrace (packets) = %d",
  1551. dwError
  1552. );
  1553. //
  1554. // Stop the trace
  1555. //
  1556. ControlTrace(
  1557. *phSession,
  1558. NULL,
  1559. pProperties,
  1560. EVENT_TRACE_CONTROL_STOP
  1561. );
  1562. *phSession = NULL;
  1563. break;
  1564. }
  1565. }
  1566. if (pSettings->fLogConnections)
  1567. {
  1568. dwError = EnableTrace(
  1569. TRUE,
  1570. 0,
  1571. 0,
  1572. &c_ConnectionCreationEventGuid,
  1573. *phSession
  1574. );
  1575. if (ERROR_SUCCESS != dwError)
  1576. {
  1577. NhTrace(
  1578. TRACE_FLAG_FWLOG,
  1579. "FwpLaunchTraceSession: EnableTrace (connections) = %d",
  1580. dwError
  1581. );
  1582. //
  1583. // Stop the trace
  1584. //
  1585. ControlTrace(
  1586. *phSession,
  1587. NULL,
  1588. pProperties,
  1589. EVENT_TRACE_CONTROL_STOP
  1590. );
  1591. *phSession = NULL;
  1592. break;
  1593. }
  1594. }
  1595. } while (FALSE);
  1596. if (NULL != pProperties)
  1597. {
  1598. HeapFree(GetProcessHeap(), 0, pProperties);
  1599. }
  1600. return dwError;
  1601. } // FwpLaunchTraceSession
  1602. HRESULT
  1603. FwpLoadSettings(
  1604. HNET_FW_LOGGING_SETTINGS **ppSettings
  1605. )
  1606. /*++
  1607. Routine Description:
  1608. This routine is called to retrieve the firewall logging settings.
  1609. Arguments:
  1610. ppSettings - receives a pointer to the settings structure on success.
  1611. The caller is responsible for calling
  1612. HNetFreeFirewallLoggingSettings on this pointer.
  1613. Return Value:
  1614. standard HRESULT
  1615. --*/
  1616. {
  1617. HRESULT hr = S_OK;
  1618. IHNetCfgMgr *pCfgMgr;
  1619. IHNetFirewallSettings *pFwSettings;
  1620. PROFILE("FwpLoadSettings");
  1621. ASSERT(NULL != ppSettings);
  1622. hr = NhGetHNetCfgMgr(&pCfgMgr);
  1623. if (SUCCEEDED(hr))
  1624. {
  1625. hr = pCfgMgr->QueryInterface(
  1626. IID_PPV_ARG(IHNetFirewallSettings, &pFwSettings)
  1627. );
  1628. pCfgMgr->Release();
  1629. if (SUCCEEDED(hr))
  1630. {
  1631. hr = pFwSettings->GetFirewallLoggingSettings(ppSettings);
  1632. pFwSettings->Release();
  1633. if (SUCCEEDED(hr))
  1634. {
  1635. //
  1636. // Make sure that the minimum file size is at least 1024 bytes.
  1637. //
  1638. if ((*ppSettings)->ulMaxFileSize < 1024)
  1639. {
  1640. (*ppSettings)->ulMaxFileSize = 1024;
  1641. }
  1642. }
  1643. else
  1644. {
  1645. NhTrace(
  1646. TRACE_FLAG_FWLOG,
  1647. "FwpLoadSettings: GetFirewallLoggingSettings = 0x%08x",
  1648. hr
  1649. );
  1650. }
  1651. }
  1652. else
  1653. {
  1654. NhTrace(
  1655. TRACE_FLAG_FWLOG,
  1656. "FwpLoadSettings: QueryInterface = 0x%08x",
  1657. hr
  1658. );
  1659. }
  1660. }
  1661. else
  1662. {
  1663. NhTrace(
  1664. TRACE_FLAG_FWLOG,
  1665. "FwpLoadSettings: NhGetHNetCfgMgr = 0x%08x",
  1666. hr
  1667. );
  1668. }
  1669. return hr;
  1670. } // FwpLoadSettings
  1671. DWORD
  1672. WINAPI
  1673. FwpTraceProcessingThreadRoutine(
  1674. LPVOID pvParam
  1675. )
  1676. /*++
  1677. Routine Description:
  1678. This routine is the entrypoint for our trace processing thread. It
  1679. does the following:
  1680. 1) Creates the file that we are logging to
  1681. 2) Sets up the trace callback routines
  1682. 3) Calls ProcessTrace. This call blocks until the trace session is
  1683. finished (i.e,, FwStopLogging is called)
  1684. Arguments:
  1685. pvParam - unused
  1686. Return Value:
  1687. DWORD - Win32 error code
  1688. --*/
  1689. {
  1690. TRACEHANDLE hTraceSession;
  1691. EVENT_TRACE_LOGFILE LogFile;
  1692. BOOLEAN fNewFile;
  1693. DWORD dwError;
  1694. BOOL fSucceeded;
  1695. ULONG ulKernelEventsLostAtShutdown;
  1696. PROFILE("FwpTraceProcessingThreadRoutine");
  1697. EnterCriticalSection(&g_FwFileLock);
  1698. ASSERT(INVALID_HANDLE_VALUE == g_hFile);
  1699. ASSERT(0 == g_dwFileOffset);
  1700. ASSERT(NULL == g_pCurrentBuffer);
  1701. ASSERT(NULL == g_pReserveBuffer);
  1702. ASSERT(FALSE == g_fIOPending);
  1703. ASSERT(NULL == g_hIOEvent);
  1704. ASSERT(0 == g_ulDroppedEventCount);
  1705. ASSERT(NULL == g_hDroppedEventTimer);
  1706. ASSERT(0 == g_ulKernelEventsLost);
  1707. do
  1708. {
  1709. //
  1710. // Create/Open the logfile.
  1711. //
  1712. dwError = FwpOpenLogFile(&g_hFile, &fNewFile);
  1713. if (ERROR_SUCCESS != dwError)
  1714. {
  1715. LeaveCriticalSection(&g_FwFileLock);
  1716. break;
  1717. }
  1718. //
  1719. // Allocate the initial working buffer
  1720. //
  1721. dwError = FwpAllocateBuffer(&g_pCurrentBuffer);
  1722. if (ERROR_SUCCESS != dwError)
  1723. {
  1724. LeaveCriticalSection(&g_FwFileLock);
  1725. NhTrace(
  1726. TRACE_FLAG_FWLOG,
  1727. "FwpTraceProcessingRoutine: Unable to allocate buffer"
  1728. );
  1729. break;
  1730. }
  1731. if (fNewFile)
  1732. {
  1733. //
  1734. // Write the log header
  1735. //
  1736. g_dwFileOffset = 0;
  1737. dwError = FwpWriteLogHeaderToBuffer(g_pCurrentBuffer);
  1738. if (ERROR_SUCCESS == dwError)
  1739. {
  1740. FwpFlushCurrentBuffer();
  1741. }
  1742. else
  1743. {
  1744. //
  1745. // Even though we failed in writing the header, we'll still
  1746. // try to log as much as possible
  1747. //
  1748. NhTrace(
  1749. TRACE_FLAG_FWLOG,
  1750. "FwpTraceProcessinRoutine: FwpWriteLogHeaderToBuffer = %d",
  1751. dwError
  1752. );
  1753. }
  1754. }
  1755. else
  1756. {
  1757. //
  1758. // Find the end-of-file position
  1759. //
  1760. g_dwFileOffset = GetFileSize(g_hFile, NULL);
  1761. if ((DWORD)-1 == g_dwFileOffset)
  1762. {
  1763. NhTrace(
  1764. TRACE_FLAG_FWLOG,
  1765. "FwpTraceProcessingRoutine: GetFileSize = %d",
  1766. GetLastError()
  1767. );
  1768. LeaveCriticalSection(&g_FwFileLock);
  1769. break;
  1770. }
  1771. }
  1772. //
  1773. // Launch our dropped event timer. When this timer fires,
  1774. // the callback routine will check if any events have
  1775. // been dropped (both in kernel mode and user mode),
  1776. // and, if so, log that fact.
  1777. //
  1778. fSucceeded =
  1779. CreateTimerQueueTimer(
  1780. &g_hDroppedEventTimer,
  1781. NULL,
  1782. FwpDroppedEventTimerRoutine,
  1783. NULL,
  1784. 0,
  1785. 1000 * 60 * 5, // 5 minutes
  1786. 0
  1787. );
  1788. if (FALSE == fSucceeded)
  1789. {
  1790. //
  1791. // Even though we weren't able to create the timer,
  1792. // we'll still try to log as much as possible.
  1793. //
  1794. NhTrace(
  1795. TRACE_FLAG_FWLOG,
  1796. "FwpTraceProcessinRoutine: CreateTimerQueueTimer = %d",
  1797. GetLastError()
  1798. );
  1799. }
  1800. LeaveCriticalSection(&g_FwFileLock);
  1801. //
  1802. // Register our callback routines. We will attempt to continue
  1803. // even if errors occur here.
  1804. //
  1805. dwError = SetTraceCallback(
  1806. &c_PacketDroppedEventGuid,
  1807. FwpPacketDroppedCallback
  1808. );
  1809. if (ERROR_SUCCESS != dwError)
  1810. {
  1811. NhTrace(
  1812. TRACE_FLAG_FWLOG,
  1813. "FwpTraceProcessingThreadRoutine: SetTraceCallback (packets dropped) = %d",
  1814. dwError
  1815. );
  1816. }
  1817. dwError = SetTraceCallback(
  1818. &c_ConnectionCreationEventGuid,
  1819. FwpConnectionCreationCallback
  1820. );
  1821. if (ERROR_SUCCESS != dwError)
  1822. {
  1823. NhTrace(
  1824. TRACE_FLAG_FWLOG,
  1825. "FwpTraceProcessingThreadRoutine: SetTraceCallback (connection creation) = %d",
  1826. dwError
  1827. );
  1828. }
  1829. dwError = SetTraceCallback(
  1830. &c_ConnectionDeletionEventGuid,
  1831. FwpConnectionDeletionCallback
  1832. );
  1833. if (ERROR_SUCCESS != dwError)
  1834. {
  1835. NhTrace(
  1836. TRACE_FLAG_FWLOG,
  1837. "FwpTraceProcessingThreadRoutine: SetTraceCallback (connection deletion) = %d",
  1838. dwError
  1839. );
  1840. }
  1841. //
  1842. // Open the trace stream
  1843. //
  1844. ZeroMemory(&LogFile, sizeof(LogFile));
  1845. LogFile.LoggerName = c_wszLogSessionName;
  1846. LogFile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  1847. hTraceSession = OpenTrace(&LogFile);
  1848. if ((TRACEHANDLE)INVALID_HANDLE_VALUE == hTraceSession)
  1849. {
  1850. NhTrace(
  1851. TRACE_FLAG_FWLOG,
  1852. "FwpTraceProcessingThreadRoutine: OpenTrace = %d",
  1853. GetLastError()
  1854. );
  1855. break;
  1856. }
  1857. //
  1858. // Start processing the trace stream. This call will block until
  1859. // the trace session is closed (i.e., FwStopLogging is called).
  1860. //
  1861. dwError = ProcessTrace(&hTraceSession, 1, NULL, NULL);
  1862. NhTrace(
  1863. TRACE_FLAG_FWLOG,
  1864. "FwpTraceProcessingThreadRoutine: ProcessTrace = %d",
  1865. dwError
  1866. );
  1867. dwError = CloseTrace(hTraceSession);
  1868. if (ERROR_SUCCESS != dwError)
  1869. {
  1870. NhTrace(
  1871. TRACE_FLAG_FWLOG,
  1872. "FwpTraceProcessingThreadRoutine: CloseTrace = %d",
  1873. dwError
  1874. );
  1875. }
  1876. } while (FALSE);
  1877. //
  1878. // Make sure that all dropped events are properly logged
  1879. //
  1880. EnterCriticalSection(&g_FwLock);
  1881. ulKernelEventsLostAtShutdown = g_ulKernelEventsLostAtShutdown;
  1882. LeaveCriticalSection(&g_FwLock);
  1883. //
  1884. // Since we're shutting down, we pass in the number of lost kernel
  1885. // events. This will prevent the timer routine from attempting to
  1886. // query the stopped trace session
  1887. //
  1888. FwpDroppedEventTimerRoutine((PVOID)&ulKernelEventsLostAtShutdown, FALSE);
  1889. //
  1890. // Cleanup tracing thread resources
  1891. //
  1892. FwpCleanupTraceThreadResources();
  1893. return dwError;
  1894. } // FwpTraceProcessingThreadRoutine
  1895. DWORD
  1896. FwpWriteLogHeaderToBuffer(
  1897. PFW_LOG_BUFFER pBuffer
  1898. )
  1899. /*++
  1900. Routine Description:
  1901. Writes the log file header to the passed in buffer
  1902. Arguments:
  1903. pBuffer - the buffer to write the header to.
  1904. Return Value:
  1905. DWORD - Win32 error
  1906. --*/
  1907. {
  1908. DWORD dwError = ERROR_SUCCESS;
  1909. DWORD dwHeaderSize;
  1910. ASSERT(NULL != pBuffer);
  1911. dwHeaderSize = lstrlenA(c_szLogFileHeader);
  1912. if (FW_LOG_BUFFER_REMAINING(pBuffer) < dwHeaderSize)
  1913. {
  1914. dwError = ERROR_INSUFFICIENT_BUFFER;
  1915. }
  1916. else
  1917. {
  1918. RtlCopyMemory(pBuffer->pChar, c_szLogFileHeader, dwHeaderSize);
  1919. pBuffer->pChar += dwHeaderSize;
  1920. }
  1921. return dwError;
  1922. } // FwpWriteLogHeaderToBuffer
  1923. VOID
  1924. FwStartLogging(
  1925. VOID
  1926. )
  1927. /*++
  1928. Routine Description:
  1929. This routine is called to start logging operations (depending on
  1930. the current logging settings). It is safe to call this routine when
  1931. logging has already started.
  1932. Arguments:
  1933. none.
  1934. Return Value:
  1935. none.
  1936. --*/
  1937. {
  1938. HRESULT hr = S_OK;
  1939. DWORD dwError;
  1940. PROFILE("FwStartLogging");
  1941. ASSERT(FwInitialized == FwpModuleState);
  1942. EnterCriticalSection(&g_FwLock);
  1943. g_fTracingActive = TRUE;
  1944. if (NULL == g_pSettings)
  1945. {
  1946. hr = FwpLoadSettings(&g_pSettings);
  1947. }
  1948. if (SUCCEEDED(hr))
  1949. {
  1950. if ((g_pSettings->fLogDroppedPackets || g_pSettings->fLogConnections)
  1951. && NULL == g_hSession)
  1952. {
  1953. ASSERT(NULL == g_hThread);
  1954. //
  1955. // Start the tracing session
  1956. //
  1957. dwError = FwpLaunchTraceSession(g_pSettings, &g_hSession);
  1958. if (ERROR_SUCCESS == dwError)
  1959. {
  1960. //
  1961. // Launch the trace processing thread. We're not using
  1962. // any thread-specific crt routines (e.g., strtok) so
  1963. // there's no need to call __beginthreadex
  1964. //
  1965. g_hThread = CreateThread(
  1966. NULL, // SD
  1967. 0, // stack size
  1968. FwpTraceProcessingThreadRoutine,
  1969. NULL, // thread argument
  1970. 0, // flags
  1971. NULL // thread ID
  1972. );
  1973. if (NULL == g_hThread)
  1974. {
  1975. NhTrace(
  1976. TRACE_FLAG_FWLOG,
  1977. "FwStartLogging: CreateThread = %d",
  1978. GetLastError()
  1979. );
  1980. LeaveCriticalSection(&g_FwLock);
  1981. FwStopLogging();
  1982. return;
  1983. }
  1984. }
  1985. }
  1986. }
  1987. LeaveCriticalSection(&g_FwLock);
  1988. } // FwStartLogging
  1989. VOID
  1990. FwStopLogging(
  1991. VOID
  1992. )
  1993. /*++
  1994. Routine Description:
  1995. This routine is called to stop logging operations. It is safe to call
  1996. this routine when logging is stopped.
  1997. Arguments:
  1998. none.
  1999. Return Value:
  2000. none.
  2001. Environment:
  2002. The caller must not hold g_FwFileLock or g_FwLock.
  2003. --*/
  2004. {
  2005. DWORD dwError;
  2006. PEVENT_TRACE_PROPERTIES pProperties;
  2007. PROFILE("FwStopLogging");
  2008. ASSERT(FwInitialized == FwpModuleState);
  2009. EnterCriticalSection(&g_FwLock);
  2010. g_fTracingActive = FALSE;
  2011. //
  2012. // Stop the trace session if it is currently active
  2013. //
  2014. if (NULL != g_hSession)
  2015. {
  2016. pProperties = FwpAllocateTraceProperties();
  2017. if (NULL != pProperties)
  2018. {
  2019. dwError = ControlTrace(
  2020. g_hSession,
  2021. 0,
  2022. pProperties,
  2023. EVENT_TRACE_CONTROL_STOP
  2024. );
  2025. if (ERROR_SUCCESS == dwError)
  2026. {
  2027. g_hSession = NULL;
  2028. g_ulKernelEventsLostAtShutdown = pProperties->EventsLost;
  2029. if (NULL != g_hThread)
  2030. {
  2031. HANDLE hThread;
  2032. //
  2033. // Wait for thread to exit
  2034. //
  2035. hThread = g_hThread;
  2036. LeaveCriticalSection(&g_FwLock);
  2037. dwError = WaitForSingleObject(hThread, 45 * 1000);
  2038. if (WAIT_TIMEOUT == dwError)
  2039. {
  2040. NhTrace(
  2041. TRACE_FLAG_FWLOG,
  2042. "FwStopLogging: Timeout waiting for thread"
  2043. );
  2044. //
  2045. // The logging thread still hasn't exited; kill
  2046. // it hard and make sure that all resources are
  2047. // properly freed...
  2048. //
  2049. EnterCriticalSection(&g_FwFileLock);
  2050. EnterCriticalSection(&g_FwLock);
  2051. //
  2052. // TerminateThread is a very dangerous call. However,
  2053. // since we control the thread we're about to kill,
  2054. // we can guarantee that this will be safe. In
  2055. // particular, since we hold both critical sections,
  2056. // there is no danger of them being orphaned, or of
  2057. // any of our global data being in an inconsistent
  2058. // state.
  2059. //
  2060. if (!TerminateThread(g_hThread, ERROR_TIMEOUT))
  2061. {
  2062. NhTrace(
  2063. TRACE_FLAG_FWLOG,
  2064. "FwStopLogging: TerminateThread = %d",
  2065. GetLastError()
  2066. );
  2067. }
  2068. LeaveCriticalSection(&g_FwLock);
  2069. LeaveCriticalSection(&g_FwFileLock);
  2070. //
  2071. // Cleanup thread resources. It is safe to call this
  2072. // routine multiple times.
  2073. //
  2074. FwpCleanupTraceThreadResources();
  2075. }
  2076. else if (WAIT_OBJECT_0 != dwError)
  2077. {
  2078. NhTrace(
  2079. TRACE_FLAG_FWLOG,
  2080. "FwStopLogging: wait for thread = %d/%d",
  2081. dwError,
  2082. GetLastError()
  2083. );
  2084. }
  2085. EnterCriticalSection(&g_FwLock);
  2086. if (NULL != g_hThread)
  2087. {
  2088. CloseHandle(g_hThread);
  2089. }
  2090. g_hThread = NULL;
  2091. }
  2092. NhTrace(
  2093. TRACE_FLAG_FWLOG,
  2094. "FwStopLogging: Stopped w/ %d events and %d buffers lost",
  2095. pProperties->EventsLost,
  2096. pProperties->RealTimeBuffersLost
  2097. );
  2098. g_ulKernelEventsLostAtShutdown = 0;
  2099. }
  2100. else
  2101. {
  2102. NhTrace(
  2103. TRACE_FLAG_FWLOG,
  2104. "FwStopLogging: ControlTrace = %d",
  2105. dwError
  2106. );
  2107. //
  2108. // Since the trace session has not yet been stopped,
  2109. // we leave g_hSession unchanged.
  2110. //
  2111. }
  2112. HeapFree(GetProcessHeap(), 0, pProperties);
  2113. }
  2114. }
  2115. LeaveCriticalSection(&g_FwLock);
  2116. } // FwStopLogging
  2117. VOID
  2118. FwUpdateLoggingSettings(
  2119. VOID
  2120. )
  2121. /*++
  2122. Routine Description:
  2123. This routine is called to notify the logging subsystem that the
  2124. logging settings have changed.
  2125. Arguments:
  2126. none.
  2127. Return Value:
  2128. none.
  2129. --*/
  2130. {
  2131. HRESULT hr;
  2132. HNET_FW_LOGGING_SETTINGS *pSettings;
  2133. DWORD dwError;
  2134. PROFILE("FwUpdateLoggingSettings");
  2135. ASSERT(FwInitialized == FwpModuleState);
  2136. EnterCriticalSection(&g_FwLock);
  2137. do
  2138. {
  2139. if (FALSE == g_fTracingActive)
  2140. {
  2141. //
  2142. // Since tracing is not currently active, there is no
  2143. // need to retrieve the current settings. Furthermore, free
  2144. // any stored settings that we might have so that stale
  2145. // settings are not used.
  2146. //
  2147. if (g_pSettings)
  2148. {
  2149. HNetFreeFirewallLoggingSettings(g_pSettings);
  2150. g_pSettings = NULL;
  2151. }
  2152. break;
  2153. }
  2154. //
  2155. // Obtain the current settings
  2156. //
  2157. hr = FwpLoadSettings(&pSettings);
  2158. if (FAILED(hr))
  2159. {
  2160. break;
  2161. }
  2162. if (NULL == g_pSettings)
  2163. {
  2164. //
  2165. // Since we don't have any cached settings (previous failure
  2166. // in FwpLoadSettings?) simply store what we just retrieved
  2167. // and call FwStartLogging.
  2168. //
  2169. g_pSettings = pSettings;
  2170. FwStartLogging();
  2171. break;
  2172. }
  2173. if (NULL == g_hSession)
  2174. {
  2175. //
  2176. // There is no log session at the moment. Free the old settings,
  2177. // store the new ones, and call FwStartLogging.
  2178. //
  2179. ASSERT(NULL == g_hThread);
  2180. HNetFreeFirewallLoggingSettings(g_pSettings);
  2181. g_pSettings = pSettings;
  2182. FwStartLogging();
  2183. break;
  2184. }
  2185. //
  2186. // Compare the settings to see what, if anything, has changed
  2187. //
  2188. if (wcscmp(g_pSettings->pszwPath, pSettings->pszwPath))
  2189. {
  2190. //
  2191. // Our log file has changed -- we need to stop and restart
  2192. // everything so that logging is properly moved to the
  2193. // new file.
  2194. //
  2195. LeaveCriticalSection(&g_FwLock);
  2196. FwStopLogging();
  2197. EnterCriticalSection(&g_FwLock);
  2198. if (NULL != g_pSettings)
  2199. {
  2200. HNetFreeFirewallLoggingSettings(g_pSettings);
  2201. }
  2202. g_pSettings = pSettings;
  2203. FwStartLogging();
  2204. break;
  2205. }
  2206. //
  2207. // Only possible changes are to enabled events
  2208. //
  2209. if (!!g_pSettings->fLogDroppedPackets
  2210. != !!pSettings->fLogDroppedPackets)
  2211. {
  2212. dwError = EnableTrace(
  2213. pSettings->fLogDroppedPackets,
  2214. 0,
  2215. 0,
  2216. &c_PacketDroppedEventGuid,
  2217. g_hSession
  2218. );
  2219. if (ERROR_SUCCESS != dwError)
  2220. {
  2221. NhTrace(
  2222. TRACE_FLAG_FWLOG,
  2223. "FwUpdateLoggingSettings: EnableTrace (packets) = %d",
  2224. dwError
  2225. );
  2226. }
  2227. }
  2228. if (!!g_pSettings->fLogConnections
  2229. != !!pSettings->fLogConnections)
  2230. {
  2231. dwError = EnableTrace(
  2232. pSettings->fLogConnections,
  2233. 0,
  2234. 0,
  2235. &c_ConnectionCreationEventGuid,
  2236. g_hSession
  2237. );
  2238. if (ERROR_SUCCESS != dwError)
  2239. {
  2240. NhTrace(
  2241. TRACE_FLAG_FWLOG,
  2242. "FwUpdateLoggingSettings: EnableTrace (connections) = %d",
  2243. dwError
  2244. );
  2245. }
  2246. }
  2247. //
  2248. // Free old settings and store new
  2249. //
  2250. HNetFreeFirewallLoggingSettings(g_pSettings);
  2251. g_pSettings = pSettings;
  2252. } while (FALSE);
  2253. LeaveCriticalSection(&g_FwLock);
  2254. } // FwUpdateLoggingSettings