- 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: case TDI_CONNECTION_FILE:
Endpoint = Endpoint =
(PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; (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( RtlZeroMemory(
&Address->Address[0].Address[0].sin_zero, &Address->Address[0].Address[0].sin_zero,
sizeof(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: default:
TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));

View file

@ -194,7 +194,10 @@ VOID AddrFileFree(
/* Protocol specific handling */ /* Protocol specific handling */
switch (AddrFile->Protocol) { switch (AddrFile->Protocol) {
case IPPROTO_TCP: case IPPROTO_TCP:
if (AddrFile->Port)
{
TCPFreePort(AddrFile->Port); TCPFreePort(AddrFile->Port);
}
break; break;
case IPPROTO_UDP: case IPPROTO_UDP:
@ -277,17 +280,27 @@ NTSTATUS FileOpenAddress(
/* Protocol specific handling */ /* Protocol specific handling */
switch (Protocol) { switch (Protocol) {
case IPPROTO_TCP: case IPPROTO_TCP:
AddrFile->Port = if (Address->Address[0].Address[0].sin_port)
TCPAllocatePort(Address->Address[0].Address[0].sin_port); {
/* The client specified an explicit port so we force a bind to this */
AddrFile->Port = TCPAllocatePort(Address->Address[0].Address[0].sin_port);
if ((Address->Address[0].Address[0].sin_port && /* Check for bind success */
AddrFile->Port != Address->Address[0].Address[0].sin_port) || if (AddrFile->Port == 0xffff)
AddrFile->Port == 0xffff)
{ {
ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG); ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
return STATUS_ADDRESS_ALREADY_EXISTS; 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); AddEntity(CO_TL_ENTITY, AddrFile, CO_TL_TCP);
AddrFile->Send = NULL; /* TCPSendData */ AddrFile->Send = NULL; /* TCPSendData */

View file

@ -65,12 +65,14 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
SOCKADDR_IN AddressToBind; SOCKADDR_IN AddressToBind;
KIRQL OldIrql; KIRQL OldIrql;
TA_IP_ADDRESS LocalAddress;
ASSERT(Connection); ASSERT(Connection);
ASSERT_KM_POINTER(Connection->AddressFile);
LockObject(Connection, &OldIrql); LockObject(Connection, &OldIrql);
ASSERT_KM_POINTER(Connection->AddressFile);
TI_DbgPrint(DEBUG_TCP,("TCPListen started\n")); TI_DbgPrint(DEBUG_TCP,("TCPListen started\n"));
TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext %x\n", TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext %x\n",
@ -87,6 +89,23 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
Status = TCPTranslateError( OskitTCPBind( Connection->SocketContext, Status = TCPTranslateError( OskitTCPBind( Connection->SocketContext,
&AddressToBind, &AddressToBind,
sizeof(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)) if (NT_SUCCESS(Status))
Status = TCPTranslateError( OskitTCPListen( Connection->SocketContext, Backlog ) ); Status = TCPTranslateError( OskitTCPListen( Connection->SocketContext, Backlog ) );

View file

@ -605,6 +605,7 @@ NTSTATUS TCPConnect
SOCKADDR_IN AddressToConnect = { 0 }, AddressToBind = { 0 }; SOCKADDR_IN AddressToConnect = { 0 }, AddressToBind = { 0 };
IP_ADDRESS RemoteAddress; IP_ADDRESS RemoteAddress;
USHORT RemotePort; USHORT RemotePort;
TA_IP_ADDRESS LocalAddress;
PTDI_BUCKET Bucket; PTDI_BUCKET Bucket;
PNEIGHBOR_CACHE_ENTRY NCE; PNEIGHBOR_CACHE_ENTRY NCE;
KIRQL OldIrql; KIRQL OldIrql;
@ -653,12 +654,31 @@ NTSTATUS TCPConnect
AddressToBind.sin_addr.s_addr = Connection->AddressFile->Address.Address.IPv4Address; AddressToBind.sin_addr.s_addr = Connection->AddressFile->Address.Address.IPv4Address;
} }
AddressToBind.sin_port = Connection->AddressFile->Port;
Status = TCPTranslateError Status = TCPTranslateError
( OskitTCPBind( Connection->SocketContext, ( OskitTCPBind( Connection->SocketContext,
&AddressToBind, &AddressToBind,
sizeof(AddressToBind) ) ); sizeof(AddressToBind) ) );
if (NT_SUCCESS(Status)) { 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))
{
memcpy( &AddressToConnect.sin_addr, memcpy( &AddressToConnect.sin_addr,
&RemoteAddress.Address.IPv4Address, &RemoteAddress.Address.IPv4Address,
sizeof(AddressToConnect.sin_addr) ); sizeof(AddressToConnect.sin_addr) );
@ -684,6 +704,7 @@ NTSTATUS TCPConnect
InsertTailList( &Connection->ConnectRequest, &Bucket->Entry ); InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
} }
} }
}
UnlockObject(Connection, OldIrql); UnlockObject(Connection, OldIrql);

View file

@ -117,7 +117,7 @@ void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len )
void InitializeSocketFlags(struct socket *so) void InitializeSocketFlags(struct socket *so)
{ {
so->so_state |= SS_NBIO; 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_snd.sb_flags |= SB_SEL;
so->so_rcv.sb_flags |= SB_SEL; so->so_rcv.sb_flags |= SB_SEL;
} }