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.
 
 
 
 
 
 

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