From 90b16f9eca0ae8b410ef4982c19c20eb97aac6ff Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Sun, 15 Feb 2009 21:52:56 +0000 Subject: [PATCH] Fix loopback adapter locking and make traffic work consistently. Fix zero-address binding. Local tcp services should work now. svn path=/trunk/; revision=39613 --- .../drivers/network/tcpip/tcpip/fileobjs.c | 21 +++---- reactos/lib/drivers/ip/network/address.c | 1 + reactos/lib/drivers/ip/network/ip.c | 7 +++ reactos/lib/drivers/ip/network/loopback.c | 56 +++++++++++-------- reactos/lib/drivers/ip/transport/udp/udp.c | 48 +++++++++------- 5 files changed, 76 insertions(+), 57 deletions(-) diff --git a/reactos/drivers/network/tcpip/tcpip/fileobjs.c b/reactos/drivers/network/tcpip/tcpip/fileobjs.c index b2f4df631c0..43b03b26ae5 100644 --- a/reactos/drivers/network/tcpip/tcpip/fileobjs.c +++ b/reactos/drivers/network/tcpip/tcpip/fileobjs.c @@ -242,7 +242,6 @@ NTSTATUS FileOpenAddress( PVOID Options) { IPv4_RAW_ADDRESS IPv4Address; - BOOLEAN Matched; PADDRESS_FILE AddrFile; TI_DbgPrint(MID_TRACE, ("Called (Proto %d).\n", Protocol)); @@ -260,21 +259,19 @@ NTSTATUS FileOpenAddress( AddrFile->Free = AddrFileFree; /* Make sure address is a local unicast address or 0 */ - - /* Locate address entry. If specified address is 0, a random address is chosen */ - /* FIXME: IPv4 only */ AddrFile->Family = Address->Address[0].AddressType; IPv4Address = Address->Address[0].Address[0].in_addr; - if (IPv4Address == 0) - Matched = IPGetDefaultAddress(&AddrFile->Address); + if (IPv4Address != 0 && + !AddrLocateADEv4(IPv4Address, &AddrFile->Address)) { + exFreePool(AddrFile); + TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", DN2H(IPv4Address))); + return STATUS_INVALID_PARAMETER; + } else - Matched = AddrLocateADEv4(IPv4Address, &AddrFile->Address); - - if (!Matched) { - exFreePool(AddrFile); - TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", DN2H(IPv4Address))); - return STATUS_INVALID_PARAMETER; + { + /* Bound to the default address ... Copy the address type */ + AddrFile->Address.Type = IP_ADDRESS_V4; } TI_DbgPrint(MID_TRACE, ("Opening address %s for communication (P=%d U=%d).\n", diff --git a/reactos/lib/drivers/ip/network/address.c b/reactos/lib/drivers/ip/network/address.c index 9bd88171bb9..aeca8ba0819 100644 --- a/reactos/lib/drivers/ip/network/address.c +++ b/reactos/lib/drivers/ip/network/address.c @@ -223,6 +223,7 @@ BOOLEAN AddrIsEqual( { if (Address1->Type != Address2->Type) { DbgPrint("AddrIsEqual: Unequal Address Types\n"); + ASSERT(FALSE); return FALSE; } diff --git a/reactos/lib/drivers/ip/network/ip.c b/reactos/lib/drivers/ip/network/ip.c index dc98bdfe384..a5af87682ad 100644 --- a/reactos/lib/drivers/ip/network/ip.c +++ b/reactos/lib/drivers/ip/network/ip.c @@ -195,6 +195,8 @@ PIP_INTERFACE IPCreateInterface( INIT_TAG(IF, TAG('F','A','C','E')); + RtlZeroMemory(IF, sizeof(IP_INTERFACE)); + IF->Free = FreeIF; IF->Context = BindInfo->Context; IF->HeaderSize = BindInfo->HeaderSize; @@ -210,6 +212,11 @@ PIP_INTERFACE IPCreateInterface( IF->AddressLength = BindInfo->AddressLength; IF->Transmit = BindInfo->Transmit; + IF->Unicast.Type = IP_ADDRESS_V4; + IF->PointToPoint.Type = IP_ADDRESS_V4; + IF->Netmask.Type = IP_ADDRESS_V4; + IF->Broadcast.Type = IP_ADDRESS_V4; + TcpipInitializeSpinLock(&IF->Lock); #ifdef __NTDRIVER__ diff --git a/reactos/lib/drivers/ip/network/loopback.c b/reactos/lib/drivers/ip/network/loopback.c index d09c6910d09..f12a2d771aa 100644 --- a/reactos/lib/drivers/ip/network/loopback.c +++ b/reactos/lib/drivers/ip/network/loopback.c @@ -32,49 +32,57 @@ VOID NTAPI LoopReceiveWorker( PVOID Context ) { UINT BytesTransferred; PNDIS_BUFFER NdisBuffer; IP_PACKET IPPacket; + KIRQL OldIrql; TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); - while( (ListEntry = - ExInterlockedRemoveHeadList( &LoopWorkList, &LoopWorkLock )) ) { - WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry); - - TI_DbgPrint(DEBUG_DATALINK, ("WorkItem: %x\n", WorkItem)); - - Packet = WorkItem->Packet; - Adapter = WorkItem->Adapter; - BytesTransferred = WorkItem->BytesTransferred; - - exFreePool( WorkItem ); + TcpipAcquireSpinLock( &LoopWorkLock, &OldIrql ); + while( !IsListEmpty(&LoopWorkList) ) + { + ListEntry = RemoveHeadList( &LoopWorkList ); + TcpipReleaseSpinLock( &LoopWorkLock, OldIrql ); + WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry); + + TI_DbgPrint(DEBUG_DATALINK, ("WorkItem: %x\n", WorkItem)); + + Packet = WorkItem->Packet; + Adapter = WorkItem->Adapter; + BytesTransferred = WorkItem->BytesTransferred; + + exFreePool( WorkItem ); + IPPacket.NdisPacket = Packet; - + TI_DbgPrint(DEBUG_DATALINK, ("Packet %x Adapter %x Trans %x\n", Packet, Adapter, BytesTransferred)); - + NdisGetFirstBufferFromPacket(Packet, &NdisBuffer, &IPPacket.Header, &IPPacket.ContigSize, &IPPacket.TotalSize); - IPPacket.ContigSize = IPPacket.TotalSize = BytesTransferred; + IPPacket.ContigSize = IPPacket.TotalSize = BytesTransferred; /* Determine which upper layer protocol that should receive this packet and pass it to the correct receive handler */ - - TI_DbgPrint(MID_TRACE, - ("ContigSize: %d, TotalSize: %d, BytesTransferred: %d\n", - IPPacket.ContigSize, IPPacket.TotalSize, - BytesTransferred)); - - IPPacket.Position = 0; - + + TI_DbgPrint + (MID_TRACE, + ("ContigSize: %d, TotalSize: %d, BytesTransferred: %d\n", + IPPacket.ContigSize, IPPacket.TotalSize, + BytesTransferred)); + + IPPacket.Position = 0; + IPReceive(Loopback, &IPPacket); - - FreeNdisPacket( Packet ); + + FreeNdisPacket( Packet ); + TcpipAcquireSpinLock( &LoopWorkLock, &OldIrql ); } TI_DbgPrint(DEBUG_DATALINK, ("Leaving\n")); LoopReceiveWorkerBusy = FALSE; + TcpipReleaseSpinLock( &LoopWorkLock, OldIrql ); } VOID LoopSubmitReceiveWork( diff --git a/reactos/lib/drivers/ip/transport/udp/udp.c b/reactos/lib/drivers/ip/transport/udp/udp.c index 7fcd1e31c5e..57ce3276f62 100644 --- a/reactos/lib/drivers/ip/transport/udp/udp.c +++ b/reactos/lib/drivers/ip/transport/udp/udp.c @@ -10,7 +10,6 @@ #include "precomp.h" - BOOLEAN UDPInitialized = FALSE; PORT_SET UDPPorts; @@ -164,42 +163,49 @@ NTSTATUS UDPSendDatagram( IP_PACKET Packet; PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress; IP_ADDRESS RemoteAddress; + IP_ADDRESS LocalAddress; USHORT RemotePort; NTSTATUS Status; PNEIGHBOR_CACHE_ENTRY NCE; TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n", - AddrFile, ConnInfo, BufferData, DataSize)); + AddrFile, ConnInfo, BufferData, DataSize)); TI_DbgPrint(MID_TRACE,("RemoteAddressTa: %x\n", RemoteAddressTa)); switch( RemoteAddressTa->Address[0].AddressType ) { case TDI_ADDRESS_TYPE_IP: - RemoteAddress.Type = IP_ADDRESS_V4; - RemoteAddress.Address.IPv4Address = - RemoteAddressTa->Address[0].Address[0].in_addr; - RemotePort = RemoteAddressTa->Address[0].Address[0].sin_port; - break; + RemoteAddress.Type = IP_ADDRESS_V4; + RemoteAddress.Address.IPv4Address = + RemoteAddressTa->Address[0].Address[0].in_addr; + RemotePort = RemoteAddressTa->Address[0].Address[0].sin_port; + break; default: - return STATUS_UNSUCCESSFUL; + return STATUS_UNSUCCESSFUL; } - Status = BuildUDPPacket( &Packet, - &RemoteAddress, - RemotePort, - &AddrFile->Address, - AddrFile->Port, - BufferData, - DataSize ); - - if( !NT_SUCCESS(Status) ) - return Status; - if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) { - FreeNdisPacket(Packet.NdisPacket); - return STATUS_UNSUCCESSFUL; + return STATUS_UNSUCCESSFUL; } + LocalAddress = AddrFile->Address; + if (AddrIsUnspecified(&LocalAddress)) + { + if (!IPGetDefaultAddress(&LocalAddress)) + return FALSE; + } + + Status = BuildUDPPacket( &Packet, + &RemoteAddress, + RemotePort, + &LocalAddress, + AddrFile->Port, + BufferData, + DataSize ); + + if( !NT_SUCCESS(Status) ) + return Status; + if (!NT_SUCCESS(Status = IPSendDatagram( &Packet, NCE, UDPSendPacketComplete, NULL ))) { FreeNdisPacket(Packet.NdisPacket);