windows-nt/Source/XPSP1/NT/net/homenet/fwlogger/fwlogger.cpp

840 lines
18 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
FwLogger.cpp
Abstract:
Simple console logger for the personal firewall.
Author:
Jonathan Burstein (jonburs) 12-April-2000
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Name of the event trace session
//
_TCHAR cszLogSession[] = _T("FirewallLogSession");
//
// Event counters
//
LONG g_lDropped = 0;
LONG g_lCCreated = 0;
LONG g_lCDeleted = 0;
//
// GUIDs corresponding to the firewall trace events
//
GUID ConnectionCreationEventGuid = MSIPNAT_ConnectionCreationEventGuid;
GUID ConnectionDeletionEventGuid = MSIPNAT_ConnectionDeletionEventGuid;
GUID PacketDroppedEventGuid = MSIPNAT_PacketDroppedEventGuid;
//
// Event to signal for shutdown
//
HANDLE g_hShutdownEvent;
//
// Function prototypes
//
VOID
CALLBACK
ConnectionCreationCallback(
PEVENT_TRACE pEvent
);
VOID
CALLBACK
ConnectionDeletionCallback(
PEVENT_TRACE pEvent
);
BOOL
WINAPI
ControlHandler(
DWORD dwCtrlType
);
VOID
CALLBACK
PacketDroppedCallback(
PEVENT_TRACE pEvent
);
UINT
WINAPI
ProcessTraceRoutine(
PVOID pvThreadParam
);
int
__cdecl
main(
int argc,
_TCHAR **argv
)
/*++
Routine Description:
Program entry point. Starts the logging session and launches the
processing thread.
Arguments:
argc -- count of command line arguments.
argv -- command line arguments
Return Value:
Error code.
--*/
{
TRACEHANDLE hSession;
HANDLE hThread;
HANDLE rghWaitHandles[2];
PEVENT_TRACE_PROPERTIES pProperties;
ULONG ulError;
ULONG ulSize;
UINT uiThreadId;
BOOL fWaitForThread = FALSE;
//
// Create the event used to signal that the program should exit
//
g_hShutdownEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
if( NULL == g_hShutdownEvent )
{
_tprintf( _T("FwLogger: CreateEvent returned NULL (%08x)\n"),
GetLastError() );
return -1;
}
//
// Set our control handler. The handler will signal the shutdown event;
//
if( !SetConsoleCtrlHandler( ControlHandler, TRUE ))
{
_tprintf( _T("FwLogger: SetConsoleCtrlHandler failed (%08x)\n"),
GetLastError() );
CloseHandle( g_hShutdownEvent );
return -1;
}
//
// Initialize our trace properties and start the tracing session.
//
ulSize = sizeof(*pProperties)
+ (_tcslen( cszLogSession ) + 1) * sizeof(_TCHAR);
pProperties = (PEVENT_TRACE_PROPERTIES) HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
ulSize
);
if( NULL == pProperties )
{
_tprintf( _T("FwLogger: allocation failed\n" ));
CloseHandle( g_hShutdownEvent );
return -1;
}
pProperties->Wnode.BufferSize = ulSize;
pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
pProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
pProperties->FlushTimer = 1;
pProperties->BufferSize = 4;
ulError = StartTrace( &hSession, cszLogSession, pProperties );
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: StartTrace returned 0x%08x\n"), ulError );
CloseHandle( g_hShutdownEvent );
HeapFree( GetProcessHeap(), 0, pProperties );
return -1;
}
//
// Enable the trace control guids
//
ulError = EnableTrace(
TRUE,
0,
0,
&PacketDroppedEventGuid,
hSession
);
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: EnableTrace (PacketDropped) returned 0x%08x\n"),
ulError );
goto StopTrace;
}
ulError = EnableTrace(
TRUE,
0,
0,
&ConnectionCreationEventGuid,
hSession
);
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: EnableTrace (ConnectionCreation) returned 0x%08x\n"),
ulError );
goto StopTrace;
}
//
// Launch a thread to process the trace data. This needs to happen in a
// separate thread as ProcessTrace blocks.
//
hThread = (HANDLE) _beginthreadex(
NULL,
0,
ProcessTraceRoutine,
NULL,
0,
&uiThreadId
);
if( NULL == hThread )
{
_tprintf( _T("FwLogger: Unable to create thread (0x%08x)\n"),
GetLastError() );
goto StopTrace;
}
//
// Wait for the shutdown event to be signalled, or for our
// thread to exit.
//
rghWaitHandles[0] = g_hShutdownEvent;
rghWaitHandles[1] = hThread;
ulError = WaitForMultipleObjects( 2, rghWaitHandles, FALSE, INFINITE );
if( WAIT_OBJECT_0 == ulError )
{
//
// User wants program to finish. After we shutdownt the trace session,
// we'll need to wait for the processing thread to cleanup and exit.
//
fWaitForThread = TRUE;
_tprintf( _T("FwLogger: Shutdown event signaled\n") );
}
else if( WAIT_OBJECT_0 + 1 == ulError )
{
//
// Thread exited early, due to some problem...
//
_tprintf( _T("FwLogger: Trace process thread finished early.\n") );
}
StopTrace:
//
// Disable the events we previously enabled
//
ulError = EnableTrace(
FALSE,
0,
0,
&PacketDroppedEventGuid,
hSession
);
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: EnableTrace (PacketDropped - FALSE) returned 0x%08x\n"),
ulError );
}
ulError = EnableTrace(
FALSE,
0,
0,
&ConnectionCreationEventGuid,
hSession
);
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: EnableTrace (ConnectionCreation - FALSE) returned 0x%08x\n"),
ulError );
}
//
// Stop the trace
//
ZeroMemory( pProperties, ulSize );
pProperties->Wnode.BufferSize = ulSize;
ulError = StopTrace( hSession, NULL, pProperties );
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: StopTrace returned 0x%08x\n"), ulError );
}
else
{
_tprintf( _T("FwLogger: Trace stopped\n\n") );
//
// Print out statistics
//
_tprintf( _T("**Packets dropped: %i\n"), g_lDropped );
_tprintf( _T("**Connections created: %i\n"), g_lCCreated );
_tprintf( _T("**Connections deleted: %i\n"), g_lCDeleted );
_tprintf( _T("**Events lost: %u\n"), pProperties->EventsLost );
_tprintf( _T("**Buffers lost: %u\n"), pProperties->LogBuffersLost );
_tprintf( _T("**Realtime buffers lost: %u\n\n"),
pProperties->RealTimeBuffersLost );
}
//
// Give processing thread 15 seconds to finish
//
if( fWaitForThread )
{
_tprintf( _T("FwLogger: Waiting for thread to exit...\n") );
ulError = WaitForSingleObject( hThread, 15 * 1000 );
if( WAIT_OBJECT_0 != ulError )
{
_tprintf( _T("FwLogger: Wait failed (timeout = %s)\n"),
WAIT_TIMEOUT == ulError ? _T("true") : _T("false") );
}
}
CloseHandle( g_hShutdownEvent );
CloseHandle( hThread );
HeapFree( GetProcessHeap(), 0, pProperties );
return 0;
}
VOID
CALLBACK
ConnectionCreationCallback(
PEVENT_TRACE pEvent
)
/*++
Routine Description:
Called when a ConnectionCreationEvent occurs.
Arguments:
pEvent -- pointer to the event trace structure
Return Value:
None.
--*/
{
FILETIME ftUtcTime;
FILETIME ftLocalTime;
SYSTEMTIME stLocalTime;
PMSIPNAT_ConnectionCreationEvent pEventData;
struct in_addr inAddr;
InterlockedIncrement( &g_lCCreated );
pEventData = (PMSIPNAT_ConnectionCreationEvent) pEvent->MofData;
//
// Convert the event timestamp to local systemtime structure
//
ftUtcTime.dwLowDateTime = pEvent->Header.TimeStamp.LowPart;
ftUtcTime.dwHighDateTime = pEvent->Header.TimeStamp.HighPart;
if( !FileTimeToLocalFileTime( &ftUtcTime, &ftLocalTime )
|| !FileTimeToSystemTime( &ftLocalTime, &stLocalTime ))
{
//
// Conversion failed -- use zero time
//
ZeroMemory( &stLocalTime, sizeof( SYSTEMTIME ));
}
//
// Print timestamp (yyyy/mm/dd hh:mm:ss)
//
_tprintf(
_T("%i/%02i/%02i %02i:%02i:%02i ++"),
stLocalTime.wYear,
stLocalTime.wMonth,
stLocalTime.wDay,
stLocalTime.wHour,
stLocalTime.wMinute,
stLocalTime.wSecond
);
//
// Connection details.
//
if( NAT_PROTOCOL_TCP == pEventData->Protocol )
{
_tprintf( _T("TCP ") );
}
else
{
_tprintf( _T("UDP ") );
}
if( pEventData->InboundConnection )
{
_tprintf( _T("inbound ") );
}
else
{
_tprintf( _T("outbound ") );
}
inAddr.s_addr = pEventData->LocalAddress;
printf( inet_ntoa( inAddr ));
_tprintf(
_T("/%u :: "),
ntohs( (u_short) pEventData->LocalPort )
);
inAddr.s_addr = pEventData->RemoteAddress;
printf( inet_ntoa( inAddr ));
_tprintf(
_T("/%u\n"),
ntohs( (u_short) pEventData->RemotePort )
);
}
VOID
CALLBACK
ConnectionDeletionCallback(
PEVENT_TRACE pEvent
)
/*++
Routine Description:
Called when a ConnectionDeletionEvent occurs.
Arguments:
pEvent -- pointer to the event trace structure
Return Value:
None.
--*/
{
FILETIME ftUtcTime;
FILETIME ftLocalTime;
SYSTEMTIME stLocalTime;
PMSIPNAT_ConnectionDeletionEvent pEventData;
struct in_addr inAddr;
InterlockedIncrement( &g_lCDeleted );
pEventData = (PMSIPNAT_ConnectionDeletionEvent) pEvent->MofData;
//
// Convert the event timestamp to local systemtime structure
//
ftUtcTime.dwLowDateTime = pEvent->Header.TimeStamp.LowPart;
ftUtcTime.dwHighDateTime = pEvent->Header.TimeStamp.HighPart;
if( !FileTimeToLocalFileTime( &ftUtcTime, &ftLocalTime )
|| !FileTimeToSystemTime( &ftLocalTime, &stLocalTime ))
{
//
// Conversion failed -- use zero time
//
ZeroMemory( &stLocalTime, sizeof( SYSTEMTIME ));
}
//
// Print timestamp (yyyy/mm/dd hh:mm:ss)
//
_tprintf(
_T("%i/%02i/%02i %02i:%02i:%02i --"),
stLocalTime.wYear,
stLocalTime.wMonth,
stLocalTime.wDay,
stLocalTime.wHour,
stLocalTime.wMinute,
stLocalTime.wSecond
);
//
// Connection details.
//
if( NAT_PROTOCOL_TCP == pEventData->Protocol )
{
_tprintf( _T("TCP ") );
}
else
{
_tprintf( _T("UDP ") );
}
inAddr.s_addr = pEventData->LocalAddress;
printf( inet_ntoa( inAddr ));
_tprintf(
_T("/%u :: "),
ntohs( (u_short) pEventData->LocalPort )
);
inAddr.s_addr = pEventData->RemoteAddress;
printf( inet_ntoa( inAddr ));
_tprintf(
_T("/%u\n"),
ntohs( (u_short) pEventData->RemotePort )
);
}
VOID
CALLBACK
PacketDroppedCallback(
PEVENT_TRACE pEvent
)
/*++
Routine Description:
Called when a PacketDroppedEvent occurs.
Arguments:
pEvent -- pointer to the event trace structure
Return Value:
None.
--*/
{
FILETIME ftUtcTime;
FILETIME ftLocalTime;
SYSTEMTIME stLocalTime;
PMSIPNAT_PacketDroppedEvent pEventData;
struct in_addr inAddr;
InterlockedIncrement( &g_lDropped );
pEventData = (PMSIPNAT_PacketDroppedEvent) pEvent->MofData;
//
// Convert the event timestamp to local systemtime structure
//
ftUtcTime.dwLowDateTime = pEvent->Header.TimeStamp.LowPart;
ftUtcTime.dwHighDateTime = pEvent->Header.TimeStamp.HighPart;
if( !FileTimeToLocalFileTime( &ftUtcTime, &ftLocalTime )
|| !FileTimeToSystemTime( &ftLocalTime, &stLocalTime ))
{
//
// Conversion failed -- use zero time
//
ZeroMemory( &stLocalTime, sizeof( SYSTEMTIME ));
}
//
// Print timestamp (yyyy/mm/dd hh:mm:ss)
//
_tprintf(
_T("%i/%02i/%02i %02i:%02i:%02i - "),
stLocalTime.wYear,
stLocalTime.wMonth,
stLocalTime.wDay,
stLocalTime.wHour,
stLocalTime.wMinute,
stLocalTime.wSecond
);
switch( pEventData->Protocol )
{
case NAT_PROTOCOL_TCP:
{
_tprintf( _T("TCP: ") );
inAddr.s_addr = pEventData->SourceAddress;
printf( inet_ntoa( inAddr ));
_tprintf(
_T("/%u -> "),
ntohs( (u_short) pEventData->SourceIdentifier )
);
inAddr.s_addr = pEventData->DestinationAddress;
printf( inet_ntoa( inAddr ));
_tprintf(
_T("/%u "),
ntohs( (u_short) pEventData->DestinationIdentifier )
);
if( pEventData->ProtocolData4 & TCP_FLAG_SYN )
{
_tprintf( _T("S") );
}
if( pEventData->ProtocolData4 & TCP_FLAG_FIN )
{
_tprintf( _T("F") );
}
if( pEventData->ProtocolData4 & TCP_FLAG_ACK )
{
_tprintf( _T("A") );
}
if( pEventData->ProtocolData4 & TCP_FLAG_RST )
{
_tprintf( _T("R") );
}
if( pEventData->ProtocolData4 & TCP_FLAG_URG )
{
_tprintf( _T("U") );
}
if( pEventData->ProtocolData4 & TCP_FLAG_PSH )
{
_tprintf( _T("P") );
}
_tprintf( _T("\n") );
break;
}
case NAT_PROTOCOL_UDP:
{
_tprintf( _T("UDP: ") );
inAddr.s_addr = pEventData->SourceAddress;
printf( inet_ntoa( inAddr ));
_tprintf(
_T("/%u -> "),
ntohs( (u_short) pEventData->SourceIdentifier )
);
inAddr.s_addr = pEventData->DestinationAddress;
printf( inet_ntoa( inAddr ));
_tprintf(
_T("/%u\n"),
ntohs( (u_short) pEventData->DestinationIdentifier )
);
break;
}
case NAT_PROTOCOL_ICMP:
{
_tprintf( _T("ICMP: ") );
inAddr.s_addr = pEventData->SourceAddress;
printf( inet_ntoa( inAddr ));
_tprintf( _T(" -> ") );
inAddr.s_addr = pEventData->DestinationAddress;
printf( "%s\n", inet_ntoa( inAddr ));
break;
}
default:
{
_tprintf( _T("Prot. %i: "), pEventData->Protocol );
inAddr.s_addr = pEventData->SourceAddress;
printf( inet_ntoa( inAddr ));
_tprintf( _T(" -> ") );
inAddr.s_addr = pEventData->DestinationAddress;
printf( "%s\n", inet_ntoa( inAddr ));
}
}
}
UINT
WINAPI
ProcessTraceRoutine(
PVOID pvThreadParam
)
/*++
Routine Description:
Thread routine for trace processing.
Arguments:
pvThreadParam -- unused.
Return Value:
Thread exit code.
--*/
{
TRACEHANDLE hStream;
EVENT_TRACE_LOGFILE LogFile;
ULONG ulError;
//
// Register our trace callbacks
//
ulError = SetTraceCallback( &PacketDroppedEventGuid, PacketDroppedCallback );
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: SetTraceCallback (PacketDropped) returned 0x%08x\n"),
ulError );
return -1;
}
ulError = SetTraceCallback( &ConnectionCreationEventGuid, ConnectionCreationCallback );
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: SetTraceCallback (ConnectionCreation) returned 0x%08x\n"),
ulError );
return -1;
}
ulError = SetTraceCallback( &ConnectionDeletionEventGuid, ConnectionDeletionCallback );
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: SetTraceCallback (ConnectionDeletion) returned 0x%08x\n"),
ulError );
return -1;
}
//
// Open the event stream.
//
ZeroMemory( &LogFile, sizeof(LogFile) );
LogFile.LoggerName = cszLogSession;
LogFile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
hStream = OpenTrace( &LogFile );
if( (TRACEHANDLE)INVALID_HANDLE_VALUE == hStream )
{
_tprintf( _T("FwLogger: OpenTrace returned 0x%08x\n"), GetLastError() );
return -1;
}
//
// Process the trace stream
//
_tprintf( _T("FwLogger: Calling ProcessTrace...\n") );
ulError = ProcessTrace( &hStream, 1, NULL, NULL );
if( ERROR_SUCCESS != ulError )
{
_tprintf( _T("FwLogger: ProcessTrace returned 0x%08x\n"), ulError );
CloseTrace( hStream );
return -1;
}
//
// Close the stream and exit
//
CloseTrace( hStream );
return 0;
}
BOOL
WINAPI
ControlHandler(
DWORD dwCtrlType
)
/*++
Routine Description:
Signals our shutdown event when the user wants to exit.
Arguments:
dwCtrlType -- control signal type
Return Value:
TRUE if we handled the control signal.
--*/
{
if( CTRL_LOGOFF_EVENT != dwCtrlType )
{
SetEvent( g_hShutdownEvent );
return TRUE;
}
return FALSE;
}