Author: cgutman Date: Sat Jul 2 15:37:37 2011 New Revision: 52501
URL: http://svn.reactos.org/svn/reactos?rev=52501&view=rev Log: [TCPIP] - 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
Modified: trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c trunk/reactos/drivers/network/tcpip/tcpip/fileobjs.c trunk/reactos/lib/drivers/ip/transport/tcp/accept.c trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c
Modified: trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip... ============================================================================== --- trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c [iso-8859-1] Sat Jul 2 15:37:37 2011 @@ -739,10 +739,16 @@ 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"));
Modified: trunk/reactos/drivers/network/tcpip/tcpip/fileobjs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip... ============================================================================== --- trunk/reactos/drivers/network/tcpip/tcpip/fileobjs.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/tcpip/fileobjs.c [iso-8859-1] Sat Jul 2 15:37:37 2011 @@ -194,7 +194,10 @@ /* Protocol specific handling */ switch (AddrFile->Protocol) { case IPPROTO_TCP: - TCPFreePort( AddrFile->Port ); + if (AddrFile->Port) + { + TCPFreePort(AddrFile->Port); + } break;
case IPPROTO_UDP: @@ -277,8 +280,36 @@ /* Protocol specific handling */ switch (Protocol) { case IPPROTO_TCP: + if (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); + + /* 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); + + AddrFile->Send = NULL; /* TCPSendData */ + break; + + case IPPROTO_UDP: + TI_DbgPrint(MID_TRACE,("Allocating udp port\n")); AddrFile->Port = - TCPAllocatePort(Address->Address[0].Address[0].sin_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) || @@ -288,24 +319,6 @@ return STATUS_ADDRESS_ALREADY_EXISTS; }
- AddEntity(CO_TL_ENTITY, AddrFile, CO_TL_TCP); - - AddrFile->Send = NULL; /* TCPSendData */ - break; - - case IPPROTO_UDP: - 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_ADDRESS_ALREADY_EXISTS; - } - TI_DbgPrint(MID_TRACE,("Setting port %d (wanted %d)\n", AddrFile->Port, Address->Address[0].Address[0].sin_port));
Modified: trunk/reactos/lib/drivers/ip/transport/tcp/accept.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tc... ============================================================================== --- trunk/reactos/lib/drivers/ip/transport/tcp/accept.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/transport/tcp/accept.c [iso-8859-1] Sat Jul 2 15:37:37 2011 @@ -65,11 +65,13 @@ 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 @@ 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 ) );
Modified: trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tc... ============================================================================== --- trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] Sat Jul 2 15:37:37 2011 @@ -605,6 +605,7 @@ 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 @@ { 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 @@ sizeof(AddressToBind) ) );
if (NT_SUCCESS(Status)) { - memcpy( &AddressToConnect.sin_addr, - &RemoteAddress.Address.IPv4Address, - sizeof(AddressToConnect.sin_addr) ); - AddressToConnect.sin_port = RemotePort; - - Status = TCPTranslateError + /* 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, + &RemoteAddress.Address.IPv4Address, + sizeof(AddressToConnect.sin_addr) ); + AddressToConnect.sin_port = RemotePort; + + Status = TCPTranslateError ( OskitTCPConnect( Connection->SocketContext, - &AddressToConnect, - sizeof(AddressToConnect) ) ); - - if (Status == STATUS_PENDING) - { - Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG ); - if( !Bucket ) + &AddressToConnect, + sizeof(AddressToConnect) ) ); + + if (Status == STATUS_PENDING) { - UnlockObject(Connection, OldIrql); - return STATUS_NO_MEMORY; + 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 ); } - - Bucket->Request.RequestNotifyObject = (PVOID)Complete; - Bucket->Request.RequestContext = Context; - - InsertTailList( &Connection->ConnectRequest, &Bucket->Entry ); } }
Modified: trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/oskittcp/oskitt... ============================================================================== --- trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c [iso-8859-1] Sat Jul 2 15:37:37 2011 @@ -117,7 +117,7 @@ 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; }