return AddrSearchNext(SearchContext);
}
-BOOLEAN AddrIsBroadcast(
- PIP_ADDRESS PossibleMatch,
- PIP_ADDRESS TargetAddress ) {
+BOOLEAN AddrIsBroadcastMatch(
+ PIP_ADDRESS UnicastAddress,
+ PIP_ADDRESS BroadcastAddress ) {
IF_LIST_ITER(IF);
ForEachInterface(IF) {
- if( AddrIsEqual( &IF->Unicast, PossibleMatch ) &&
- AddrIsEqual( &IF->Broadcast, TargetAddress ) )
+ if ((AddrIsUnspecified(UnicastAddress) ||
+ AddrIsEqual(&IF->Unicast, UnicastAddress)) &&
+ (AddrIsEqual(&IF->Broadcast, BroadcastAddress)))
return TRUE;
} EndFor(IF);
return FALSE;
}
+BOOLEAN AddrReceiveMatch(
+ PIP_ADDRESS LocalAddress,
+ PIP_ADDRESS RemoteAddress)
+{
+ if (AddrIsEqual(LocalAddress, RemoteAddress))
+ {
+ /* Unicast address match */
+ return TRUE;
+ }
+
+ if (AddrIsBroadcastMatch(LocalAddress, RemoteAddress))
+ {
+ /* Broadcast address match */
+ return TRUE;
+ }
+
+ if (AddrIsUnspecified(LocalAddress))
+ {
+ /* Local address unspecified */
+ return TRUE;
+ }
+
+ if (AddrIsUnspecified(RemoteAddress))
+ {
+ /* Remote address unspecified */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/*
* FUNCTION: Searches through address file entries to find next match
* ARGUMENTS:
/* 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))) {
+ (AddrReceiveMatch(IPAddress, SearchContext->Address))) {
/* We've found a match */
Found = TRUE;
break;
* Object = Pointer to address file object to free
*/
{
- ExFreePool(Object);
-}
-
-
-VOID ControlChannelFree(
- PVOID Object)
-/*
- * FUNCTION: Frees an address file object
- * ARGUMENTS:
- * Object = Pointer to address file object to free
- */
-{
- ExFreePool(Object);
-}
-
-
-VOID DeleteAddress(PADDRESS_FILE AddrFile)
-/*
- * FUNCTION: Deletes an address file object
- * ARGUMENTS:
- * AddrFile = Pointer to address file object to delete
- */
-{
+ PADDRESS_FILE AddrFile = Object;
KIRQL OldIrql;
- PLIST_ENTRY CurrentEntry;
- PLIST_ENTRY NextEntry;
- PDATAGRAM_SEND_REQUEST SendRequest;
PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
+ PDATAGRAM_SEND_REQUEST SendRequest;
+ PLIST_ENTRY CurrentEntry;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
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;
+ while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
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;
+ (*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_CANCELLED, 0);
+ /* ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); FIXME: WTF? */
}
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;
+ while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
+ SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
+ (*SendRequest->Complete)(SendRequest->Context, STATUS_CANCELLED, 0);
+ ExFreePoolWithTag(SendRequest, DATAGRAM_SEND_TAG);
}
- TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ /* Protocol specific handling */
+ switch (AddrFile->Protocol) {
+ case IPPROTO_TCP:
+ TCPFreePort( AddrFile->Port );
+ break;
+
+ case IPPROTO_UDP:
+ UDPFreePort( AddrFile->Port );
+ break;
+ }
- (*AddrFile->Free)(AddrFile);
+ RemoveEntityByContext(AddrFile);
- TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+ ExFreePoolWithTag(Object, ADDR_FILE_TAG);
}
+VOID ControlChannelFree(
+ PVOID Object)
/*
- * FUNCTION: Deletes a connection endpoint file object
+ * FUNCTION: Frees an address file object
* ARGUMENTS:
- * Connection = Pointer to connection endpoint to delete
+ * Object = Pointer to address file object to free
*/
-VOID DeleteConnectionEndpoint(
- PCONNECTION_ENDPOINT Connection)
{
- KIRQL OldIrql;
-
- TI_DbgPrint(MID_TRACE, ("Called.\n"));
-
- /* Remove connection endpoint from the global list */
- TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
- RemoveEntryList(&Connection->ListEntry);
- TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
-
- ExFreePool(Connection);
-
- TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+ ExFreePoolWithTag(Object, CONTROL_CHANNEL_TAG);
}
+
/*
* FUNCTION: Open an address file object
* ARGUMENTS:
USHORT Protocol,
PVOID Options)
{
- IPv4_RAW_ADDRESS IPv4Address;
- BOOLEAN Matched;
PADDRESS_FILE AddrFile;
TI_DbgPrint(MID_TRACE, ("Called (Proto %d).\n", Protocol));
- AddrFile = ExAllocatePool(NonPagedPool, sizeof(ADDRESS_FILE));
+ AddrFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(ADDRESS_FILE),
+ ADDR_FILE_TAG);
if (!AddrFile) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(AddrFile, sizeof(ADDRESS_FILE));
+ AddrFile->RefCount = 1;
AddrFile->Free = AddrFileFree;
- /* Make sure address is a local unicast address or 0 */
-
- /* Locate address entry. If specified address is 0, a random address is chosen */
+ /* Set our default TTL */
+ AddrFile->TTL = 128;
+ /* Make sure address is a local unicast address or 0 */
/* 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);
-
- if (!Matched) {
- ExFreePool(AddrFile);
- TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", DN2H(IPv4Address)));
- return STATUS_INVALID_PARAMETER;
+ AddrFile->Address.Address.IPv4Address = Address->Address[0].Address[0].in_addr;
+ AddrFile->Address.Type = IP_ADDRESS_V4;
+
+ if (!AddrIsUnspecified(&AddrFile->Address) &&
+ !AddrLocateInterface(&AddrFile->Address)) {
+ ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
+ TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", A2S(&AddrFile->Address)));
+ return STATUS_INVALID_PARAMETER;
}
TI_DbgPrint(MID_TRACE, ("Opening address %s for communication (P=%d U=%d).\n",
case IPPROTO_TCP:
AddrFile->Port =
TCPAllocatePort(Address->Address[0].Address[0].sin_port);
+
+ if ((Address->Address[0].Address[0].sin_port &&
+ AddrFile->Port != Address->Address[0].Address[0].sin_port) ||
+ AddrFile->Port == 0xffff)
+ {
+ ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ AddEntity(CO_TL_ENTITY, AddrFile, CO_TL_TCP);
+
AddrFile->Send = NULL; /* TCPSendData */
break;
TI_DbgPrint(MID_TRACE,("Allocating udp port\n"));
AddrFile->Port =
UDPAllocatePort(Address->Address[0].Address[0].sin_port);
+
+ if ((Address->Address[0].Address[0].sin_port &&
+ AddrFile->Port != Address->Address[0].Address[0].sin_port) ||
+ AddrFile->Port == 0xffff)
+ {
+ ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
+ return STATUS_INVALID_PARAMETER;
+ }
+
TI_DbgPrint(MID_TRACE,("Setting port %d (wanted %d)\n",
AddrFile->Port,
Address->Address[0].Address[0].sin_port));
+
+ AddEntity(CL_TL_ENTITY, AddrFile, CL_TL_UDP);
+
AddrFile->Send = UDPSendDatagram;
break;
+ case IPPROTO_ICMP:
+ AddrFile->Port = 0;
+ AddrFile->Send = ICMPSendDatagram;
+
+ /* FIXME: Verify this */
+ AddEntity(ER_ENTITY, AddrFile, ER_ICMP);
+ break;
+
default:
/* Use raw IP for all other protocols */
AddrFile->Port = 0;
AddrFile->Send = RawIPSendDatagram;
+
+ /* FIXME: Verify this */
+ AddEntity(CL_TL_ENTITY, AddrFile, 0);
break;
}
/* Initialize spin lock that protects the address file object */
KeInitializeSpinLock(&AddrFile->Lock);
- /* Set valid flag so the address can be used */
- AF_SET_VALID(AddrFile);
-
/* Return address file object */
Request->Handle.AddressHandle = AddrFile;
NTSTATUS FileCloseAddress(
PTDI_REQUEST Request)
{
+ PADDRESS_FILE AddrFile = Request->Handle.AddressHandle;
KIRQL OldIrql;
- PADDRESS_FILE AddrFile;
- NTSTATUS Status = STATUS_SUCCESS;
- TI_DbgPrint(MID_TRACE, ("Called.\n"));
+ if (!Request->Handle.AddressHandle) return STATUS_INVALID_PARAMETER;
- AddrFile = Request->Handle.AddressHandle;
+ LockObject(AddrFile, &OldIrql);
+ /* We have to close this connection because we started it */
+ if( AddrFile->Listener )
+ TCPClose( AddrFile->Listener );
+ if( AddrFile->Connection )
+ DereferenceObject( AddrFile->Connection );
+ UnlockObject(AddrFile, OldIrql);
- TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
-
- /* Set address file object exclusive to us */
- AF_SET_BUSY(AddrFile);
- AF_CLR_VALID(AddrFile);
-
- TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
- /* Protocol specific handling */
- switch (AddrFile->Protocol) {
- case IPPROTO_TCP:
- TCPFreePort( AddrFile->Port );
- if( AddrFile->Listener )
- TCPClose( AddrFile->Listener );
- break;
-
- case IPPROTO_UDP:
- UDPFreePort( AddrFile->Port );
- break;
- }
-
- DeleteAddress(AddrFile);
+ DereferenceObject(AddrFile);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
- return Status;
+ return STATUS_SUCCESS;
}
Status = TCPSocket( Connection, AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( !NT_SUCCESS(Status) ) {
- TCPFreeConnectionEndpoint( Connection );
+ DereferenceObject( Connection );
return Status;
}
/* 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:
PTDI_REQUEST Request)
{
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 );
+ if (!Connection) return STATUS_INVALID_PARAMETER;
+
+ TCPClose( Connection );
+
+ Request->Handle.ConnectionContext = NULL;
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
- return Status;
+ return STATUS_SUCCESS;
}
-
/*
* FUNCTION: Opens a control channel file object
* ARGUMENTS:
PCONTROL_CHANNEL ControlChannel;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
- ControlChannel = ExAllocatePool(NonPagedPool, sizeof(*ControlChannel));
+ ControlChannel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ControlChannel),
+ CONTROL_CHANNEL_TAG);
if (!ControlChannel) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
/* Initialize spin lock that protects the address file object */
KeInitializeSpinLock(&ControlChannel->Lock);
+ ControlChannel->RefCount = 1;
+ ControlChannel->Free = ControlChannelFree;
+
/* Return address file object */
Request->Handle.ControlChannel = ControlChannel;
NTSTATUS FileCloseControlChannel(
PTDI_REQUEST Request)
{
- PCONTROL_CHANNEL ControlChannel = Request->Handle.ControlChannel;
- NTSTATUS Status = STATUS_SUCCESS;
+ if (!Request->Handle.ControlChannel) return STATUS_INVALID_PARAMETER;
+
+ DereferenceObject((PCONTROL_CHANNEL)Request->Handle.ControlChannel);
- ExFreePool(ControlChannel);
Request->Handle.ControlChannel = NULL;
- return Status;
+ return STATUS_SUCCESS;
}
/* EOF */