849 lines
18 KiB
C
849 lines
18 KiB
C
/*++
|
||
|
||
Copyright (c) 1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
director.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the code for director management.
|
||
|
||
Author:
|
||
|
||
Abolade Gbadegesin (t-abolag) 16-Feb-1998
|
||
|
||
Revision History:
|
||
|
||
Abolade Gbadegesin (aboladeg) 19-Apr-1998
|
||
|
||
Added support for wildcards in protocol/port of a director registration.
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
//
|
||
// GLOBAL DATA DEFINITIONS
|
||
//
|
||
|
||
//
|
||
// Count of NAT directors
|
||
//
|
||
|
||
ULONG DirectorCount;
|
||
|
||
//
|
||
// List of NAT directors
|
||
//
|
||
|
||
LIST_ENTRY DirectorList;
|
||
|
||
//
|
||
// Spin-lock controlling access to 'DirectorList'
|
||
//
|
||
|
||
KSPIN_LOCK DirectorLock;
|
||
|
||
//
|
||
// Spin-lock controlling access to the 'MappingList' field of all directors
|
||
//
|
||
|
||
KSPIN_LOCK DirectorMappingLock;
|
||
|
||
|
||
VOID
|
||
NatCleanupDirector(
|
||
PNAT_DIRECTOR Director
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Called to perform final cleanup for an director.
|
||
|
||
Arguments:
|
||
|
||
Director - the director to be cleaned up.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL Irql;
|
||
PLIST_ENTRY Link;
|
||
PNAT_DYNAMIC_MAPPING Mapping;
|
||
|
||
CALLTRACE(("NatCleanupDirector\n"));
|
||
|
||
//
|
||
// Detach the director from all of its mappings
|
||
//
|
||
|
||
KeAcquireSpinLock(&DirectorLock, &Irql);
|
||
KeAcquireSpinLockAtDpcLevel(&DirectorMappingLock);
|
||
for (Link = Director->MappingList.Flink; Link != &Director->MappingList;
|
||
Link = Link->Flink) {
|
||
Mapping = CONTAINING_RECORD(Link, NAT_DYNAMIC_MAPPING, DirectorLink);
|
||
Link = Link->Blink;
|
||
NatMappingDetachDirector(
|
||
Director,
|
||
Mapping->DirectorContext,
|
||
Mapping,
|
||
NatCleanupDirectorDeleteReason
|
||
);
|
||
}
|
||
KeReleaseSpinLockFromDpcLevel(&DirectorMappingLock);
|
||
KeReleaseSpinLock(&DirectorLock, Irql);
|
||
|
||
if (Director->UnloadHandler) {
|
||
Director->UnloadHandler(Director->Context);
|
||
}
|
||
|
||
ExFreePool(Director);
|
||
|
||
} // NatCleanupDirector
|
||
|
||
|
||
|
||
NTSTATUS
|
||
NatCreateDirector(
|
||
PIP_NAT_REGISTER_DIRECTOR RegisterContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked when an director attempts to register.
|
||
It handles creation of a context-block for the director.
|
||
|
||
Arguments:
|
||
|
||
RegisterContext - information about the registering director
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - status code.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNAT_DIRECTOR Director;
|
||
PLIST_ENTRY InsertionPoint;
|
||
KIRQL Irql;
|
||
ULONG Key;
|
||
|
||
CALLTRACE(("NatCreateDirector\n"));
|
||
|
||
RegisterContext->DirectorHandle = NULL;
|
||
|
||
//
|
||
// Validate the registration information
|
||
//
|
||
|
||
if (!RegisterContext->QueryHandler &&
|
||
!RegisterContext->CreateHandler &&
|
||
!RegisterContext->DeleteHandler &&
|
||
!RegisterContext->UnloadHandler) {
|
||
ERROR(("NatCreateDirector: bad argument\n"));
|
||
return STATUS_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Allocate a new director-struct
|
||
//
|
||
|
||
Director =
|
||
ExAllocatePoolWithTag(
|
||
NonPagedPool, sizeof(NAT_DIRECTOR), NAT_TAG_DIRECTOR
|
||
);
|
||
|
||
if (!Director) {
|
||
ERROR(("NatCreateDirector: allocation failed\n"));
|
||
return STATUS_NO_MEMORY;
|
||
}
|
||
|
||
KeInitializeSpinLock(&Director->Lock);
|
||
Director->ReferenceCount = 1;
|
||
Director->Flags = RegisterContext->Flags;
|
||
Director->Key =
|
||
MAKE_DIRECTOR_KEY(RegisterContext->Protocol, RegisterContext->Port);
|
||
InitializeListHead(&Director->MappingList);
|
||
Director->Context = RegisterContext->DirectorContext;
|
||
Director->CreateHandler = RegisterContext->CreateHandler;
|
||
Director->DeleteHandler = RegisterContext->DeleteHandler;
|
||
Director->QueryHandler = RegisterContext->QueryHandler;
|
||
Director->UnloadHandler = RegisterContext->UnloadHandler;
|
||
|
||
KeAcquireSpinLock(&DirectorLock, &Irql);
|
||
if (NatLookupDirector(Director->Key, &InsertionPoint)) {
|
||
KeReleaseSpinLock(&DirectorLock, Irql);
|
||
ERROR(
|
||
("NatCreateDirector: duplicate director %d/%d\n",
|
||
RegisterContext->Protocol, RegisterContext->Port)
|
||
);
|
||
ExFreePool(Director);
|
||
return STATUS_UNSUCCESSFUL;
|
||
}
|
||
InsertTailList(InsertionPoint, &Director->Link);
|
||
KeReleaseSpinLock(&DirectorLock, Irql);
|
||
|
||
InterlockedIncrement(&DirectorCount);
|
||
|
||
//
|
||
// Supply the caller with 'out' information
|
||
//
|
||
|
||
RegisterContext->DirectorHandle = (PVOID)Director;
|
||
RegisterContext->QueryInfoSession = NatDirectorQueryInfoSession;
|
||
RegisterContext->Deregister = NatDirectorDeregister;
|
||
RegisterContext->DissociateSession = NatDirectorDissociateSession;
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // NatCreateDirector
|
||
|
||
|
||
|
||
NTSTATUS
|
||
NatDeleteDirector(
|
||
PNAT_DIRECTOR Director
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Handles director deletion.
|
||
|
||
Arguments:
|
||
|
||
Director - specifies the director to be deleted.
|
||
|
||
Return Value
|
||
|
||
NTSTATUS - status code.
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL Irql;
|
||
CALLTRACE(("NatDeleteDirector\n"));
|
||
if (!Director) { return STATUS_INVALID_PARAMETER; }
|
||
InterlockedDecrement(&DirectorCount);
|
||
|
||
//
|
||
// Remove the director from the list
|
||
//
|
||
|
||
KeAcquireSpinLock(&DirectorLock, &Irql);
|
||
RemoveEntryList(&Director->Link);
|
||
Director->Flags |= NAT_DIRECTOR_FLAG_DELETED;
|
||
KeReleaseSpinLock(&DirectorLock, Irql);
|
||
|
||
//
|
||
// Drop its reference count and cleanup if necessary
|
||
//
|
||
|
||
if (InterlockedDecrement(&Director->ReferenceCount) > 0) {
|
||
return STATUS_PENDING;
|
||
}
|
||
NatCleanupDirector(Director);
|
||
return STATUS_SUCCESS;
|
||
|
||
} // NatDeleteDirector
|
||
|
||
|
||
VOID
|
||
NatInitializeDirectorManagement(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine prepares the director-management module for operation.
|
||
|
||
Arguments:
|
||
|
||
none.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
CALLTRACE(("NatInitializeDirectorManagement\n"));
|
||
|
||
DirectorCount = 0;
|
||
KeInitializeSpinLock(&DirectorLock);
|
||
InitializeListHead(&DirectorList);
|
||
KeInitializeSpinLock(&DirectorMappingLock);
|
||
|
||
} // NatInitializeDirectorManagement
|
||
|
||
|
||
PNAT_DIRECTOR
|
||
NatLookupAndReferenceDirector(
|
||
UCHAR Protocol,
|
||
USHORT Port
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to search for a director for the given
|
||
incoming protocol and port, and to obtain a referenced pointer
|
||
to such a director.
|
||
|
||
This routine must be invoked at DISPATCH_LEVEL.
|
||
|
||
Arguments:
|
||
|
||
Protocol - the protocol of the director to be looked up
|
||
|
||
Port - the port-number of the director to be looked up
|
||
|
||
Return Value:
|
||
|
||
PNAT_DIRECTOR - the references director if found; NULL otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNAT_DIRECTOR Director;
|
||
ULONG Key;
|
||
PLIST_ENTRY Link;
|
||
|
||
KeAcquireSpinLockAtDpcLevel(&DirectorLock);
|
||
|
||
if (IsListEmpty(&DirectorList)) {
|
||
KeReleaseSpinLockFromDpcLevel(&DirectorLock); return NULL;
|
||
}
|
||
Key = MAKE_DIRECTOR_KEY(Protocol, Port);
|
||
|
||
//
|
||
// Our support for wildcards takes advantage of the fact that
|
||
// all wildcards are designated by zero; hence, since our list
|
||
// is in descending order we only need to look for wildcards
|
||
// at the point where we would break off a normal search.
|
||
//
|
||
|
||
for (Link = DirectorList.Flink; Link != &DirectorList; Link = Link->Flink) {
|
||
Director = CONTAINING_RECORD(Link, NAT_DIRECTOR, Link);
|
||
if (Key < Director->Key) {
|
||
continue;
|
||
} else if (Key > Director->Key) {
|
||
//
|
||
// End of normal search. Now look for wildcards
|
||
//
|
||
do {
|
||
if ((!DIRECTOR_KEY_PROTOCOL(Director->Key) ||
|
||
Protocol == DIRECTOR_KEY_PROTOCOL(Director->Key)) &&
|
||
(!DIRECTOR_KEY_PORT(Director->Key) ||
|
||
Port == DIRECTOR_KEY_PORT(Director->Key))) {
|
||
//
|
||
// We have a matching wildcard.
|
||
//
|
||
break;
|
||
}
|
||
Link = Link->Flink;
|
||
} while (Link != &DirectorList);
|
||
if (Link == &DirectorList) { break; }
|
||
}
|
||
|
||
//
|
||
// We've found it. Reference it and return.
|
||
//
|
||
|
||
if (!NatReferenceDirector(Director)) { Director = NULL; }
|
||
KeReleaseSpinLockFromDpcLevel(&DirectorLock);
|
||
return Director;
|
||
}
|
||
|
||
KeReleaseSpinLockFromDpcLevel(&DirectorLock);
|
||
|
||
return NULL;
|
||
|
||
} // NatLookupAndReferenceDirector
|
||
|
||
|
||
PNAT_DIRECTOR
|
||
NatLookupDirector(
|
||
ULONG Key,
|
||
PLIST_ENTRY* InsertionPoint
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to retrieve the director corresponding to the given
|
||
key.
|
||
|
||
Arguments:
|
||
|
||
Key - the key for which an director is to be found
|
||
|
||
InsertionPoint - receives the point at which the director should be
|
||
inserted if not found
|
||
|
||
Return Value:
|
||
|
||
PNAT_DIRECTOR - the required director, if found
|
||
|
||
--*/
|
||
|
||
{
|
||
PNAT_DIRECTOR Director;
|
||
PLIST_ENTRY Link;
|
||
for (Link = DirectorList.Flink; Link != &DirectorList; Link = Link->Flink) {
|
||
Director = CONTAINING_RECORD(Link, NAT_DIRECTOR, Link);
|
||
if (Key < Director->Key) {
|
||
continue;
|
||
} else if (Key > Director->Key) {
|
||
break;
|
||
}
|
||
return Director;
|
||
}
|
||
if (InsertionPoint) { *InsertionPoint = Link; }
|
||
return NULL;
|
||
} // NatLookupDirector
|
||
|
||
|
||
VOID
|
||
NatMappingAttachDirector(
|
||
PNAT_DIRECTOR Director,
|
||
PVOID DirectorSessionContext,
|
||
PNAT_DYNAMIC_MAPPING Mapping
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to attach a mapping to a director.
|
||
It serves as a notification that there is one more mapping
|
||
associated with the director.
|
||
|
||
Arguments:
|
||
|
||
Director - the director for the mapping
|
||
|
||
DirectorSessionContext - context associated with the mapping by the director
|
||
|
||
Mapping - the mapping to be attached.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
Environment:
|
||
|
||
Always invoked at dispatch level with 'DirectorLock' and
|
||
'DirectorMappingLock' held by the caller.
|
||
|
||
--*/
|
||
|
||
{
|
||
Mapping->Director = Director;
|
||
Mapping->DirectorContext = DirectorSessionContext;
|
||
InsertTailList(&Director->MappingList, &Mapping->DirectorLink);
|
||
if (Director->CreateHandler) {
|
||
Director->CreateHandler(
|
||
Mapping,
|
||
Director->Context,
|
||
DirectorSessionContext
|
||
);
|
||
}
|
||
} // NatMappingAttachDirector
|
||
|
||
|
||
VOID
|
||
NatMappingDetachDirector(
|
||
PNAT_DIRECTOR Director,
|
||
PVOID DirectorSessionContext,
|
||
PNAT_DYNAMIC_MAPPING Mapping,
|
||
IP_NAT_DELETE_REASON DeleteReason
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked to detach a mapping from a director.
|
||
It serves as a notification that there is one less mapping
|
||
associated with the director.
|
||
|
||
Arguments:
|
||
|
||
Director - director to be detached
|
||
|
||
DirectorSessionContext - context associated with the director
|
||
|
||
Mapping - the mapping to be detached, or NULL if a mapping could not be
|
||
created.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
Environment:
|
||
|
||
Always invoked at dispatch level with 'DirectorLock' and
|
||
'DirectorMappingLock' held, in that order.
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL Irql;
|
||
if (!Mapping) {
|
||
if (Director->DeleteHandler) {
|
||
Director->DeleteHandler(
|
||
NULL,
|
||
Director->Context,
|
||
DirectorSessionContext,
|
||
DeleteReason
|
||
);
|
||
}
|
||
} else {
|
||
if (Director->DeleteHandler) {
|
||
Director->DeleteHandler(
|
||
Mapping,
|
||
Director->Context,
|
||
Mapping->DirectorContext,
|
||
DeleteReason
|
||
);
|
||
}
|
||
RemoveEntryList(&Mapping->DirectorLink);
|
||
Mapping->Director = NULL;
|
||
Mapping->DirectorContext = NULL;
|
||
}
|
||
} // NatMappingDetachDirector
|
||
|
||
|
||
NTSTATUS
|
||
NatQueryDirectorTable(
|
||
IN PIP_NAT_ENUMERATE_DIRECTORS InputBuffer,
|
||
IN PIP_NAT_ENUMERATE_DIRECTORS OutputBuffer,
|
||
IN PULONG OutputBufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used for enumerating the registered directors.
|
||
|
||
Arguments:
|
||
|
||
InputBuffer - supplies context information for the information
|
||
|
||
OutputBuffer - receives the result of the enumeration
|
||
|
||
OutputBufferLength - size of the i/o buffer
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS if successful, error code otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Count;
|
||
ULONG i;
|
||
KIRQL Irql;
|
||
ULONG Key;
|
||
PLIST_ENTRY Link;
|
||
PNAT_DIRECTOR Director;
|
||
NTSTATUS status;
|
||
PIP_NAT_DIRECTOR Table;
|
||
|
||
CALLTRACE(("NatQueryDirectorTable\n"));
|
||
|
||
Key = InputBuffer->EnumerateContext;
|
||
KeAcquireSpinLock(&DirectorLock, &Irql);
|
||
|
||
//
|
||
// See if this is a new enumeration or a continuation of an old one.
|
||
//
|
||
|
||
if (!Key) {
|
||
|
||
//
|
||
// This is a new enumeration. We start with the first item
|
||
// in the list of entries
|
||
//
|
||
|
||
Director =
|
||
IsListEmpty(&DirectorList)
|
||
? NULL
|
||
: CONTAINING_RECORD(DirectorList.Flink, NAT_DIRECTOR, Link);
|
||
} else {
|
||
|
||
//
|
||
// This is a continuation. The context therefore contains
|
||
// the key for the next entry.
|
||
//
|
||
|
||
Director = NatLookupDirector(Key, NULL);
|
||
}
|
||
|
||
if (!Director) {
|
||
OutputBuffer->EnumerateCount = 0;
|
||
OutputBuffer->EnumerateContext = 0;
|
||
OutputBuffer->EnumerateTotalHint = DirectorCount;
|
||
*OutputBufferLength =
|
||
FIELD_OFFSET(IP_NAT_ENUMERATE_DIRECTORS, EnumerateTable);
|
||
KeReleaseSpinLock(&DirectorLock, Irql);
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// Compute the maximum number of entries we can store
|
||
//
|
||
|
||
Count =
|
||
*OutputBufferLength -
|
||
FIELD_OFFSET(IP_NAT_ENUMERATE_DIRECTORS, EnumerateTable);
|
||
Count /= sizeof(IP_NAT_DIRECTOR);
|
||
|
||
//
|
||
// Walk the list storing entries in the caller's buffer
|
||
//
|
||
|
||
Table = OutputBuffer->EnumerateTable;
|
||
|
||
for (i = 0, Link = &Director->Link; i < Count && Link != &DirectorList;
|
||
i++, Link = Link->Flink) {
|
||
Director = CONTAINING_RECORD(Link, NAT_DIRECTOR, Link);
|
||
Table[i].Protocol = DIRECTOR_KEY_PROTOCOL(Director->Key);
|
||
Table[i].Port = DIRECTOR_KEY_PORT(Director->Key);
|
||
}
|
||
|
||
//
|
||
// The enumeration is over; update the output structure
|
||
//
|
||
|
||
*OutputBufferLength =
|
||
i * sizeof(IP_NAT_DIRECTOR) +
|
||
FIELD_OFFSET(IP_NAT_ENUMERATE_DIRECTORS, EnumerateTable);
|
||
OutputBuffer->EnumerateCount = i;
|
||
OutputBuffer->EnumerateTotalHint = DirectorCount;
|
||
if (Link == &DirectorList) {
|
||
//
|
||
// We reached the end of the list
|
||
//
|
||
OutputBuffer->EnumerateContext = 0;
|
||
} else {
|
||
//
|
||
// Save the continuation context
|
||
//
|
||
OutputBuffer->EnumerateContext =
|
||
CONTAINING_RECORD(Link, NAT_DIRECTOR, Link)->Key;
|
||
}
|
||
|
||
KeReleaseSpinLock(&DirectorLock, Irql);
|
||
return STATUS_SUCCESS;
|
||
|
||
} // NatQueryDirectorTable
|
||
|
||
|
||
VOID
|
||
NatShutdownDirectorManagement(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine shuts down the director-management module.
|
||
|
||
Arguments:
|
||
|
||
none.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNAT_DIRECTOR Director;
|
||
KIRQL Irql;
|
||
|
||
CALLTRACE(("NatShutdownDirectorManagement\n"));
|
||
|
||
//
|
||
// Delete all directors
|
||
//
|
||
|
||
KeAcquireSpinLock(&DirectorLock, &Irql);
|
||
while (!IsListEmpty(&DirectorList)) {
|
||
Director = CONTAINING_RECORD(DirectorList.Flink, NAT_DIRECTOR, Link);
|
||
RemoveEntryList(&Director->Link);
|
||
KeReleaseSpinLockFromDpcLevel(&DirectorLock);
|
||
NatCleanupDirector(Director);
|
||
KeAcquireSpinLockAtDpcLevel(&DirectorLock);
|
||
}
|
||
KeReleaseSpinLock(&DirectorLock, Irql);
|
||
|
||
} // NatShutdownDirectorManagement
|
||
|
||
|
||
|
||
//
|
||
// DIRECTOR HELPER ROUTINES
|
||
//
|
||
// The caller is assumed to be running at DISPATCH_LEVEL.
|
||
//
|
||
|
||
NTSTATUS
|
||
NatDirectorDeregister(
|
||
IN PVOID DirectorHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by a director to remove itself
|
||
from the director list.
|
||
|
||
Arguments:
|
||
|
||
DirectorHandle - handle of the director to be removed.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - status code.
|
||
|
||
--*/
|
||
|
||
{
|
||
CALLTRACE(("NatDirectorDeregister\n"));
|
||
return NatDeleteDirector((PNAT_DIRECTOR)DirectorHandle);
|
||
|
||
} // NatDirectorDeregister
|
||
|
||
|
||
NTSTATUS
|
||
NatDirectorDissociateSession(
|
||
IN PVOID DirectorHandle,
|
||
IN PVOID SessionHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by a director to dissociate itself from a specific
|
||
session.
|
||
|
||
Arguments:
|
||
|
||
DirectorHandle - the director which wishes to dissociate itself.
|
||
|
||
SessionHandle - the session from which the director is disssociating itself.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - indicates success/failure
|
||
|
||
Environment:
|
||
|
||
Invoked at dispatch level with neither 'DirectorLock' nor
|
||
'DirectorMappingLock' held by the caller.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PNAT_DIRECTOR Director = (PNAT_DIRECTOR)DirectorHandle;
|
||
KIRQL Irql;
|
||
PNAT_DYNAMIC_MAPPING Mapping = (PNAT_DYNAMIC_MAPPING)SessionHandle;
|
||
CALLTRACE(("NatDirectorDissociateSession\n"));
|
||
KeAcquireSpinLock(&DirectorLock, &Irql);
|
||
if (Mapping->Director != Director) {
|
||
KeReleaseSpinLock(&DirectorLock, Irql);
|
||
return STATUS_INVALID_PARAMETER;
|
||
}
|
||
KeAcquireSpinLockAtDpcLevel(&DirectorMappingLock);
|
||
NatMappingDetachDirector(
|
||
Director,
|
||
Mapping->DirectorContext,
|
||
Mapping,
|
||
NatDissociateDirectorDeleteReason
|
||
);
|
||
KeReleaseSpinLockFromDpcLevel(&DirectorMappingLock);
|
||
if (!NAT_MAPPING_DELETE_ON_DISSOCIATE_DIRECTOR(Mapping)) {
|
||
KeReleaseSpinLock(&DirectorLock, Irql);
|
||
} else {
|
||
KeReleaseSpinLockFromDpcLevel(&DirectorLock);
|
||
KeAcquireSpinLockAtDpcLevel(&MappingLock);
|
||
NatDeleteMapping(Mapping);
|
||
KeReleaseSpinLock(&MappingLock, Irql);
|
||
}
|
||
return STATUS_SUCCESS;
|
||
|
||
} // NatDirectorDissociateSession
|
||
|
||
|
||
VOID
|
||
NatDirectorQueryInfoSession(
|
||
IN PVOID SessionHandle,
|
||
OUT PIP_NAT_SESSION_MAPPING_STATISTICS Statistics OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked by a director to obtain information
|
||
about a session.
|
||
|
||
Arguments:
|
||
|
||
SessionHandle - the session for which information is required
|
||
|
||
Statistics - receives statistics for the session
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
Environment:
|
||
|
||
Invoked
|
||
--*/
|
||
|
||
{
|
||
KIRQL Irql;
|
||
KeAcquireSpinLock(&MappingLock, &Irql);
|
||
NatQueryInformationMapping(
|
||
(PNAT_DYNAMIC_MAPPING)SessionHandle,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
Statistics
|
||
);
|
||
KeReleaseSpinLock(&MappingLock, Irql);
|
||
} // NatDirectorQueryInfoSession
|