mirror of
https://github.com/tnodir/fort
synced 2024-11-15 07:25:18 +00:00
Driver: Prepare traffic statistics.
This commit is contained in:
parent
0f6c60a629
commit
809013d91c
@ -31,8 +31,8 @@ fort_buffer_data_new (PFORT_BUFFER buf)
|
||||
if (data != NULL) {
|
||||
buf->data_free = data->next;
|
||||
} else {
|
||||
data = ExAllocatePoolWithTag(NonPagedPool, sizeof(FORT_BUFFER_DATA),
|
||||
FORT_BUFFER_POOL_TAG);
|
||||
data = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(FORT_BUFFER_DATA), FORT_BUFFER_POOL_TAG);
|
||||
}
|
||||
|
||||
return data;
|
||||
@ -76,7 +76,6 @@ fort_buffer_data_alloc (PFORT_BUFFER buf, UINT32 len)
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fort_buffer_data_free (PFORT_BUFFER buf)
|
||||
{
|
||||
@ -232,3 +231,24 @@ fort_buffer_cancel_pending (PFORT_BUFFER buf, PIRP irp, ULONG_PTR *info)
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
fort_buffer_flush_pending (PFORT_BUFFER buf, PIRP *irp, ULONG_PTR *info)
|
||||
{
|
||||
UINT32 out_top;
|
||||
|
||||
KeAcquireSpinLockAtDpcLevel(&buf->lock);
|
||||
out_top = buf->out_top;
|
||||
if (out_top) {
|
||||
*info = out_top;
|
||||
|
||||
buf->out_top = 0;
|
||||
buf->out_len = 0;
|
||||
|
||||
*irp = buf->irp;
|
||||
buf->irp = NULL;
|
||||
}
|
||||
KeReleaseSpinLockFromDpcLevel(&buf->lock);
|
||||
|
||||
return out_top != 0;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ typedef struct fort_device {
|
||||
UINT32 flow4_id;
|
||||
|
||||
FORT_BUFFER buffer;
|
||||
FORT_STAT stat;
|
||||
FORT_TIMER timer;
|
||||
|
||||
PFORT_CONF_REF volatile conf_ref;
|
||||
@ -51,8 +52,8 @@ static PFORT_CONF_REF
|
||||
fort_conf_ref_new (const PFORT_CONF conf, ULONG len)
|
||||
{
|
||||
const ULONG ref_len = len + offsetof(FORT_CONF_REF, conf);
|
||||
PFORT_CONF_REF conf_ref = ExAllocatePoolWithTag(NonPagedPool, ref_len,
|
||||
FORT_DEVICE_POOL_TAG);
|
||||
PFORT_CONF_REF conf_ref = ExAllocatePoolWithTag(
|
||||
NonPagedPool, ref_len, FORT_DEVICE_POOL_TAG);
|
||||
|
||||
if (conf_ref != NULL) {
|
||||
conf_ref->refcount = 0;
|
||||
@ -208,7 +209,7 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
|
||||
|
||||
if (!blocked) {
|
||||
if (ip_included && conf_flags.log_stat) {
|
||||
fort_stat_flow_associate(inMetaValues->flowHandle,
|
||||
fort_stat_flow_associate(&g_device->stat, inMetaValues->flowHandle,
|
||||
g_device->flow4_id, (UINT32) inMetaValues->processId);
|
||||
}
|
||||
goto permit;
|
||||
@ -289,6 +290,34 @@ fort_callout_notify (FWPS_CALLOUT_NOTIFY_TYPE notifyType,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
fort_callout_flow_delete_v4 (UINT16 layerId,
|
||||
UINT32 calloutId,
|
||||
UINT64 flowContext)
|
||||
{
|
||||
UNUSED(layerId);
|
||||
UNUSED(calloutId);
|
||||
|
||||
fort_stat_flow_delete(&g_device->stat, flowContext);
|
||||
}
|
||||
|
||||
static void
|
||||
fort_callout_flow_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
|
||||
const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues,
|
||||
FWPS_STREAM_CALLOUT_IO_PACKET0 *packet,
|
||||
const FWPS_FILTER0 *filter,
|
||||
UINT64 flowContext,
|
||||
FWPS_CLASSIFY_OUT0 *classifyOut)
|
||||
{
|
||||
FWPS_STREAM_DATA0 *streamData = packet->streamData;
|
||||
|
||||
fort_stat_flow_classify(&g_device->stat, flowContext,
|
||||
(UINT32) streamData->dataLength,
|
||||
(streamData->flags & FWPS_STREAM_FLAG_RECEIVE) != 0);
|
||||
|
||||
classifyOut->actionType = FWP_ACTION_CONTINUE;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
fort_callout_install (PDEVICE_OBJECT device)
|
||||
{
|
||||
@ -407,6 +436,24 @@ fort_callout_force_reauth (PDEVICE_OBJECT device,
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
fort_callout_timer (void)
|
||||
{
|
||||
// Flush traffic statistics
|
||||
{
|
||||
}
|
||||
|
||||
// Flush pending buffer
|
||||
{
|
||||
PIRP irp;
|
||||
ULONG_PTR info;
|
||||
|
||||
if (fort_buffer_flush_pending(&g_device->buffer, &irp, &info)) {
|
||||
fort_request_complete_info(irp, STATUS_SUCCESS, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
fort_device_create (PDEVICE_OBJECT device, PIRP irp)
|
||||
{
|
||||
@ -565,6 +612,7 @@ fort_driver_unload (PDRIVER_OBJECT driver)
|
||||
|
||||
if (g_device != NULL) {
|
||||
fort_timer_close(&g_device->timer);
|
||||
fort_stat_close(&g_device->stat);
|
||||
fort_buffer_close(&g_device->buffer);
|
||||
|
||||
if (!g_device->prov_boot) {
|
||||
@ -638,7 +686,8 @@ DriverEntry (PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
|
||||
RtlZeroMemory(g_device, sizeof(FORT_DEVICE));
|
||||
|
||||
fort_buffer_init(&g_device->buffer);
|
||||
fort_timer_init(&g_device->timer, &g_device->buffer);
|
||||
fort_stat_init(&g_device->stat);
|
||||
fort_timer_init(&g_device->timer, &fort_callout_timer);
|
||||
|
||||
KeInitializeSpinLock(&g_device->conf_lock);
|
||||
|
||||
|
@ -1,45 +1,204 @@
|
||||
/* Fort Firewall Usage Statistics */
|
||||
/* Fort Firewall Traffic Statistics */
|
||||
|
||||
static void
|
||||
fort_stat_flow_associate (UINT64 flowId,
|
||||
UINT32 calloutId,
|
||||
UINT32 processId)
|
||||
#define FORT_STAT_POOL_TAG 'SwfF'
|
||||
|
||||
typedef struct fort_stat_proc {
|
||||
UINT32 process_id;
|
||||
|
||||
UINT32 in_bytes;
|
||||
UINT32 out_bytes;
|
||||
|
||||
int refcount;
|
||||
} FORT_STAT_PROC, *PFORT_STAT_PROC;
|
||||
|
||||
typedef struct fort_stat {
|
||||
UINT32 proc_top;
|
||||
UINT32 proc_count;
|
||||
|
||||
int proc_free_index;
|
||||
|
||||
PFORT_STAT_PROC procs;
|
||||
|
||||
KSPIN_LOCK lock;
|
||||
} FORT_STAT, *PFORT_STAT;
|
||||
|
||||
|
||||
static int
|
||||
fort_stat_proc_index (PFORT_STAT stat, UINT32 process_id)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PFORT_STAT_PROC proc = stat->procs;
|
||||
const int n = stat->proc_count;
|
||||
int i;
|
||||
|
||||
status = FwpsFlowAssociateContext0(
|
||||
flowId, FWPS_LAYER_STREAM_V4, calloutId, processId);
|
||||
for (i = 0; i < n; ++i, ++proc) {
|
||||
if (process_id == proc->process_id)
|
||||
return i;
|
||||
}
|
||||
|
||||
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
|
||||
"FORT: flow +: %d %d\n", flowId, processId);
|
||||
|
||||
//STATUS_OBJECT_NAME_EXISTS
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
fort_callout_flow_delete_v4 (UINT16 layerId,
|
||||
UINT32 calloutId,
|
||||
UINT64 flowContext)
|
||||
fort_stat_proc_inc (PFORT_STAT stat, int proc_index)
|
||||
{
|
||||
UNUSED(layerId);
|
||||
UNUSED(calloutId);
|
||||
PFORT_STAT_PROC proc = &stat->procs[proc_index];
|
||||
|
||||
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
|
||||
"FORT: flow -: %d\n", (UINT32) flowContext);
|
||||
proc->refcount++;
|
||||
}
|
||||
|
||||
static void
|
||||
fort_callout_flow_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
|
||||
const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues,
|
||||
FWPS_STREAM_CALLOUT_IO_PACKET0 *packet,
|
||||
const FWPS_FILTER0 *filter,
|
||||
UINT64 flowContext,
|
||||
FWPS_CLASSIFY_OUT0 *classifyOut)
|
||||
fort_stat_proc_dec (PFORT_STAT stat, int proc_index)
|
||||
{
|
||||
FWPS_STREAM_DATA0 *streamData = packet->streamData;
|
||||
PFORT_STAT_PROC proc = &stat->procs[proc_index];
|
||||
|
||||
if (--proc->refcount > 0)
|
||||
return;
|
||||
|
||||
proc->process_id = 0;
|
||||
|
||||
proc->refcount = stat->proc_free_index;
|
||||
stat->proc_free_index = proc_index;
|
||||
}
|
||||
|
||||
static void
|
||||
fort_stat_proc_del (PFORT_STAT stat)
|
||||
{
|
||||
ExFreePoolWithTag(stat->procs, FORT_STAT_POOL_TAG);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
fort_stat_proc_realloc (PFORT_STAT stat)
|
||||
{
|
||||
const UINT32 count = stat->proc_count;
|
||||
const UINT32 new_count = (count ? count : 16) * 3 / 2;
|
||||
PFORT_STAT_PROC new_procs = ExAllocatePoolWithTag(NonPagedPool,
|
||||
new_count * sizeof(FORT_STAT_PROC), FORT_STAT_POOL_TAG);
|
||||
|
||||
if (new_procs == NULL)
|
||||
return FALSE;
|
||||
|
||||
RtlCopyMemory(new_procs, stat->procs, count * sizeof(FORT_STAT_PROC));
|
||||
|
||||
fort_stat_proc_del(stat);
|
||||
|
||||
stat->proc_count = new_count;
|
||||
stat->procs = new_procs;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
fort_stat_proc_add (PFORT_STAT stat, UINT32 process_id)
|
||||
{
|
||||
PFORT_STAT_PROC proc;
|
||||
int proc_index = stat->proc_free_index;
|
||||
|
||||
if (proc_index != -1) {
|
||||
proc = &stat->procs[proc_index];
|
||||
|
||||
stat->proc_free_index = proc->refcount;
|
||||
}
|
||||
else {
|
||||
if (stat->proc_top >= stat->proc_count
|
||||
&& !fort_stat_proc_realloc(stat)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
proc_index = stat->proc_top++;
|
||||
proc = &stat->procs[proc_index];
|
||||
}
|
||||
|
||||
proc->process_id = process_id;
|
||||
proc->in_bytes = proc->out_bytes = 0;
|
||||
proc->refcount = 1;
|
||||
|
||||
return proc_index;
|
||||
}
|
||||
|
||||
static void
|
||||
fort_stat_init (PFORT_STAT stat)
|
||||
{
|
||||
stat->proc_free_index = -1;
|
||||
|
||||
KeInitializeSpinLock(&stat->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
fort_stat_close (PFORT_STAT stat)
|
||||
{
|
||||
fort_stat_proc_del(stat);
|
||||
}
|
||||
|
||||
static void
|
||||
fort_stat_flow_associate (PFORT_STAT stat, UINT64 flow_id,
|
||||
UINT32 callout_id, UINT32 process_id)
|
||||
{
|
||||
KIRQL irq;
|
||||
UINT64 flow_context;
|
||||
int proc_index;
|
||||
|
||||
KeAcquireSpinLock(&stat->lock, &irq);
|
||||
|
||||
proc_index = fort_stat_proc_index(stat, process_id);
|
||||
if (proc_index == -1) {
|
||||
proc_index = fort_stat_proc_add(stat, process_id);
|
||||
if (proc_index == -1)
|
||||
goto end;
|
||||
}
|
||||
|
||||
flow_context = (UINT64) process_id | ((UINT64) proc_index << 32);
|
||||
|
||||
fort_stat_proc_inc(stat, proc_index);
|
||||
|
||||
if (!NT_SUCCESS(FwpsFlowAssociateContext0(flow_id,
|
||||
FWPS_LAYER_STREAM_V4, callout_id, flow_context))) {
|
||||
fort_stat_proc_dec(stat, proc_index);
|
||||
}
|
||||
|
||||
end:
|
||||
KeReleaseSpinLock(&stat->lock, irq);
|
||||
|
||||
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
|
||||
"FORT: flow >: %d %d %d\n", inMetaValues->flowHandle, flowContext, streamData->dataLength);
|
||||
|
||||
classifyOut->actionType = FWP_ACTION_CONTINUE;
|
||||
"FORT: flow +: %d\n", process_id);
|
||||
}
|
||||
|
||||
static void
|
||||
fort_stat_flow_delete (PFORT_STAT stat, UINT64 flow_context)
|
||||
{
|
||||
KIRQL irq;
|
||||
const int proc_index = (int) (flow_context >> 32);
|
||||
|
||||
KeAcquireSpinLock(&stat->lock, &irq);
|
||||
|
||||
fort_stat_proc_dec(stat, proc_index);
|
||||
|
||||
KeReleaseSpinLock(&stat->lock, irq);
|
||||
|
||||
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
|
||||
"FORT: flow -: %d\n", (UINT32) flow_context);
|
||||
}
|
||||
|
||||
static void
|
||||
fort_stat_flow_classify (PFORT_STAT stat, UINT64 flow_context,
|
||||
UINT32 data_len, BOOL inbound)
|
||||
{
|
||||
PFORT_STAT_PROC proc;
|
||||
KIRQL irq;
|
||||
const UINT32 process_id = (UINT32) flow_context;
|
||||
const int proc_index = (int) (flow_context >> 32);
|
||||
|
||||
KeAcquireSpinLock(&stat->lock, &irq);
|
||||
|
||||
proc = &stat->procs[proc_index];
|
||||
|
||||
if (inbound) {
|
||||
proc->in_bytes += data_len;
|
||||
} else {
|
||||
proc->out_bytes += data_len;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&stat->lock, irq);
|
||||
|
||||
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
|
||||
"FORT: flow >: %d %d\n", (UINT32) flow_context, data_len);
|
||||
}
|
||||
|
@ -1,43 +1,35 @@
|
||||
/* Fort Firewall Timer */
|
||||
|
||||
typedef void (*FORT_TIMER_FUNC) (void);
|
||||
|
||||
typedef struct fort_timer {
|
||||
UINT32 running : 1;
|
||||
|
||||
FORT_TIMER_FUNC callback;
|
||||
|
||||
KDPC dpc;
|
||||
KTIMER id;
|
||||
} FORT_TIMER, *PFORT_TIMER;
|
||||
|
||||
|
||||
static void
|
||||
fort_timer_callback (PKDPC dpc, PFORT_BUFFER buf, PVOID arg1, PVOID arg2)
|
||||
fort_timer_callback (PKDPC dpc, PFORT_TIMER timer, PVOID arg1, PVOID arg2)
|
||||
{
|
||||
PIRP irp = NULL;
|
||||
ULONG info;
|
||||
|
||||
UNUSED(dpc);
|
||||
UNUSED(arg1);
|
||||
UNUSED(arg2);
|
||||
|
||||
KeAcquireSpinLockAtDpcLevel(&buf->lock);
|
||||
info = buf->out_top;
|
||||
if (info) {
|
||||
buf->out_top = 0;
|
||||
buf->out_len = 0;
|
||||
|
||||
irp = buf->irp;
|
||||
buf->irp = NULL;
|
||||
}
|
||||
KeReleaseSpinLockFromDpcLevel(&buf->lock);
|
||||
|
||||
if (info) {
|
||||
fort_request_complete_info(irp, STATUS_SUCCESS, info);
|
||||
if (timer->callback != NULL) {
|
||||
timer->callback();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fort_timer_init (PFORT_TIMER timer, PFORT_BUFFER buf)
|
||||
fort_timer_init (PFORT_TIMER timer, FORT_TIMER_FUNC callback)
|
||||
{
|
||||
KeInitializeDpc(&timer->dpc, &fort_timer_callback, buf);
|
||||
timer->callback = callback;
|
||||
|
||||
KeInitializeDpc(&timer->dpc, &fort_timer_callback, timer);
|
||||
KeInitializeTimer(&timer->id);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user