- Fix binding to an unspecified port on a connect so that it works reliably by asking the TCP library for a free port instead of assuming that one we have is free
- Fix binding to an unspecified port on a listen which previously would result in the address file not having information stored about the port number assigned
- Fix a nasty bug which resulted in us binding to an arbitrary port during a connect even when the client wanted a specific port
- Revert the hack that partially fixed this before

svn path=/trunk/; revision=52501
This commit is contained in:
Cameron Gutman 2011-07-02 15:37:37 +00:00
parent b062ee8583
commit 16ded1b13b
5 changed files with 90 additions and 31 deletions

View file

@ -739,10 +739,16 @@ NTSTATUS DispTdiQueryInformation(
case TDI_CONNECTION_FILE:
Endpoint =
(PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
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 = Endpoint->AddressFile->Port;
Address->Address[0].Address[0].in_addr = Endpoint->AddressFile->Address.Address.IPv4Address;
RtlZeroMemory(
&Address->Address[0].Address[0].sin_zero,
sizeof(Address->Address[0].Address[0].sin_zero));
return TCPGetSockAddress( Endpoint, (PTRANSPORT_ADDRESS)Address, FALSE );
return STATUS_SUCCESS;
default:
TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));

View file

@ -194,7 +194,10 @@ VOID AddrFileFree(
/* Protocol specific handling */
switch (AddrFile->Protocol) {
case IPPROTO_TCP:
TCPFreePort( AddrFile->Port );
if (AddrFile->Port)
{
TCPFreePort(AddrFile->Port);
}
break;
case IPPROTO_UDP:
@ -277,15 +280,25 @@ NTSTATUS FileOpenAddress(
/* Protocol specific handling */
switch (Protocol) {
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)
if (Address->Address[0].Address[0].sin_port)
{
ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
return STATUS_ADDRESS_ALREADY_EXISTS;
/* The client specified an explicit port so we force a bind to this */
AddrFile->Port = TCPAllocatePort(Address->Address[0].Address[0].sin_port);
/* Check for bind success */
if (AddrFile->Port == 0xffff)
{
ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
return STATUS_ADDRESS_ALREADY_EXISTS;
}
/* Sanity check */
ASSERT(Address->Address[0].Address[0].sin_port == AddrFile->Port);
}
else
{
/* The client wants an unspecified port so we wait to see what the TCP library gives us */
AddrFile->Port = 0;
}
AddEntity(CO_TL_ENTITY, AddrFile, CO_TL_TCP);

View file

@ -65,11 +65,13 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
NTSTATUS Status = STATUS_SUCCESS;
SOCKADDR_IN AddressToBind;
KIRQL OldIrql;
TA_IP_ADDRESS LocalAddress;
ASSERT(Connection);
ASSERT_KM_POINTER(Connection->AddressFile);
LockObject(Connection, &OldIrql);
ASSERT_KM_POINTER(Connection->AddressFile);
TI_DbgPrint(DEBUG_TCP,("TCPListen started\n"));
@ -87,6 +89,23 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
Status = TCPTranslateError( OskitTCPBind( Connection->SocketContext,
&AddressToBind,
sizeof(AddressToBind) ) );
if (NT_SUCCESS(Status))
{
/* Check if we had an unspecified port */
if (!Connection->AddressFile->Port)
{
/* We did, so we need to copy back the port */
Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE);
if (NT_SUCCESS(Status))
{
/* Allocate the port in the port bitmap */
Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
/* This should never fail */
ASSERT(Connection->AddressFile->Port != 0xFFFF);
}
}
}
if (NT_SUCCESS(Status))
Status = TCPTranslateError( OskitTCPListen( Connection->SocketContext, Backlog ) );

View file

@ -605,6 +605,7 @@ NTSTATUS TCPConnect
SOCKADDR_IN AddressToConnect = { 0 }, AddressToBind = { 0 };
IP_ADDRESS RemoteAddress;
USHORT RemotePort;
TA_IP_ADDRESS LocalAddress;
PTDI_BUCKET Bucket;
PNEIGHBOR_CACHE_ENTRY NCE;
KIRQL OldIrql;
@ -652,6 +653,8 @@ NTSTATUS TCPConnect
{
AddressToBind.sin_addr.s_addr = Connection->AddressFile->Address.Address.IPv4Address;
}
AddressToBind.sin_port = Connection->AddressFile->Port;
Status = TCPTranslateError
( OskitTCPBind( Connection->SocketContext,
@ -659,29 +662,47 @@ NTSTATUS TCPConnect
sizeof(AddressToBind) ) );
if (NT_SUCCESS(Status)) {
memcpy( &AddressToConnect.sin_addr,
&RemoteAddress.Address.IPv4Address,
sizeof(AddressToConnect.sin_addr) );
AddressToConnect.sin_port = RemotePort;
Status = TCPTranslateError
( OskitTCPConnect( Connection->SocketContext,
&AddressToConnect,
sizeof(AddressToConnect) ) );
if (Status == STATUS_PENDING)
/* Check if we had an unspecified port */
if (!Connection->AddressFile->Port)
{
Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG );
if( !Bucket )
/* We did, so we need to copy back the port */
Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE);
if (NT_SUCCESS(Status))
{
UnlockObject(Connection, OldIrql);
return STATUS_NO_MEMORY;
/* Allocate the port in the port bitmap */
Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
/* This should never fail */
ASSERT(Connection->AddressFile->Port != 0xFFFF);
}
}
if (NT_SUCCESS(Status))
{
memcpy( &AddressToConnect.sin_addr,
&RemoteAddress.Address.IPv4Address,
sizeof(AddressToConnect.sin_addr) );
AddressToConnect.sin_port = RemotePort;
Bucket->Request.RequestNotifyObject = (PVOID)Complete;
Bucket->Request.RequestContext = Context;
InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
Status = TCPTranslateError
( OskitTCPConnect( Connection->SocketContext,
&AddressToConnect,
sizeof(AddressToConnect) ) );
if (Status == STATUS_PENDING)
{
Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG );
if( !Bucket )
{
UnlockObject(Connection, OldIrql);
return STATUS_NO_MEMORY;
}
Bucket->Request.RequestNotifyObject = (PVOID)Complete;
Bucket->Request.RequestContext = Context;
InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
}
}
}

View file

@ -117,7 +117,7 @@ void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len )
void InitializeSocketFlags(struct socket *so)
{
so->so_state |= SS_NBIO;
so->so_options |= SO_DONTROUTE | SO_REUSEPORT;
so->so_options |= SO_DONTROUTE;
so->so_snd.sb_flags |= SB_SEL;
so->so_rcv.sb_flags |= SB_SEL;
}