* REVISIONS:
* CSH 01/08-2000 Created
*/
-#include <tcpip.h>
-#include <datagram.h>
-#include <address.h>
-#include <pool.h>
-#include <rawip.h>
-#include <udp.h>
-#include <ip.h>
-#include <fileobjs.h>
+#include "precomp.h"
+
+
+/* List of all address file objects managed by this driver */
LIST_ENTRY AddressFileListHead;
KSPIN_LOCK AddressFileListLock;
+/* List of all connection endpoint file objects managed by this driver */
+LIST_ENTRY ConnectionEndpointListHead;
+KSPIN_LOCK ConnectionEndpointListLock;
/*
- * FUNCTION: Deletes an address file object
+ * FUNCTION: Searches through address file entries to find the first match
* ARGUMENTS:
- * AddrFile = Pointer to address file object to delete
+ * Address = IP address
+ * Port = Port number
+ * Protocol = Protocol number
+ * SearchContext = Pointer to search context
+ * RETURNS:
+ * Pointer to address file, NULL if none was found
*/
-VOID DeleteAddress(
- PADDRESS_FILE AddrFile)
+PADDRESS_FILE AddrSearchFirst(
+ PIP_ADDRESS Address,
+ USHORT Port,
+ USHORT Protocol,
+ PAF_SEARCH SearchContext)
{
- KIRQL OldIrql;
- PLIST_ENTRY CurrentEntry;
- PLIST_ENTRY NextEntry;
- PDATAGRAM_SEND_REQUEST SendRequest;
- PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
-
- TI_DbgPrint(MID_TRACE, ("Called.\n"));
-
- /* Remove address file from the global list */
- KeAcquireSpinLock(&AddressFileListLock, &OldIrql);
- RemoveEntryList(&AddrFile->ListEntry);
- KeReleaseSpinLock(&AddressFileListLock, OldIrql);
-
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
-
- /* FIXME: Kill TCP connections on this address file object */
-
- /* Return pending requests with error */
-
- TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile));
-
- /* Go through pending receive request list and cancel them all */
- CurrentEntry = AddrFile->ReceiveQueue.Flink;
- while (CurrentEntry != &AddrFile->ReceiveQueue) {
- NextEntry = CurrentEntry->Flink;
- ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
- /* Abort the request and free its resources */
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
- (*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_ADDRESS_CLOSED, 0);
- PoolFreeBuffer(ReceiveRequest);
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
- CurrentEntry = NextEntry;
- }
+ SearchContext->Address = Address;
+ SearchContext->Port = Port;
+ SearchContext->Next = AddressFileListHead.Flink;
+ SearchContext->Protocol = Protocol;
- TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile));
-
- /* Go through pending send request list and cancel them all */
- CurrentEntry = AddrFile->TransmitQueue.Flink;
- while (CurrentEntry != &AddrFile->TransmitQueue) {
- NextEntry = CurrentEntry->Flink;
- SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
- /* Abort the request and free its resources */
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
- (*SendRequest->Complete)(SendRequest->Context, STATUS_ADDRESS_CLOSED, 0);
- PoolFreeBuffer(SendRequest);
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
- CurrentEntry = NextEntry;
- }
-
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
- /* Dereference address entry */
- DereferenceObject(AddrFile->ADE);
-
- /* Dereference address cache */
- if (AddrFile->AddrCache)
- DereferenceObject(AddrFile->AddrCache);
+ return AddrSearchNext(SearchContext);
+}
-#ifdef DBG
- /* Remove reference provided at creation time */
- AddrFile->RefCount--;
+BOOLEAN AddrIsBroadcast(
+ PIP_ADDRESS PossibleMatch,
+ PIP_ADDRESS TargetAddress ) {
+ IF_LIST_ITER(IF);
- if (AddrFile->RefCount != 0)
- TI_DbgPrint(DEBUG_REFCOUNT, ("AddrFile->RefCount is (%d) (should be 0).\n", AddrFile->RefCount));
-#endif
-
- PoolFreeBuffer(AddrFile);
+ ForEachInterface(IF) {
+ if( AddrIsEqual( &IF->Unicast, PossibleMatch ) &&
+ AddrIsEqual( &IF->Broadcast, TargetAddress ) )
+ return TRUE;
+ } EndFor(IF);
- TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+ return FALSE;
}
-
-VOID RequestWorker(
- PVOID Context)
/*
- * FUNCTION: Worker routine for processing address file object requests
+ * FUNCTION: Searches through address file entries to find next match
* ARGUMENTS:
- * Context = Pointer to context information (ADDRESS_FILE)
+ * SearchContext = Pointer to search context
+ * RETURNS:
+ * Pointer to address file, NULL if none was found
*/
+PADDRESS_FILE AddrSearchNext(
+ PAF_SEARCH SearchContext)
{
- KIRQL OldIrql;
PLIST_ENTRY CurrentEntry;
- PADDRESS_FILE AddrFile = Context;
-
- TI_DbgPrint(MID_TRACE, ("Called.\n"));
-
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
-
- /* Check it the address file should be deleted */
- if (AF_IS_PENDING(AddrFile, AFF_DELETE)) {
- DATAGRAM_COMPLETION_ROUTINE RtnComplete;
- PVOID RtnContext;
-
- RtnComplete = AddrFile->Complete;
- RtnContext = AddrFile->Context;
-
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
- DeleteAddress(AddrFile);
-
- (*RtnComplete)(RtnContext, TDI_SUCCESS, 0);
-
- TI_DbgPrint(MAX_TRACE, ("Leaving (delete).\n"));
-
- return;
+ PIP_ADDRESS IPAddress;
+ KIRQL OldIrql;
+ PADDRESS_FILE Current = NULL;
+ BOOLEAN Found = FALSE;
+
+ if (IsListEmpty(SearchContext->Next))
+ return NULL;
+
+ CurrentEntry = SearchContext->Next;
+
+ TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
+
+ while (CurrentEntry != &AddressFileListHead) {
+ Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry);
+
+ IPAddress = &Current->Address;
+
+ TI_DbgPrint(DEBUG_ADDRFILE, ("Comparing: ((%d, %d, %s), (%d, %d, %s)).\n",
+ WN2H(Current->Port),
+ Current->Protocol,
+ A2S(IPAddress),
+ WN2H(SearchContext->Port),
+ SearchContext->Protocol,
+ A2S(SearchContext->Address)));
+
+ /* See if this address matches the search criteria */
+ if ((Current->Port == SearchContext->Port) &&
+ (Current->Protocol == SearchContext->Protocol) &&
+ (AddrIsEqual(IPAddress, SearchContext->Address) ||
+ AddrIsBroadcast(IPAddress, SearchContext->Address) ||
+ AddrIsUnspecified(IPAddress))) {
+ /* We've found a match */
+ Found = TRUE;
+ break;
+ }
+ CurrentEntry = CurrentEntry->Flink;
}
- /* Check if there is a pending send request */
- if (AF_IS_PENDING(AddrFile, AFF_SEND)) {
- if (!IsListEmpty(&AddrFile->TransmitQueue)) {
- PDATAGRAM_SEND_REQUEST SendRequest;
+ TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
- CurrentEntry = RemoveHeadList(&AddrFile->TransmitQueue);
- SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
+ if (Found) {
+ SearchContext->Next = CurrentEntry->Flink;
+ return Current;
+ } else
+ return NULL;
+}
- AF_CLR_BUSY(AddrFile);
+VOID AddrFileFree(
+ PVOID Object)
+/*
+ * FUNCTION: Frees an address file object
+ * ARGUMENTS:
+ * Object = Pointer to address file object to free
+ */
+{
+ ExFreePool(Object);
+}
- ReferenceObject(AddrFile);
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+VOID ControlChannelFree(
+ PVOID Object)
+/*
+ * FUNCTION: Frees an address file object
+ * ARGUMENTS:
+ * Object = Pointer to address file object to free
+ */
+{
+ ExFreePool(Object);
+}
- /* The send routine processes the send requests in
- the transmit queue on the address file. When the
- queue is empty the pending send flag is cleared.
- The routine may return with the pending send flag
- set. This can happen if there was not enough free
- resources available to complete all send requests */
- DGSend(AddrFile, SendRequest);
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
- DereferenceObject(AddrFile);
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+VOID DeleteAddress(PADDRESS_FILE AddrFile)
+/*
+ * FUNCTION: Deletes an address file object
+ * ARGUMENTS:
+ * AddrFile = Pointer to address file object to delete
+ */
+{
+ KIRQL OldIrql;
+ PLIST_ENTRY CurrentEntry;
+ PLIST_ENTRY NextEntry;
+ PDATAGRAM_SEND_REQUEST SendRequest;
+ PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
+
+ TI_DbgPrint(MID_TRACE, ("Called.\n"));
+
+ /* Remove address file from the global list */
+ TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
+ RemoveEntryList(&AddrFile->ListEntry);
+ TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
+
+ TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+
+ /* FIXME: Kill TCP connections on this address file object */
+
+ /* Return pending requests with error */
+
+ TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile));
+
+ /* Go through pending receive request list and cancel them all */
+ CurrentEntry = AddrFile->ReceiveQueue.Flink;
+ while (CurrentEntry != &AddrFile->ReceiveQueue) {
+ NextEntry = CurrentEntry->Flink;
+ ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
+ /* Abort the request and free its resources */
+ TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ (*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_ADDRESS_CLOSED, 0);
+ TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+ CurrentEntry = NextEntry;
+ }
+
+ TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile));
+
+ /* Go through pending send request list and cancel them all */
+ CurrentEntry = AddrFile->TransmitQueue.Flink;
+ while (CurrentEntry != &AddrFile->TransmitQueue) {
+ NextEntry = CurrentEntry->Flink;
+ SendRequest = CONTAINING_RECORD(CurrentEntry,
+ DATAGRAM_SEND_REQUEST, ListEntry);
+ /* Abort the request and free its resources */
+ TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ (*SendRequest->Complete)(SendRequest->Context, STATUS_ADDRESS_CLOSED, 0);
+ ExFreePool(SendRequest);
+ TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+ CurrentEntry = NextEntry;
+ }
+
+ TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+
+ (*AddrFile->Free)(AddrFile);
+
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+}
- TI_DbgPrint(MAX_TRACE, ("Leaving (send request).\n"));
- return;
- } else
- /* There was a pending send, but no send request.
- Print a debug message and continue */
- TI_DbgPrint(MIN_TRACE, ("Pending send, but no send request.\n"));
- }
+/*
+ * FUNCTION: Deletes a connection endpoint file object
+ * ARGUMENTS:
+ * Connection = Pointer to connection endpoint to delete
+ */
+VOID DeleteConnectionEndpoint(
+ PCONNECTION_ENDPOINT Connection)
+{
+ KIRQL OldIrql;
- AF_CLR_BUSY(AddrFile);
+ TI_DbgPrint(MID_TRACE, ("Called.\n"));
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ /* Remove connection endpoint from the global list */
+ TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
+ RemoveEntryList(&Connection->ListEntry);
+ TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
- TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
-}
+ ExFreePool(Connection);
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+}
/*
* FUNCTION: Open an address file object
* Status of operation
*/
NTSTATUS FileOpenAddress(
- PTDI_REQUEST Request,
- PTA_ADDRESS_IP Address,
- USHORT Protocol,
- PVOID Options)
+ PTDI_REQUEST Request,
+ PTA_IP_ADDRESS Address,
+ USHORT Protocol,
+ PVOID Options)
{
- PADDRESS_FILE AddrFile;
- IPv4_RAW_ADDRESS IPv4Address;
+ IPv4_RAW_ADDRESS IPv4Address;
+ BOOLEAN Matched;
+ PADDRESS_FILE AddrFile;
- TI_DbgPrint(MID_TRACE, ("Called.\n"));
+ TI_DbgPrint(MID_TRACE, ("Called (Proto %d).\n", Protocol));
- AddrFile = PoolAllocateBuffer(sizeof(ADDRESS_FILE));
- if (!AddrFile) {
- TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ AddrFile = ExAllocatePool(NonPagedPool, sizeof(ADDRESS_FILE));
+ if (!AddrFile) {
+ TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- TI_DbgPrint(DEBUG_ADDRFILE, ("Address file object allocated at (0x%X).\n", AddrFile));
+ TI_DbgPrint(DEBUG_ADDRFILE, ("Address file object allocated at (0x%X).\n", AddrFile));
- RtlZeroMemory(AddrFile, sizeof(ADDRESS_FILE));
+ RtlZeroMemory(AddrFile, sizeof(ADDRESS_FILE));
- /* Make sure address is a local unicast address or 0 */
+ AddrFile->Free = AddrFileFree;
- /* Locate address entry. If specified address is 0, a random address is chosen */
+ /* Make sure address is a local unicast address or 0 */
- IPv4Address = Address->Address[0].Address[0].in_addr;
- if (IPv4Address == 0)
- AddrFile->ADE = IPGetDefaultADE(ADE_UNICAST);
- else
- AddrFile->ADE = AddrLocateADEv4(IPv4Address);
+ /* Locate address entry. If specified address is 0, a random address is chosen */
- if (!AddrFile->ADE) {
- PoolFreeBuffer(AddrFile);
- TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", DN2H(IPv4Address)));
- return STATUS_INVALID_PARAMETER;
- }
+ /* FIXME: IPv4 only */
+ AddrFile->Family = Address->Address[0].AddressType;
+ IPv4Address = Address->Address[0].Address[0].in_addr;
+ if (IPv4Address == 0)
+ Matched = IPGetDefaultAddress(&AddrFile->Address);
+ else
+ Matched = AddrLocateADEv4(IPv4Address, &AddrFile->Address);
- TI_DbgPrint(DEBUG_ADDRFILE, ("Opening address (0x%X) for communication.\n",
- DN2H(AddrFile->ADE->Address->Address.IPv4Address)));
-
- /* Protocol specific handling */
- switch (Protocol) {
- case IPPROTO_TCP:
- /* FIXME: TCP */
- TI_DbgPrint(MIN_TRACE, ("TCP is not supported.\n"));
- DereferenceObject(AddrFile->ADE);
- PoolFreeBuffer(AddrFile);
- return STATUS_INVALID_PARAMETER;
- case IPPROTO_UDP:
- /* FIXME: If specified port is 0, a port is chosen dynamically */
- AddrFile->Port = Address->Address[0].Address[0].sin_port;
- AddrFile->Send = UDPSendDatagram;
- break;
- default:
- /* Use raw IP for all other protocols */
- AddrFile->Send = RawIPSendDatagram;
- break;
- }
+ if (!Matched) {
+ ExFreePool(AddrFile);
+ TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", DN2H(IPv4Address)));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ TI_DbgPrint(MID_TRACE, ("Opening address %s for communication (P=%d U=%d).\n",
+ A2S(&AddrFile->Address), Protocol, IPPROTO_UDP));
+
+ /* Protocol specific handling */
+ switch (Protocol) {
+ case IPPROTO_TCP:
+ AddrFile->Port =
+ TCPAllocatePort(Address->Address[0].Address[0].sin_port);
+ AddrFile->Send = NULL; /* TCPSendData */
+ break;
+
+ case IPPROTO_UDP:
+ TI_DbgPrint(MID_TRACE,("Allocating udp port\n"));
+ AddrFile->Port =
+ UDPAllocatePort(Address->Address[0].Address[0].sin_port);
+ TI_DbgPrint(MID_TRACE,("Setting port %d (wanted %d)\n",
+ AddrFile->Port,
+ Address->Address[0].Address[0].sin_port));
+ AddrFile->Send = UDPSendDatagram;
+ break;
- /* Set protocol */
- AddrFile->Protocol = Protocol;
-
- /* Initialize receive and transmit queues */
- InitializeListHead(&AddrFile->ReceiveQueue);
- InitializeListHead(&AddrFile->TransmitQueue);
+ default:
+ /* Use raw IP for all other protocols */
+ AddrFile->Port = 0;
+ AddrFile->Send = RawIPSendDatagram;
+ break;
+ }
- /* Initialize work queue item. We use this for pending requests */
- ExInitializeWorkItem(&AddrFile->WorkItem, RequestWorker, AddrFile);
+ TI_DbgPrint(MID_TRACE, ("IP protocol number for address file object is %d.\n",
+ Protocol));
- /* Initialize spin lock that protects the address file object */
- KeInitializeSpinLock(&AddrFile->Lock);
+ TI_DbgPrint(MID_TRACE, ("Port number for address file object is %d.\n",
+ WN2H(AddrFile->Port)));
- /* Reference the object */
- AddrFile->RefCount = 1;
+ /* Set protocol */
+ AddrFile->Protocol = Protocol;
- /* Set valid flag so the address can be used */
- AF_SET_VALID(AddrFile);
+ /* Initialize receive and transmit queues */
+ InitializeListHead(&AddrFile->ReceiveQueue);
+ InitializeListHead(&AddrFile->TransmitQueue);
- /* Return address file object */
- Request->Handle.AddressHandle = AddrFile;
+ /* Initialize spin lock that protects the address file object */
+ KeInitializeSpinLock(&AddrFile->Lock);
- /* Add address file to global list */
- ExInterlockedInsertTailList(&AddressFileListHead, &AddrFile->ListEntry, &AddressFileListLock);
+ /* Set valid flag so the address can be used */
+ AF_SET_VALID(AddrFile);
- TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+ /* Return address file object */
+ Request->Handle.AddressHandle = AddrFile;
- return STATUS_SUCCESS;
+ /* Add address file to global list */
+ ExInterlockedInsertTailList(
+ &AddressFileListHead,
+ &AddrFile->ListEntry,
+ &AddressFileListLock);
+
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+
+ return STATUS_SUCCESS;
}
* Status of operation
*/
NTSTATUS FileCloseAddress(
- PTDI_REQUEST Request)
+ PTDI_REQUEST Request)
{
- KIRQL OldIrql;
- PADDRESS_FILE AddrFile;
- NTSTATUS Status = STATUS_SUCCESS;
+ KIRQL OldIrql;
+ PADDRESS_FILE AddrFile;
+ NTSTATUS Status = STATUS_SUCCESS;
- TI_DbgPrint(MID_TRACE, ("Called.\n"));
+ TI_DbgPrint(MID_TRACE, ("Called.\n"));
- AddrFile = Request->Handle.AddressHandle;
+ AddrFile = Request->Handle.AddressHandle;
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+ TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
- if ((!AF_IS_BUSY(AddrFile)) && (AddrFile->RefCount == 1)) {
- /* Set address file object exclusive to us */
- AF_SET_BUSY(AddrFile);
- AF_CLR_VALID(AddrFile);
+ /* Set address file object exclusive to us */
+ AF_SET_BUSY(AddrFile);
+ AF_CLR_VALID(AddrFile);
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
- DeleteAddress(AddrFile);
- } else {
- if (!AF_IS_PENDING(AddrFile, AFF_DELETE)) {
- AddrFile->Complete = Request->RequestNotifyObject;
- AddrFile->Context = Request->RequestContext;
+ /* Protocol specific handling */
+ switch (AddrFile->Protocol) {
+ case IPPROTO_TCP:
+ TCPFreePort( AddrFile->Port );
+ if( AddrFile->Listener )
+ TCPClose( AddrFile->Listener );
+ break;
- /* Shedule address file for deletion */
- AF_SET_PENDING(AddrFile, AFF_DELETE);
- AF_CLR_VALID(AddrFile);
+ case IPPROTO_UDP:
+ UDPFreePort( AddrFile->Port );
+ break;
+ }
- if (!AF_IS_BUSY(AddrFile)) {
- /* Worker function is not running, so shedule it to run */
- AF_SET_BUSY(AddrFile);
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
- ExQueueWorkItem(&AddrFile->WorkItem, CriticalWorkQueue);
- } else
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ DeleteAddress(AddrFile);
- TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n"));
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
- return STATUS_PENDING;
- } else
- Status = STATUS_ADDRESS_CLOSED;
-
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
- }
-
- TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
-
- return Status;
+ return Status;
}
/*
* FUNCTION: Opens a connection file object
* ARGUMENTS:
- * Request = Pointer to TDI request structure for this request
+ * Request = Pointer to TDI request structure for this request
+ * ClientContext = Pointer to client context information
* RETURNS:
* Status of operation
*/
NTSTATUS FileOpenConnection(
- PTDI_REQUEST Request)
+ PTDI_REQUEST Request,
+ PVOID ClientContext)
{
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ PCONNECTION_ENDPOINT Connection;
+
+ TI_DbgPrint(MID_TRACE, ("Called.\n"));
+
+ Connection = TCPAllocateConnectionEndpoint( ClientContext );
+
+ if( !Connection ) return STATUS_NO_MEMORY;
+
+ Status = TCPSocket( Connection, AF_INET, SOCK_STREAM, IPPROTO_TCP );
+
+ /* Return connection endpoint file object */
+ Request->Handle.ConnectionContext = Connection;
+
+ /* Add connection endpoint to global list */
+ ExInterlockedInsertTailList(
+ &ConnectionEndpointListHead,
+ &Connection->ListEntry,
+ &ConnectionEndpointListLock);
+
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+
+ return STATUS_SUCCESS;
}
+/*
+ * FUNCTION: Find a connection by examining the context field. This
+ * is needed in some situations where a FIN reply is needed after a
+ * socket is formally broken.
+ * ARGUMENTS:
+ * Request = Pointer to TDI request structure for this request
+ * RETURNS:
+ * Status of operation
+ */
+PCONNECTION_ENDPOINT FileFindConnectionByContext( PVOID Context ) {
+ PLIST_ENTRY Entry;
+ KIRQL OldIrql;
+ PCONNECTION_ENDPOINT Connection = NULL;
+
+ TcpipAcquireSpinLock( &ConnectionEndpointListLock, &OldIrql );
+
+ for( Entry = ConnectionEndpointListHead.Flink;
+ Entry != &ConnectionEndpointListHead;
+ Entry = Entry->Flink ) {
+ Connection =
+ CONTAINING_RECORD( Entry, CONNECTION_ENDPOINT, ListEntry );
+ if( Connection->SocketContext == Context ) break;
+ else Connection = NULL;
+ }
+
+ TcpipReleaseSpinLock( &ConnectionEndpointListLock, OldIrql );
+
+ return Connection;
+}
+
/*
* FUNCTION: Closes an connection file object
* ARGUMENTS:
- * Request = Pointer to TDI request structure for this request
+ * Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
NTSTATUS FileCloseConnection(
- PTDI_REQUEST Request)
+ PTDI_REQUEST Request)
{
- return STATUS_NOT_IMPLEMENTED;
+ PCONNECTION_ENDPOINT Connection;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TI_DbgPrint(MID_TRACE, ("Called.\n"));
+
+ Connection = Request->Handle.ConnectionContext;
+
+ TcpipRecursiveMutexEnter( &TCPLock, TRUE );
+ TCPClose(Connection);
+ DeleteConnectionEndpoint(Connection);
+ TcpipRecursiveMutexLeave( &TCPLock );
+
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+
+ return Status;
}
/*
* FUNCTION: Opens a control channel file object
* ARGUMENTS:
- * Request = Pointer to TDI request structure for this request
+ * Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
NTSTATUS FileOpenControlChannel(
PTDI_REQUEST Request)
{
- return STATUS_NOT_IMPLEMENTED;
-}
+ PCONTROL_CHANNEL ControlChannel;
+ TI_DbgPrint(MID_TRACE, ("Called.\n"));
+ ControlChannel = ExAllocatePool(NonPagedPool, sizeof(*ControlChannel));
+
+ if (!ControlChannel) {
+ TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(ControlChannel, sizeof(CONTROL_CHANNEL));
+
+ /* Make sure address is a local unicast address or 0 */
+
+ /* Locate address entry. If specified address is 0, a random address is chosen */
+
+ /* Initialize receive and transmit queues */
+ InitializeListHead(&ControlChannel->ListEntry);
+
+ /* Initialize spin lock that protects the address file object */
+ KeInitializeSpinLock(&ControlChannel->Lock);
+
+ /* Return address file object */
+ Request->Handle.ControlChannel = ControlChannel;
+
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+
+ return STATUS_SUCCESS;
+}
/*
* FUNCTION: Closes a control channel file object
* ARGUMENTS:
- * Request = Pointer to TDI request structure for this request
+ * Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
NTSTATUS FileCloseControlChannel(
- PTDI_REQUEST Request)
+ PTDI_REQUEST Request)
{
- return STATUS_NOT_IMPLEMENTED;
+ PCONTROL_CHANNEL ControlChannel = Request->Handle.ControlChannel;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ ExFreePool(ControlChannel);
+ Request->Handle.ControlChannel = NULL;
+
+ return Status;
}
/* EOF */