diff --git a/reactos/drivers/network/tcpip/tcpip/dispatch.c b/reactos/drivers/network/tcpip/tcpip/dispatch.c index 6388acbf08a..6fa24c83cfc 100644 --- a/reactos/drivers/network/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/network/tcpip/tcpip/dispatch.c @@ -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")); diff --git a/reactos/drivers/network/tcpip/tcpip/fileobjs.c b/reactos/drivers/network/tcpip/tcpip/fileobjs.c index 4d4285add70..6d9b0b5507b 100644 --- a/reactos/drivers/network/tcpip/tcpip/fileobjs.c +++ b/reactos/drivers/network/tcpip/tcpip/fileobjs.c @@ -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); diff --git a/reactos/lib/drivers/ip/transport/tcp/accept.c b/reactos/lib/drivers/ip/transport/tcp/accept.c index 0b66481e220..2454657d009 100644 --- a/reactos/lib/drivers/ip/transport/tcp/accept.c +++ b/reactos/lib/drivers/ip/transport/tcp/accept.c @@ -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 ) ); diff --git a/reactos/lib/drivers/ip/transport/tcp/tcp.c b/reactos/lib/drivers/ip/transport/tcp/tcp.c index 20b01f5a3f8..18245b8eaca 100644 --- a/reactos/lib/drivers/ip/transport/tcp/tcp.c +++ b/reactos/lib/drivers/ip/transport/tcp/tcp.c @@ -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 ); + } } } diff --git a/reactos/lib/drivers/oskittcp/oskittcp/interface.c b/reactos/lib/drivers/oskittcp/oskittcp/interface.c index 10224bd396f..e355a972e89 100644 --- a/reactos/lib/drivers/oskittcp/oskittcp/interface.c +++ b/reactos/lib/drivers/oskittcp/oskittcp/interface.c @@ -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; }