return AddrSearchNext(SearchContext);
}
+BOOLEAN AddrIsBroadcast(
+ PIP_ADDRESS PossibleMatch,
+ PIP_ADDRESS TargetAddress ) {
+ IF_LIST_ITER(IF);
+
+ ForEachInterface(IF) {
+ if( AddrIsEqual( &IF->Unicast, PossibleMatch ) &&
+ AddrIsEqual( &IF->Broadcast, TargetAddress ) )
+ return TRUE;
+ } EndFor(IF);
+
+ return FALSE;
+}
+
/*
* FUNCTION: Searches through address file entries to find next match
* ARGUMENTS:
CurrentEntry = SearchContext->Next;
- KeAcquireSpinLock(&AddressFileListLock, &OldIrql);
+ TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
while (CurrentEntry != &AddressFileListHead) {
Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry);
- IPAddress = Current->ADE->Address;
+ IPAddress = &Current->Address;
TI_DbgPrint(DEBUG_ADDRFILE, ("Comparing: ((%d, %d, %s), (%d, %d, %s)).\n",
WN2H(Current->Port),
A2S(SearchContext->Address)));
/* See if this address matches the search criteria */
- if (((Current->Port == SearchContext->Port) &&
+ if ((Current->Port == SearchContext->Port) &&
(Current->Protocol == SearchContext->Protocol) &&
- (AddrIsEqual(IPAddress, SearchContext->Address))) ||
- (AddrIsUnspecified(IPAddress))) {
+ (AddrIsEqual(IPAddress, SearchContext->Address) ||
+ AddrIsBroadcast(IPAddress, SearchContext->Address) ||
+ AddrIsUnspecified(IPAddress))) {
/* We've found a match */
Found = TRUE;
break;
CurrentEntry = CurrentEntry->Flink;
}
- KeReleaseSpinLock(&AddressFileListLock, OldIrql);
+ TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
if (Found) {
SearchContext->Next = CurrentEntry->Flink;
}
-VOID DeleteAddress(
- PADDRESS_FILE AddrFile)
+VOID DeleteAddress(PADDRESS_FILE AddrFile)
/*
* FUNCTION: Deletes an address file object
* ARGUMENTS:
TI_DbgPrint(MID_TRACE, ("Called.\n"));
/* Remove address file from the global list */
- KeAcquireSpinLock(&AddressFileListLock, &OldIrql);
+ TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
RemoveEntryList(&AddrFile->ListEntry);
- KeReleaseSpinLock(&AddressFileListLock, OldIrql);
+ TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+ TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
/* FIXME: Kill TCP connections on this address file object */
NextEntry = CurrentEntry->Flink;
ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
/* Abort the request and free its resources */
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
(*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_ADDRESS_CLOSED, 0);
- ExFreePool(ReceiveRequest);
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+ TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
CurrentEntry = NextEntry;
}
CurrentEntry = AddrFile->TransmitQueue.Flink;
while (CurrentEntry != &AddrFile->TransmitQueue) {
NextEntry = CurrentEntry->Flink;
- SendRequest = CONTAINING_RECORD(CurrentEntry,
+ SendRequest = CONTAINING_RECORD(CurrentEntry,
DATAGRAM_SEND_REQUEST, ListEntry);
/* Abort the request and free its resources */
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
(*SendRequest->Complete)(SendRequest->Context, STATUS_ADDRESS_CLOSED, 0);
ExFreePool(SendRequest);
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+ TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
CurrentEntry = NextEntry;
}
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
- /* Dereference address entry */
- DereferenceObject(AddrFile->ADE);
+ TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
- /* Dereference address cache */
- if (AddrFile->AddrCache)
- DereferenceObject(AddrFile->AddrCache);
-
-#ifdef DBG
- /* Remove reference provided at creation time */
- AddrFile->RefCount--;
-
- if (AddrFile->RefCount != 0)
- TI_DbgPrint(DEBUG_REFCOUNT, ("AddrFile->RefCount is (%d) (should be 0).\n", AddrFile->RefCount));
-#endif
-
(*AddrFile->Free)(AddrFile);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
TI_DbgPrint(MID_TRACE, ("Called.\n"));
/* Remove connection endpoint from the global list */
- KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
+ TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
RemoveEntryList(&Connection->ListEntry);
- KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
-
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
-
- /* Dereference and remove the address file if it exists */
- if (Connection->AddressFile) {
- DereferenceObject(Connection->AddressFile);
- }
-
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
-#ifdef DBG
- /* Remove reference provided at creation time */
- Connection->RefCount--;
-
- if (Connection->RefCount != 0)
- TI_DbgPrint(DEBUG_REFCOUNT, ("Connection->RefCount is (%d) (should be 0).\n",
- Connection->RefCount));
-#endif
+ TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
ExFreePool(Connection);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
-
-VOID STDCALL RequestWorker(
- PVOID Context)
-/*
- * FUNCTION: Worker routine for processing address file object requests
- * ARGUMENTS:
- * Context = Pointer to context information (ADDRESS_FILE)
- */
-{
- 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;
- }
-
- /* Check if there is a pending send request */
- if (AF_IS_PENDING(AddrFile, AFF_SEND)) {
- if (!IsListEmpty(&AddrFile->TransmitQueue)) {
- PDATAGRAM_SEND_REQUEST SendRequest;
-
- CurrentEntry = RemoveHeadList(&AddrFile->TransmitQueue);
- SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
-
- AF_CLR_BUSY(AddrFile);
-
- ReferenceObject(AddrFile);
-
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
- /* 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);
-
- 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"));
- }
-
- AF_CLR_BUSY(AddrFile);
-
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
- TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
-}
-
-
/*
* FUNCTION: Open an address file object
* ARGUMENTS:
USHORT Protocol,
PVOID Options)
{
- PADDRESS_FILE AddrFile;
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 = ExAllocatePool(NonPagedPool, sizeof(ADDRESS_FILE));
if (!AddrFile) {
/* Locate address entry. If specified address is 0, a random address is chosen */
/* FIXME: IPv4 only */
+ AddrFile->Family = Address->Address[0].AddressType;
IPv4Address = Address->Address[0].Address[0].in_addr;
if (IPv4Address == 0)
- AddrFile->ADE = IPGetDefaultADE(ADE_UNICAST);
+ Matched = IPGetDefaultAddress(&AddrFile->Address);
else
- AddrFile->ADE = AddrLocateADEv4(IPv4Address);
+ Matched = AddrLocateADEv4(IPv4Address, &AddrFile->Address);
- if (!AddrFile->ADE) {
+ 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.\n",
- A2S(AddrFile->ADE->Address)));
+ 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:
- /* FIXME: If specified port is 0, a port is chosen dynamically */
- AddrFile->Port = Address->Address[0].Address[0].sin_port;
- AddrFile->Send = NULL; /* TCPSendData */
- break;
+ AddrFile->Port =
+ TCPAllocatePort(Address->Address[0].Address[0].sin_port);
+ AddrFile->Send = NULL; /* TCPSendData */
+ break;
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;
+ 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;
default:
/* Use raw IP for all other protocols */
/* Set protocol */
AddrFile->Protocol = Protocol;
-
+
/* Initialize receive and transmit queues */
InitializeListHead(&AddrFile->ReceiveQueue);
InitializeListHead(&AddrFile->TransmitQueue);
- /* Initialize work queue item. We use this for pending requests */
- ExInitializeWorkItem(&AddrFile->WorkItem, RequestWorker, AddrFile);
-
/* Initialize spin lock that protects the address file object */
KeInitializeSpinLock(&AddrFile->Lock);
- /* Reference the object */
- AddrFile->RefCount = 1;
-
/* Set valid flag so the address can be used */
AF_SET_VALID(AddrFile);
AddrFile = Request->Handle.AddressHandle;
- KeAcquireSpinLock(&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);
-
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
- DeleteAddress(AddrFile);
- } else {
- if (!AF_IS_PENDING(AddrFile, AFF_DELETE)) {
- AddrFile->Complete = Request->RequestNotifyObject;
- AddrFile->Context = Request->RequestContext;
-
- /* Shedule address file for deletion */
- AF_SET_PENDING(AddrFile, AFF_DELETE);
- AF_CLR_VALID(AddrFile);
+ TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
- 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);
+ /* Set address file object exclusive to us */
+ AF_SET_BUSY(AddrFile);
+ AF_CLR_VALID(AddrFile);
- TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n"));
+ TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
- return STATUS_PENDING;
- } else
- Status = STATUS_ADDRESS_CLOSED;
+ /* Protocol specific handling */
+ switch (AddrFile->Protocol) {
+ case IPPROTO_TCP:
+ TCPFreePort( AddrFile->Port );
+ if( AddrFile->Listener )
+ TCPClose( AddrFile->Listener );
+ break;
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ case IPPROTO_UDP:
+ UDPFreePort( AddrFile->Port );
+ break;
}
+ DeleteAddress(AddrFile);
+
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return Status;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
-
- Status = TCPSocket( Connection, AF_INET, SOCK_STREAM, IPPROTO_TCP );
- DbgPrint("STATUS from OSKITTCP was %08x\n", Status);
-
- /* Initialize received segments queue */
- InitializeListHead(&Connection->ReceivedSegments);
+ Connection = TCPAllocateConnectionEndpoint( ClientContext );
-TI_DbgPrint(MIN_TRACE, ("X1 cur 0x%x\n", &Connection->ReceivedSegments));
-TI_DbgPrint(MIN_TRACE, ("X1 Flink 0x%x\n", Connection->ReceivedSegments.Flink));
-TI_DbgPrint(MIN_TRACE, ("X1 Blink 0x%x\n", Connection->ReceivedSegments.Blink));
+ if( !Connection ) return STATUS_NO_MEMORY;
+ Status = TCPSocket( Connection, AF_INET, SOCK_STREAM, IPPROTO_TCP );
/* Return connection endpoint file object */
Request->Handle.ConnectionContext = Connection;
}
+/*
+ * 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:
Connection = Request->Handle.ConnectionContext;
+ TcpipRecursiveMutexEnter( &TCPLock, TRUE );
TCPClose(Connection);
DeleteConnectionEndpoint(Connection);
+ TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
/* Initialize spin lock that protects the address file object */
KeInitializeSpinLock(&ControlChannel->Lock);
- /* Reference the object */
- ControlChannel->RefCount = 1;
-
/* Return address file object */
Request->Handle.ControlChannel = ControlChannel;
return STATUS_SUCCESS;
}
-
/*
* FUNCTION: Closes a control channel file object
* ARGUMENTS: