- Our code was a bit confused about close vs cleanup irps in tcpip. We now

interpret and implement them both properly, preparing for close in cleanup
   then actually deallocating in close.
 - AFD should have been keeping extra references to TCP resources, because 
   the handles will be closed by the handle sweeper at process shutdown.
 - Fix failure cases for pendable TCP requests and add SEL_FIN when a socket
   is closed at oskit, but closing up at tcpip.sys.
 - Fix some breakage from my previous commit re: bind the zero address.  We 
   now ask the connection for the right address if we are one, and plumb 
   the request all the way to tcp, which is deciding what adapter to send to
   anyway.
 - Fix one error code in udp, properly reporting network unreachable.

svn path=/trunk/; revision=39687
This commit is contained in:
Art Yerkes 2009-02-19 20:14:39 +00:00
parent 6de6188c1a
commit 47cb22722f
13 changed files with 253 additions and 88 deletions

View file

@ -351,6 +351,10 @@ DWORD MsafdReturnWithErrno(NTSTATUS Status,
DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n");
*Errno = WSAEINVAL;
break;
case STATUS_CANCELLED:
DbgPrint("MSAFD: STATUS_CANCELLED\n");
*Errno = WSAENOTSOCK;
break;
default:
DbgPrint("MSAFD: Error %x is unknown\n", Status);
*Errno = WSAEINVAL;

View file

@ -33,6 +33,11 @@ NTSTATUS WarmSocketForBind( PAFD_FCB FCB ) {
&FCB->AddressFile.Handle,
&FCB->AddressFile.Object );
if (NT_SUCCESS(Status))
{
ObReferenceObject(FCB->AddressFile.Object);
}
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
return Status;

View file

@ -29,6 +29,11 @@ NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ) {
FCB->Connection.Object );
}
if (NT_SUCCESS(Status))
{
ObReferenceObject(FCB->Connection.Object);
}
return Status;
}

View file

@ -110,7 +110,8 @@ AfdGetSockOrPeerName( PDEVICE_OBJECT DeviceObject, PIRP Irp,
}
Status = TdiQueryInformation
( FCB->AddressFile.Object,
( FCB->Connection.Object ?
FCB->Connection.Object : FCB->AddressFile.Object,
TDI_QUERY_ADDRESS_INFO,
Mdl );
} else {

View file

@ -224,11 +224,16 @@ VOID DestroySocket( PAFD_FCB FCB ) {
if( FCB->TdiDeviceName.Buffer )
ExFreePool(FCB->TdiDeviceName.Buffer);
/* HACK HACK HACK */
TdiCloseDevice( FCB->Connection.Handle,
FCB->Connection.Object );
TdiCloseDevice( FCB->AddressFile.Handle,
FCB->AddressFile.Object );
if (FCB->Connection.Object)
{
NtClose(FCB->Connection.Handle);
ObDereferenceObject(FCB->Connection.Object);
}
if (FCB->AddressFile.Object)
{
NtClose(FCB->AddressFile.Handle);
ObDereferenceObject(FCB->AddressFile.Object);
}
ExFreePool(FCB);
AFD_DbgPrint(MIN_TRACE,("Deleted (%x)\n", FCB));

View file

@ -34,7 +34,8 @@ static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
}
static VOID HandleEOFOnIrp( PAFD_FCB FCB, NTSTATUS Status, UINT Information ) {
if( Status == STATUS_SUCCESS && Information == 0 ) {
if( !NT_SUCCESS(Status) ||
(Status == STATUS_SUCCESS && Information == 0) ) {
AFD_DbgPrint(MID_TRACE,("Looks like an EOF\n"));
FCB->PollState |= AFD_EVENT_DISCONNECT;
PollReeval( FCB->DeviceExt, FCB->FileObject );
@ -259,10 +260,10 @@ NTSTATUS NTAPI ReceiveComplete
HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
ReceiveActivity( FCB, NULL );
PollReeval( FCB->DeviceExt, FCB->FileObject );
ReceiveActivity( FCB, NULL );
PollReeval( FCB->DeviceExt, FCB->FileObject );
SocketStateUnlock( FCB );
AFD_DbgPrint(MID_TRACE,("Returned %x\n", Status));

View file

@ -23,6 +23,9 @@ NTSTATUS FileOpenAddress(
NTSTATUS FileCloseAddress(
PTDI_REQUEST Request);
NTSTATUS FileFreeAddress(
PTDI_REQUEST Request);
NTSTATUS FileOpenConnection(
PTDI_REQUEST Request,
PVOID ClientContext);
@ -32,10 +35,13 @@ PCONNECTION_ENDPOINT FileFindConnectionByContext( PVOID Context );
NTSTATUS FileCloseConnection(
PTDI_REQUEST Request);
NTSTATUS FileFreeConnection(
PTDI_REQUEST Request);
NTSTATUS FileOpenControlChannel(
PTDI_REQUEST Request);
NTSTATUS FileCloseControlChannel(
NTSTATUS FileFreeControlChannel(
PTDI_REQUEST Request);
#endif /* __FILEOBJS_H */

View file

@ -170,9 +170,10 @@ UINT TCPAllocatePort( UINT HintPort );
VOID TCPFreePort( UINT Port );
NTSTATUS TCPGetPeerAddress
NTSTATUS TCPGetSockAddress
( PCONNECTION_ENDPOINT Connection,
PTRANSPORT_ADDRESS TransportAddress );
PTRANSPORT_ADDRESS TransportAddress,
BOOLEAN RemoteAddress );
NTSTATUS TCPStartup(
VOID);

View file

@ -671,19 +671,34 @@ NTSTATUS DispTdiQueryInformation(
PTDI_ADDRESS_INFO AddressInfo;
PADDRESS_FILE AddrFile;
PTA_IP_ADDRESS Address;
PCONNECTION_ENDPOINT Endpoint = NULL;
AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress);
Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
switch ((ULONG)IrpSp->FileObject->FsContext2) {
case TDI_TRANSPORT_ADDRESS_FILE:
AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
break;
Address->TAAddressCount = 1;
Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
Address->Address[0].Address[0].sin_port = AddrFile->Port;
Address->Address[0].Address[0].in_addr = AddrFile->Address.Address.IPv4Address;
RtlZeroMemory(
&Address->Address[0].Address[0].sin_zero,
sizeof(Address->Address[0].Address[0].sin_zero));
return STATUS_SUCCESS;
case TDI_CONNECTION_FILE:
AddrFile =
((PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext)->
AddressFile;
break;
Endpoint =
(PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
TCPGetSockAddress( Endpoint, (PTRANSPORT_ADDRESS)Address, FALSE );
DbgPrint("Returning socket address %x\n", Address->Address[0].Address[0].in_addr);
RtlZeroMemory(
&Address->Address[0].Address[0].sin_zero,
sizeof(Address->Address[0].Address[0].sin_zero));
return STATUS_SUCCESS;
default:
TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
@ -702,17 +717,6 @@ NTSTATUS DispTdiQueryInformation(
return STATUS_BUFFER_OVERFLOW;
}
Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
Address->TAAddressCount = 1;
Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
Address->Address[0].Address[0].sin_port = AddrFile->Port;
Address->Address[0].Address[0].in_addr =
AddrFile->Address.Address.IPv4Address;
RtlZeroMemory(
&Address->Address[0].Address[0].sin_zero,
sizeof(Address->Address[0].Address[0].sin_zero));
return STATUS_SUCCESS;
}
@ -752,7 +756,7 @@ NTSTATUS DispTdiQueryInformation(
return STATUS_BUFFER_OVERFLOW;
}
return TCPGetPeerAddress( Endpoint, AddressInfo->RemoteAddress );
return TCPGetSockAddress( Endpoint, AddressInfo->RemoteAddress, TRUE );
}
}

View file

@ -203,28 +203,6 @@ VOID DeleteAddress(PADDRESS_FILE AddrFile)
}
/*
* FUNCTION: Deletes a connection endpoint file object
* ARGUMENTS:
* Connection = Pointer to connection endpoint to delete
*/
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);
TCPFreeConnectionEndpoint(Connection);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
/*
* FUNCTION: Open an address file object
* ARGUMENTS:
@ -395,6 +373,29 @@ NTSTATUS FileCloseAddress(
break;
}
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return Status;
}
/*
* FUNCTION: Closes an address file object
* ARGUMENTS:
* Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
NTSTATUS FileFreeAddress(
PTDI_REQUEST Request)
{
PADDRESS_FILE AddrFile;
NTSTATUS Status = STATUS_SUCCESS;
AddrFile = Request->Handle.AddressHandle;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
DeleteAddress(AddrFile);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
@ -493,7 +494,7 @@ NTSTATUS FileCloseConnection(
Connection = Request->Handle.ConnectionContext;
TcpipRecursiveMutexEnter( &TCPLock, TRUE );
DeleteConnectionEndpoint(Connection);
TCPClose( Connection );
TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
@ -502,6 +503,35 @@ NTSTATUS FileCloseConnection(
}
/*
* FUNCTION: Frees an connection file object
* ARGUMENTS:
* Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
NTSTATUS FileFreeConnection(
PTDI_REQUEST Request)
{
KIRQL OldIrql;
PCONNECTION_ENDPOINT Connection;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
Connection = Request->Handle.ConnectionContext;
TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
RemoveEntryList(&Connection->ListEntry);
TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
TCPFreeConnectionEndpoint(Connection);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
}
/*
* FUNCTION: Opens a control channel file object
* ARGUMENTS:
@ -549,7 +579,7 @@ NTSTATUS FileOpenControlChannel(
* RETURNS:
* Status of operation
*/
NTSTATUS FileCloseControlChannel(
NTSTATUS FileFreeControlChannel(
PTDI_REQUEST Request)
{
PCONTROL_CHANNEL ControlChannel = Request->Handle.ControlChannel;

View file

@ -253,7 +253,7 @@ CP
}
/*
* FUNCTION: Releases resources used by a file object
* FUNCTION: Prepares a file object for close
* ARGUMENTS:
* DeviceObject = Pointer to a device object for this driver
* Irp = Pointer to a I/O request packet
@ -298,7 +298,76 @@ NTSTATUS TiCleanupFileObject(
case TDI_CONTROL_CHANNEL_FILE:
Request.Handle.ControlChannel = Context->Handle.ControlChannel;
Status = FileCloseControlChannel(&Request);
/* Nothing to do to close */
Status = STATUS_SUCCESS;
break;
default:
/* This should never happen */
TI_DbgPrint(MIN_TRACE, ("Unknown transport context.\n"));
IoAcquireCancelSpinLock(&OldIrql);
Context->CancelIrps = FALSE;
IoReleaseCancelSpinLock(OldIrql);
Status = STATUS_INVALID_PARAMETER;
}
Irp->IoStatus.Status = Status;
return Irp->IoStatus.Status;
}
/*
* FUNCTION: Releases resources used by a file object
* ARGUMENTS:
* DeviceObject = Pointer to a device object for this driver
* Irp = Pointer to a I/O request packet
* RETURNS:
* Status of the operation
* NOTES:
* This function does not pend
*/
NTSTATUS TiCloseFileObject(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
PTRANSPORT_CONTEXT Context;
TDI_REQUEST Request;
NTSTATUS Status;
KIRQL OldIrql;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Context = IrpSp->FileObject->FsContext;
if (!Context) {
TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
return STATUS_INVALID_PARAMETER;
}
IoAcquireCancelSpinLock(&OldIrql);
Context->CancelIrps = TRUE;
IoReleaseCancelSpinLock(OldIrql);
switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
case TDI_TRANSPORT_ADDRESS_FILE:
Request.Handle.AddressHandle = Context->Handle.AddressHandle;
Status = FileFreeAddress(&Request);
break;
case TDI_CONNECTION_FILE:
Request.Handle.ConnectionContext = Context->Handle.ConnectionContext;
Status = FileFreeConnection(&Request);
break;
case TDI_CONTROL_CHANNEL_FILE:
Request.Handle.ControlChannel = Context->Handle.ControlChannel;
Status = FileFreeControlChannel(&Request);
break;
default:
@ -352,9 +421,7 @@ TiDispatchOpenClose(
/* Close an address file, connection endpoint, or control connection */
case IRP_MJ_CLOSE:
Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
if (Context)
exFreePool(Context);
Status = STATUS_SUCCESS;
Status = TiCloseFileObject(DeviceObject, Irp);
break;
/* Release resources bound to an address file, connection endpoint,

View file

@ -42,7 +42,7 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection,
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
TI_DbgPrint(DEBUG_TCP,
("Completing Request %x\n", Bucket->Request));
("Completing Request %x\n", Bucket->Request.RequestContext));
if( (NewState & (SEL_CONNECT | SEL_FIN)) ==
(SEL_CONNECT | SEL_FIN) )
@ -158,7 +158,7 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection,
}
if( NewState & SEL_WRITE ) {
TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n",
IsListEmpty(&Connection->ReceiveRequest) ?
IsListEmpty(&Connection->SendRequest) ?
"empty" : "nonempty"));
while( !IsListEmpty( &Connection->SendRequest ) ) {
@ -282,7 +282,7 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
}
VOID TCPFreeConnectionEndpoint( PCONNECTION_ENDPOINT Connection ) {
TCPClose( Connection );
TI_DbgPrint(DEBUG_TCP, ("Freeing TCP Endpoint\n"));
exFreePool( Connection );
}
@ -542,25 +542,29 @@ NTSTATUS TCPConnect
IP_ADDRESS RemoteAddress;
USHORT RemotePort;
PTDI_BUCKET Bucket;
PNEIGHBOR_CACHE_ENTRY NCE;
TI_DbgPrint(DEBUG_TCP,("TCPConnect: Called\n"));
Bucket = exAllocatePool( NonPagedPool, sizeof(*Bucket) );
if( !Bucket ) return STATUS_NO_MEMORY;
TcpipRecursiveMutexEnter( &TCPLock, TRUE );
/* Freed in TCPSocketState */
Bucket->Request.RequestNotifyObject = (PVOID)Complete;
Bucket->Request.RequestContext = Context;
InsertHeadList( &Connection->ConnectRequest, &Bucket->Entry );
Status = AddrBuildAddress
((PTRANSPORT_ADDRESS)ConnInfo->RemoteAddress,
&RemoteAddress,
&RemotePort);
if (!(NCE = RouteGetRouteToDestination(&RemoteAddress)))
{
return STATUS_NETWORK_UNREACHABLE;
}
TcpipRecursiveMutexEnter( &TCPLock, TRUE );
if (Connection->State & SEL_FIN)
{
TcpipRecursiveMutexLeave( &TCPLock );
return STATUS_REMOTE_DISCONNECT;
}
/* Freed in TCPSocketState */
TI_DbgPrint(DEBUG_TCP,
("Connecting to address %x:%x\n",
RemoteAddress.Address.IPv4Address,
@ -574,6 +578,7 @@ NTSTATUS TCPConnect
AddressToConnect.sin_family = AF_INET;
AddressToBind = AddressToConnect;
AddressToBind.sin_addr.s_addr = NCE->Interface->Unicast.Address.IPv4Address;
Status = TCPTranslateError
( OskitTCPBind( Connection->SocketContext,
@ -592,6 +597,17 @@ NTSTATUS TCPConnect
Connection,
&AddressToConnect,
sizeof(AddressToConnect) ) );
if (Status == STATUS_PENDING)
{
Bucket = exAllocatePool( NonPagedPool, sizeof(*Bucket) );
if( !Bucket ) return STATUS_NO_MEMORY;
Bucket->Request.RequestNotifyObject = (PVOID)Complete;
Bucket->Request.RequestContext = Context;
InsertHeadList( &Connection->ConnectRequest, &Bucket->Entry );
}
}
TcpipRecursiveMutexLeave( &TCPLock );
@ -678,6 +694,14 @@ NTSTATUS TCPReceiveData
TcpipRecursiveMutexEnter( &TCPLock, TRUE );
/* Closing */
if (Connection->State & SEL_FIN)
{
TcpipRecursiveMutexLeave( &TCPLock );
*BytesReceived = 0;
return STATUS_REMOTE_DISCONNECT;
}
NdisQueryBuffer( Buffer, &DataBuffer, &DataLen );
TI_DbgPrint(DEBUG_TCP,("TCP>|< Got an MDL %x (%x:%d)\n", Buffer, DataBuffer, DataLen));
@ -706,7 +730,7 @@ NTSTATUS TCPReceiveData
Bucket->Request.RequestContext = Context;
*BytesReceived = 0;
InsertHeadList( &Connection->ReceiveRequest, &Bucket->Entry );
InsertTailList( &Connection->ReceiveRequest, &Bucket->Entry );
Status = STATUS_PENDING;
TI_DbgPrint(DEBUG_TCP,("Queued read irp\n"));
} else {
@ -744,6 +768,14 @@ NTSTATUS TCPSendData
TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext = %x\n",
Connection->SocketContext));
/* Closing */
if (Connection->State & SEL_FIN)
{
TcpipRecursiveMutexLeave( &TCPLock );
*BytesSent = 0;
return STATUS_REMOTE_DISCONNECT;
}
Status = TCPTranslateError
( OskitTCPSend( Connection->SocketContext,
(OSK_PCHAR)BufferData, SendLength,
@ -760,20 +792,20 @@ NTSTATUS TCPSendData
TcpipRecursiveMutexLeave( &TCPLock );
return STATUS_NO_MEMORY;
}
Bucket->Request.RequestNotifyObject = Complete;
Bucket->Request.RequestContext = Context;
*BytesSent = 0;
InsertHeadList( &Connection->SendRequest, &Bucket->Entry );
InsertTailList( &Connection->SendRequest, &Bucket->Entry );
TI_DbgPrint(DEBUG_TCP,("Queued write irp\n"));
} else {
TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Sent));
*BytesSent = Sent;
}
TcpipRecursiveMutexLeave( &TCPLock );
TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status));
return Status;
@ -798,9 +830,10 @@ VOID TCPFreePort( UINT Port ) {
DeallocatePort( &TCPPorts, Port );
}
NTSTATUS TCPGetPeerAddress
NTSTATUS TCPGetSockAddress
( PCONNECTION_ENDPOINT Connection,
PTRANSPORT_ADDRESS Address ) {
PTRANSPORT_ADDRESS Address,
BOOLEAN GetRemote ) {
OSK_UINT LocalAddress, RemoteAddress;
OSK_UI16 LocalPort, RemotePort;
PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
@ -815,8 +848,9 @@ NTSTATUS TCPGetPeerAddress
AddressIP->TAAddressCount = 1;
AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
AddressIP->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
AddressIP->Address[0].Address[0].sin_port = RemotePort;
AddressIP->Address[0].Address[0].in_addr = RemoteAddress;
AddressIP->Address[0].Address[0].sin_port = GetRemote ? RemotePort : LocalPort;
AddressIP->Address[0].Address[0].in_addr = GetRemote ? RemoteAddress : LocalAddress;
AddressIP->Address[1].AddressLength = TDI_ADDRESS_LENGTH_IP;
TcpipRecursiveMutexLeave( &TCPLock );
@ -837,13 +871,15 @@ VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {
TcpipAcquireSpinLock( &Endpoint->Lock, &OldIrql );
for( i = 0; i < 4; i++ ) {
for( i = 0; i < 4; i++ )
{
for( Entry = ListHead[i]->Flink;
Entry != ListHead[i];
Entry = Entry->Flink ) {
Entry = Entry->Flink )
{
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
if( Bucket->Request.RequestContext == Irp ) {
if( Bucket->Request.RequestContext == Irp )
{
RemoveEntryList( &Bucket->Entry );
exFreePool( Bucket );
break;

View file

@ -185,7 +185,7 @@ NTSTATUS UDPSendDatagram(
}
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
return STATUS_UNSUCCESSFUL;
return STATUS_NETWORK_UNREACHABLE;
}
LocalAddress = AddrFile->Address;