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.
285 lines
6.0 KiB
285 lines
6.0 KiB
/*++
|
|
|
|
Copyright (c) 1997-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
NsTimer.c
|
|
|
|
Abstract:
|
|
|
|
IpSec NAT shim timer management
|
|
|
|
Author:
|
|
|
|
Jonathan Burstein (jonburs) 11-July-2001
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Defines the interval at which the timer fires, in 100-nanosecond intervals
|
|
//
|
|
|
|
#define NS_TIMER_INTERVAL (60 * 1000 * 1000 * 10)
|
|
|
|
//
|
|
// Return-value of KeQueryTimeIncrement, used for normalizing tick-counts
|
|
//
|
|
|
|
ULONG NsTimeIncrement;
|
|
|
|
//
|
|
// DPC object for NsTimerRoutine
|
|
//
|
|
|
|
KDPC NsTimerDpcObject;
|
|
|
|
//
|
|
// Timer object for NsTimerRoutine
|
|
//
|
|
|
|
KTIMER NsTimerObject;
|
|
|
|
//
|
|
// Protocol timeouts
|
|
//
|
|
|
|
ULONG NsTcpTimeoutSeconds;
|
|
ULONG NsTcpTimeWaitSeconds;
|
|
ULONG NsUdpTimeoutSeconds;
|
|
|
|
//
|
|
// Function Prototypes
|
|
//
|
|
|
|
VOID
|
|
NsTimerRoutine(
|
|
PKDPC Dpc,
|
|
PVOID DeferredContext,
|
|
PVOID SystemArgument1,
|
|
PVOID SystemArgument2
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
NsInitializeTimerManagement(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to initialize the timer management module.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS.
|
|
|
|
--*/
|
|
|
|
{
|
|
LARGE_INTEGER DueTime;
|
|
|
|
CALLTRACE(("NsInitializeTimerManagement\n"));
|
|
|
|
NsTimeIncrement = KeQueryTimeIncrement();
|
|
KeInitializeDpc(&NsTimerDpcObject, NsTimerRoutine, NULL);
|
|
KeInitializeTimer(&NsTimerObject);
|
|
|
|
DueTime.LowPart = NS_TIMER_INTERVAL;
|
|
DueTime.HighPart = 0;
|
|
DueTime = RtlLargeIntegerNegate(DueTime);
|
|
KeSetTimerEx(
|
|
&NsTimerObject,
|
|
DueTime,
|
|
NS_TIMER_INTERVAL / 10000,
|
|
&NsTimerDpcObject
|
|
);
|
|
|
|
NsTcpTimeoutSeconds = 60 * 60 * 24;
|
|
NsTcpTimeWaitSeconds = 60 * 4;
|
|
NsUdpTimeoutSeconds = 60;
|
|
|
|
return STATUS_SUCCESS;
|
|
} // NsInitializeTimerManagement
|
|
|
|
|
|
VOID
|
|
NsShutdownTimerManagement(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to cleanup the timer management module.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
CALLTRACE(("NsShutdownTimerManagement\n"));
|
|
|
|
KeCancelTimer(&NsTimerObject);
|
|
} // NsShutdownTimerManagement
|
|
|
|
|
|
VOID
|
|
NsTimerRoutine(
|
|
PKDPC Dpc,
|
|
PVOID DeferredContext,
|
|
PVOID SystemArgument1,
|
|
PVOID SystemArgument2
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked periodically to garbage-collect expired mappings.
|
|
|
|
Arguments:
|
|
|
|
Dpc - associated DPC object
|
|
|
|
DeferredContext - unused.
|
|
|
|
SystemArgument1 - unused.
|
|
|
|
SystemArgument2 - unused.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
LONG64 CurrentTime;
|
|
KIRQL Irql;
|
|
PLIST_ENTRY Link;
|
|
PNS_CONNECTION_ENTRY pConnectionEntry;
|
|
PNS_ICMP_ENTRY pIcmpEntry;
|
|
LONG64 Timeout;
|
|
LONG64 TcpMinAccessTime;
|
|
LONG64 TcpMinTimeWaitExpiryTime;
|
|
LONG64 UdpMinAccessTime;
|
|
|
|
TRACE(TIMER, ("NsTimerRoutine\n"));
|
|
|
|
//
|
|
// Compute the minimum values allowed in TCP/UDP 'LastAccessTime' fields;
|
|
// any mappings last accessed before these thresholds will be eliminated.
|
|
//
|
|
|
|
KeQueryTickCount((PLARGE_INTEGER)&CurrentTime);
|
|
TcpMinAccessTime = CurrentTime - SECONDS_TO_TICKS(NsTcpTimeoutSeconds);
|
|
TcpMinTimeWaitExpiryTime =
|
|
CurrentTime - SECONDS_TO_TICKS(NsTcpTimeWaitSeconds);
|
|
UdpMinAccessTime = CurrentTime - SECONDS_TO_TICKS(NsUdpTimeoutSeconds);
|
|
|
|
//
|
|
// Clean out expired connection entries,
|
|
// using the above precomputed minimum access times
|
|
//
|
|
|
|
KeAcquireSpinLock(&NsConnectionLock, &Irql);
|
|
for (Link = NsConnectionList.Flink;
|
|
Link != &NsConnectionList;
|
|
Link = Link->Flink)
|
|
{
|
|
|
|
pConnectionEntry = CONTAINING_RECORD(Link, NS_CONNECTION_ENTRY, Link);
|
|
|
|
//
|
|
// See if the connection has expired
|
|
//
|
|
|
|
KeAcquireSpinLockAtDpcLevel(&pConnectionEntry->Lock);
|
|
if (!NS_CONNECTION_EXPIRED(pConnectionEntry))
|
|
{
|
|
//
|
|
// The entry is not explicitly marked for expiration;
|
|
// see if its last access time is too long ago
|
|
//
|
|
|
|
if (NS_PROTOCOL_TCP == pConnectionEntry->ucProtocol)
|
|
{
|
|
if (pConnectionEntry->l64AccessOrExpiryTime >= TcpMinAccessTime)
|
|
{
|
|
KeReleaseSpinLockFromDpcLevel(&pConnectionEntry->Lock);
|
|
continue;
|
|
}
|
|
}
|
|
else if (pConnectionEntry->l64AccessOrExpiryTime >= UdpMinAccessTime)
|
|
{
|
|
KeReleaseSpinLockFromDpcLevel(&pConnectionEntry->Lock);
|
|
continue;
|
|
}
|
|
}
|
|
else if (NS_CONNECTION_FIN(pConnectionEntry)
|
|
&& pConnectionEntry->l64AccessOrExpiryTime >= TcpMinTimeWaitExpiryTime)
|
|
{
|
|
//
|
|
// This connection was marked as expired because FINs were
|
|
// seen in both directions, but has not yet left the time-wait
|
|
// period.
|
|
//
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&pConnectionEntry->Lock);
|
|
continue;
|
|
}
|
|
KeReleaseSpinLockFromDpcLevel(&pConnectionEntry->Lock);
|
|
|
|
//
|
|
// The entry has expired; remove it
|
|
//
|
|
|
|
Link = Link->Blink;
|
|
NsDeleteConnectionEntry(pConnectionEntry);
|
|
}
|
|
KeReleaseSpinLockFromDpcLevel(&NsConnectionLock);
|
|
|
|
//
|
|
// Traverse the ICMP list and remove each expired entry.
|
|
//
|
|
|
|
KeAcquireSpinLockAtDpcLevel(&NsIcmpLock);
|
|
for (Link = NsIcmpList.Flink;
|
|
Link != &NsIcmpList;
|
|
Link = Link->Flink)
|
|
{
|
|
pIcmpEntry = CONTAINING_RECORD(Link, NS_ICMP_ENTRY, Link);
|
|
if (pIcmpEntry->l64LastAccessTime>= UdpMinAccessTime) { continue; }
|
|
Link = Link->Blink;
|
|
RemoveEntryList(&pIcmpEntry->Link);
|
|
FREE_ICMP_BLOCK(pIcmpEntry);
|
|
}
|
|
KeReleaseSpinLock(&NsIcmpLock, Irql);
|
|
|
|
} // NsTimerRoutine
|
|
|
|
|
|
|