From 9fbbec950f9a070c92efe12319f401066299d28f Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Sat, 22 Jan 2005 06:47:33 +0000 Subject: [PATCH] Working ping. msafd: Added datagram flag to SOCK_RAW sockets transport/* did some refactoring, added some printing. Main thing: there is now a generic IP only header builder in rawip that's shared by udp and rawip. afd: Make sure datagram sockets always select writable Add some socket close infrastructure to kill associated active polls svn path=/trunk/; revision=13207 --- .../lib/ip/transport/datagram/datagram.c | 4 + .../drivers/lib/ip/transport/rawip/rawip.c | 516 ++++++++++++------ reactos/drivers/lib/ip/transport/udp/udp.c | 48 +- reactos/drivers/net/afd/afd/bind.c | 4 - reactos/drivers/net/afd/afd/main.c | 14 + reactos/drivers/net/afd/afd/select.c | 45 ++ reactos/drivers/net/afd/afd/write.c | 4 + reactos/drivers/net/afd/include/afd.h | 2 + reactos/drivers/net/tcpip/include/rawip.h | 13 + reactos/drivers/net/tcpip/tcpip/dispatch.c | 15 +- reactos/lib/msafd/misc/dllmain.c | 9 +- 11 files changed, 467 insertions(+), 207 deletions(-) diff --git a/reactos/drivers/lib/ip/transport/datagram/datagram.c b/reactos/drivers/lib/ip/transport/datagram/datagram.c index 8ce64d78139..a10c20816ee 100644 --- a/reactos/drivers/lib/ip/transport/datagram/datagram.c +++ b/reactos/drivers/lib/ip/transport/datagram/datagram.c @@ -86,6 +86,10 @@ VOID DGDeliverData( if (Found) { TI_DbgPrint(MAX_TRACE, ("Suitable receive request found.\n")); + + TI_DbgPrint(MAX_TRACE, + ("Target Buffer: %x, Source Buffer: %x, Size %d\n", + Current->Buffer, DataBuffer, DataSize)); /* Copy the data into buffer provided by the user */ RtlCopyMemory( Current->Buffer, diff --git a/reactos/drivers/lib/ip/transport/rawip/rawip.c b/reactos/drivers/lib/ip/transport/rawip/rawip.c index e75d78a8325..181cc04e550 100644 --- a/reactos/drivers/lib/ip/transport/rawip/rawip.c +++ b/reactos/drivers/lib/ip/transport/rawip/rawip.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS TCP/IP protocol driver * FILE: transport/rawip/rawip.c - * PURPOSE: Raw IP routines + * PURPOSE: User Datagram Protocol routines * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * REVISIONS: * CSH 01/08-2000 Created @@ -10,71 +10,155 @@ #include "precomp.h" - -BOOLEAN RawIPInitialized = FALSE; - - -NTSTATUS BuildRawIPPacket( - PIP_PACKET Packet, - UINT DataLength, +NTSTATUS AddGenericHeaderIPv4( + PIP_ADDRESS RemoteAddress, + USHORT RemotePort, PIP_ADDRESS LocalAddress, - USHORT LocalPort ) + USHORT LocalPort, + PIP_PACKET IPPacket, + UINT DataLength, + UINT Protocol, + UINT ExtraLength, + PVOID *NextHeader ) /* - * FUNCTION: Builds an UDP packet + * FUNCTION: Adds an IPv4 and RawIp header to an IP packet + * ARGUMENTS: + * SendRequest = Pointer to send request + * LocalAddress = Pointer to our local address + * LocalPort = The port we send this datagram from + * IPPacket = Pointer to IP packet + * RETURNS: + * Status of operation + */ +{ + PIPv4_HEADER IPHeader; + ULONG BufferSize; + + TI_DbgPrint(MID_TRACE, ("Packet: %x NdisPacket %x\n", + IPPacket, IPPacket->NdisPacket)); + + BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + ExtraLength; + + GetDataPtr( IPPacket->NdisPacket, + MaxLLHeaderSize, + (PCHAR *)&IPPacket->Header, + &IPPacket->ContigSize ); + + IPPacket->HeaderSize = 20; + + TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", + BufferSize, IPPacket->Header)); + TI_DbgPrint(MAX_TRACE, ("Packet total length %d\n", IPPacket->TotalSize)); + + /* Build IPv4 header */ + IPHeader = (PIPv4_HEADER)IPPacket->Header; + /* Version = 4, Length = 5 DWORDs */ + IPHeader->VerIHL = 0x45; + /* Normal Type-of-Service */ + IPHeader->Tos = 0; + /* Length of header and data */ + IPHeader->TotalLength = WH2N((USHORT)IPPacket->TotalSize); + /* Identification */ + IPHeader->Id = 0; + /* One fragment at offset 0 */ + IPHeader->FlagsFragOfs = 0; + /* Time-to-Live is 128 */ + IPHeader->Ttl = 128; + /* User Datagram Protocol */ + IPHeader->Protocol = Protocol; + /* Checksum is 0 (for later calculation of this) */ + IPHeader->Checksum = 0; + /* Source address */ + IPHeader->SrcAddr = LocalAddress->Address.IPv4Address; + /* Destination address. FIXME: IPv4 only */ + IPHeader->DstAddr = RemoteAddress->Address.IPv4Address; + + /* Build RawIp header */ + *NextHeader = (((PCHAR)IPHeader) + sizeof(IPv4_HEADER)); + IPPacket->Data = ((PCHAR)*NextHeader) + ExtraLength; + + return STATUS_SUCCESS; +} + + +NTSTATUS BuildRawIpPacket( + PIP_PACKET Packet, + PIP_ADDRESS RemoteAddress, + USHORT RemotePort, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PCHAR DataBuffer, + UINT DataLen ) +/* + * FUNCTION: Builds an RawIp packet * ARGUMENTS: * Context = Pointer to context information (DATAGRAM_SEND_REQUEST) - * LocalAddress = Pointer to our local address (NULL) - * LocalPort = The port we send this datagram from (0) + * LocalAddress = Pointer to our local address + * LocalPort = The port we send this datagram from * IPPacket = Address of pointer to IP packet * RETURNS: * Status of operation */ { - PVOID Header; - NDIS_STATUS NdisStatus; - PNDIS_BUFFER HeaderBuffer; - PNDIS_PACKET NdisPacket = Packet->NdisPacket; - /* Will be zeroed in packet by IPInitializePacket */ - + NTSTATUS Status; + PCHAR Payload; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* FIXME: Assumes IPv4 */ + IPInitializePacket(Packet, IP_ADDRESS_V4); + if (!Packet) + return STATUS_INSUFFICIENT_RESOURCES; + + Packet->TotalSize = sizeof(IPv4_HEADER) + DataLen; + /* Prepare packet */ - IPInitializePacket(Packet,IP_ADDRESS_V4); - Packet->Flags = IP_PACKET_FLAG_RAW; /* Don't touch IP header */ - Packet->TotalSize = DataLength; - Packet->NdisPacket = NdisPacket; + Status = AllocatePacketWithBuffer( &Packet->NdisPacket, + NULL, + Packet->TotalSize + MaxLLHeaderSize ); + + if( !NT_SUCCESS(Status) ) return Status; - if (MaxLLHeaderSize != 0) { - Header = ExAllocatePool(NonPagedPool, MaxLLHeaderSize); - if (!Header) { - TI_DbgPrint(MIN_TRACE, ("Cannot allocate memory for packet headers.\n")); - return STATUS_INSUFFICIENT_RESOURCES; - } + TI_DbgPrint(MID_TRACE, ("Allocated packet: %x\n", Packet->NdisPacket)); + TI_DbgPrint(MID_TRACE, ("Local Addr : %s\n", A2S(LocalAddress))); + TI_DbgPrint(MID_TRACE, ("Remote Addr: %s\n", A2S(RemoteAddress))); + + switch (RemoteAddress->Type) { + case IP_ADDRESS_V4: + Status = AddGenericHeaderIPv4 + (RemoteAddress, RemotePort, + LocalAddress, LocalPort, Packet, DataLen, + IPPROTO_ICMP, /* XXX Figure out a better way to do this */ + 0, (PVOID *)&Payload ); + break; + case IP_ADDRESS_V6: + /* FIXME: Support IPv6 */ + Status = STATUS_UNSUCCESSFUL; + TI_DbgPrint(MIN_TRACE, ("IPv6 RawIp datagrams are not supported.\n")); + break; - TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", - MaxLLHeaderSize, Header)); - - /* Allocate NDIS buffer for maximum link level header */ - NdisAllocateBuffer(&NdisStatus, - &HeaderBuffer, - GlobalBufferPool, - Header, - MaxLLHeaderSize); - - if (NdisStatus != NDIS_STATUS_SUCCESS) { - TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS buffer for packet headers. NdisStatus = (0x%X)\n", NdisStatus)); - ExFreePool(Header); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Chain header at front of packet */ - NdisChainBufferAtFront(Packet->NdisPacket, HeaderBuffer); + default: + Status = STATUS_UNSUCCESSFUL; + TI_DbgPrint(MIN_TRACE, ("Bad Address Type %d\n", RemoteAddress->Type)); + break; } - + + TI_DbgPrint(MID_TRACE, ("Copying data (hdr %x data %x (%d))\n", + Packet->Header, Packet->Data, + (PCHAR)Packet->Data - (PCHAR)Packet->Header)); + + RtlCopyMemory( Packet->Data, DataBuffer, DataLen ); + + TI_DbgPrint(MID_TRACE, ("Displaying packet\n")); + DISPLAY_IP_PACKET(Packet); - + + TI_DbgPrint(MID_TRACE, ("Leaving\n")); + return STATUS_SUCCESS; } -VOID RawIPSendComplete +VOID RawIpSendPacketComplete ( PVOID Context, PNDIS_PACKET Packet, NDIS_STATUS Status ) { FreeNdisPacket( Packet ); } @@ -83,10 +167,10 @@ NTSTATUS RawIPSendDatagram( PADDRESS_FILE AddrFile, PTDI_CONNECTION_INFORMATION ConnInfo, PCHAR BufferData, - ULONG BufferLen, - PULONG DataUsed ) + ULONG DataSize, + PULONG DataUsed ) /* - * FUNCTION: Sends a raw IP datagram to a remote address + * FUNCTION: Sends an RawIp datagram to a remote address * ARGUMENTS: * Request = Pointer to TDI request * ConnInfo = Pointer to connection information @@ -96,134 +180,258 @@ NTSTATUS RawIPSendDatagram( * Status of operation */ { - NDIS_STATUS Status; IP_PACKET Packet; - PNEIGHBOR_CACHE_ENTRY NCE; + PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress; IP_ADDRESS RemoteAddress; + USHORT RemotePort; + NTSTATUS Status; + PNEIGHBOR_CACHE_ENTRY NCE; - Status = AllocatePacketWithBuffer( &Packet.NdisPacket, - BufferData, - BufferLen ); - - TI_DbgPrint(MID_TRACE,("Packet.NdisPacket %x\n", Packet.NdisPacket)); + TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n", + AddrFile, ConnInfo, BufferData, DataSize)); + TI_DbgPrint(MID_TRACE,("RemoteAddressTa: %x\n", RemoteAddressTa)); - *DataUsed = BufferLen; - - if( Status == NDIS_STATUS_SUCCESS ) - Status = BuildRawIPPacket( &Packet, - BufferLen, - &AddrFile->Address, - AddrFile->Port ); - - if( Status == NDIS_STATUS_SUCCESS ) { + switch( RemoteAddressTa->Address[0].AddressType ) { + case TDI_ADDRESS_TYPE_IP: RemoteAddress.Type = IP_ADDRESS_V4; - RtlCopyMemory( &RemoteAddress.Address.IPv4Address, - BufferData + FIELD_OFFSET(IPv4_HEADER, DstAddr), - sizeof(IPv4_RAW_ADDRESS) ); + RemoteAddress.Address.IPv4Address = + RemoteAddressTa->Address[0].Address[0].in_addr; + RemotePort = RemoteAddressTa->Address[0].Address[0].sin_port; + break; - if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) { - FreeNdisPacket( Packet.NdisPacket ); - return STATUS_NO_SUCH_DEVICE; - } - - IPSendDatagram( &Packet, NCE, RawIPSendComplete, NULL ); - } else - FreeNdisPacket( Packet.NdisPacket ); + default: + return STATUS_UNSUCCESSFUL; + } + + Status = BuildRawIpPacket( &Packet, + &RemoteAddress, + RemotePort, + &AddrFile->Address, + AddrFile->Port, + BufferData, + DataSize ); + + if( !NT_SUCCESS(Status) ) + return Status; + TI_DbgPrint(MID_TRACE,("About to get route to destination\n")); + + if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) + return STATUS_UNSUCCESSFUL; + + TI_DbgPrint(MID_TRACE,("About to send datagram\n")); + + IPSendDatagram( &Packet, NCE, RawIpSendPacketComplete, NULL ); + + TI_DbgPrint(MID_TRACE,("Leaving\n")); + + return STATUS_SUCCESS; +} + +VOID RawIpReceiveComplete(PVOID Context, NTSTATUS Status, ULONG Count) { + PDATAGRAM_RECEIVE_REQUEST ReceiveRequest = + (PDATAGRAM_RECEIVE_REQUEST)Context; + TI_DbgPrint(MAX_TRACE,("Called\n")); + ReceiveRequest->UserComplete( ReceiveRequest->UserContext, Status, Count ); + exFreePool( ReceiveRequest ); + TI_DbgPrint(MAX_TRACE,("Done\n")); +} + +NTSTATUS RawIPReceiveDatagram( + PADDRESS_FILE AddrFile, + PTDI_CONNECTION_INFORMATION ConnInfo, + PCHAR BufferData, + ULONG ReceiveLength, + ULONG ReceiveFlags, + PTDI_CONNECTION_INFORMATION ReturnInfo, + PULONG BytesReceived, + PDATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context) +/* + * FUNCTION: Attempts to receive an RawIp datagram from a remote address + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * Buffer = Pointer to NDIS buffer chain to store received data + * ReceiveLength = Maximum size to use of buffer, 0 if all can be used + * ReceiveFlags = Receive flags (None, Normal, Peek) + * ReturnInfo = Pointer to structure for return information + * BytesReceive = Pointer to structure for number of bytes received + * RETURNS: + * Status of operation + * NOTES: + * This is the high level interface for receiving RawIp datagrams + */ +{ + KIRQL OldIrql; + NTSTATUS Status; + PDATAGRAM_RECEIVE_REQUEST ReceiveRequest; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + if (AF_IS_VALID(AddrFile)) + { + ReceiveRequest = exAllocatePool(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST)); + if (ReceiveRequest) + { + /* Initialize a receive request */ + + /* Extract the remote address filter from the request (if any) */ + if ((ConnInfo->RemoteAddressLength != 0) && + (ConnInfo->RemoteAddress)) + { + Status = AddrGetAddress(ConnInfo->RemoteAddress, + &ReceiveRequest->RemoteAddress, + &ReceiveRequest->RemotePort); + if (!NT_SUCCESS(Status)) + { + TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql); + exFreePool(ReceiveRequest); + return Status; + } + } + else + { + ReceiveRequest->RemotePort = 0; + } + ReceiveRequest->ReturnInfo = ReturnInfo; + ReceiveRequest->Buffer = BufferData; + ReceiveRequest->BufferSize = ReceiveLength; + ReceiveRequest->UserComplete = Complete; + ReceiveRequest->UserContext = Context; + ReceiveRequest->Complete = + (PDATAGRAM_COMPLETION_ROUTINE)RawIpReceiveComplete; + ReceiveRequest->Context = ReceiveRequest; + + /* Queue receive request */ + InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry); + AF_SET_PENDING(AddrFile, AFF_RECEIVE); + + TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n")); + + return STATUS_PENDING; + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + Status = STATUS_INVALID_ADDRESS; + } + + TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status)); + return Status; } -VOID RawIPReceive( - PIP_INTERFACE Interface, - PIP_PACKET IPPacket) +VOID RawIpReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket) /* - * FUNCTION: Receives and queues a raw IP datagram + * FUNCTION: Receives and queues a RawIp datagram * ARGUMENTS: * NTE = Pointer to net table entry which the packet was received on - * IPPacket = Pointer to an IP packet that was received - * NOTES: - * This is the low level interface for receiving ICMP datagrams. - * It delivers the packet header and data to anyone that wants it - * When we get here the datagram has already passed sanity checks +* IPPacket = Pointer to an IP packet that was received +* NOTES: +* This is the low level interface for receiving RawIp datagrams. It strips +* the RawIp header from a packet and delivers the data to anyone that wants it +*/ +{ + AF_SEARCH SearchContext; + PIPv4_HEADER IPv4Header; + PADDRESS_FILE AddrFile; + PIP_ADDRESS DstAddress, SrcAddress; + UINT DataSize; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + switch (IPPacket->Type) { + /* IPv4 packet */ + case IP_ADDRESS_V4: + IPv4Header = IPPacket->Header; + DstAddress = &IPPacket->DstAddr; + SrcAddress = &IPPacket->SrcAddr; + DataSize = IPPacket->TotalSize; + break; + + /* IPv6 packet */ + case IP_ADDRESS_V6: + TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 datagram (%i bytes).\n", IPPacket->TotalSize)); + + /* FIXME: IPv6 is not supported */ + return; + + default: + return; + } + + /* Locate a receive request on destination address file object + and deliver the packet if one is found. If there is no receive + request on the address file object, call the associated receive + handler. If no receive handler is registered, drop the packet */ + + AddrFile = AddrSearchFirst(DstAddress, + 0, + IPv4Header->Protocol, + &SearchContext); + if (AddrFile) { + do { + DGDeliverData(AddrFile, + SrcAddress, + DstAddress, + 0, + 0, + IPPacket, + DataSize); + } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL); + } else { + /* There are no open address files that will take this datagram */ + /* FIXME: IPv4 only */ + TI_DbgPrint(MID_TRACE, ("Cannot deliver IPv4 raw datagram to address (0x%X).\n", + DN2H(DstAddress->Address.IPv4Address))); + + /* FIXME: Send ICMP reply */ + } + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +NTSTATUS RawIPStartup(VOID) +/* + * FUNCTION: Initializes the UDP subsystem + * RETURNS: + * Status of operation */ { - PIP_ADDRESS DstAddress; - - TI_DbgPrint(MAX_TRACE, ("Called.\n")); - - switch (IPPacket->Type) { - /* IPv4 packet */ - case IP_ADDRESS_V4: - DstAddress = &IPPacket->DstAddr; - break; - - /* IPv6 packet */ - case IP_ADDRESS_V6: - TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 raw IP datagram (%i bytes).\n", - IPPacket->TotalSize)); - - /* FIXME: IPv6 is not supported */ - return; - - default: - return; - } - - /* Locate a receive request on destination address file object - and deliver the packet if one is found. If there is no receive - request on the address file object, call the associated receive - handler. If no receive handler is registered, drop the packet */ - -#if 0 /* Decide what to do here */ - AddrFile = AddrSearchFirst(DstAddress, - 0, - IPPROTO_ICMP, - &SearchContext); - if (AddrFile) { - do { - DGDeliverData(AddrFile, - DstAddress, - IPPacket, - IPPacket->TotalSize); - } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL); - } else { - /* There are no open address files that will take this datagram */ - /* FIXME: IPv4 only */ - TI_DbgPrint(MID_TRACE, ("Cannot deliver IPv4 ICMP datagram to address (0x%X).\n", - DN2H(DstAddress->Address.IPv4Address))); - } +#ifdef __NTDRIVER__ + RtlZeroMemory(&UDPStats, sizeof(UDP_STATISTICS)); #endif - TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + /* Register this protocol with IP layer */ + IPRegisterProtocol(IPPROTO_ICMP, RawIpReceive); + + return STATUS_SUCCESS; } -NTSTATUS RawIPStartup( - VOID) +NTSTATUS RawIPShutdown(VOID) /* - * FUNCTION: Initializes the Raw IP subsystem + * FUNCTION: Shuts down the UDP subsystem * RETURNS: * Status of operation */ { - RawIPInitialized = TRUE; + /* Deregister this protocol with IP layer */ + IPRegisterProtocol(IPPROTO_ICMP, NULL); - return STATUS_SUCCESS; -} - - -NTSTATUS RawIPShutdown( - VOID) -/* - * FUNCTION: Shuts down the Raw IP subsystem - * RETURNS: - * Status of operation - */ -{ - if (!RawIPInitialized) - return STATUS_SUCCESS; - - return STATUS_SUCCESS; + return STATUS_SUCCESS; } /* EOF */ diff --git a/reactos/drivers/lib/ip/transport/udp/udp.c b/reactos/drivers/lib/ip/transport/udp/udp.c index 3cff36b752f..348458334a7 100644 --- a/reactos/drivers/lib/ip/transport/udp/udp.c +++ b/reactos/drivers/lib/ip/transport/udp/udp.c @@ -33,51 +33,19 @@ NTSTATUS AddUDPHeaderIPv4( * Status of operation */ { - PIPv4_HEADER IPHeader; PUDP_HEADER UDPHeader; - ULONG BufferSize; TI_DbgPrint(MID_TRACE, ("Packet: %x NdisPacket %x\n", IPPacket, IPPacket->NdisPacket)); - - BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + sizeof(UDP_HEADER); - - GetDataPtr( IPPacket->NdisPacket, - MaxLLHeaderSize, - (PCHAR *)&IPPacket->Header, - &IPPacket->ContigSize ); - - IPPacket->HeaderSize = 20; - - TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", - BufferSize, IPPacket->Header)); - TI_DbgPrint(MAX_TRACE, ("Packet total length %d\n", IPPacket->TotalSize)); - - /* Build IPv4 header */ - IPHeader = (PIPv4_HEADER)IPPacket->Header; - /* Version = 4, Length = 5 DWORDs */ - IPHeader->VerIHL = 0x45; - /* Normal Type-of-Service */ - IPHeader->Tos = 0; - /* Length of header and data */ - IPHeader->TotalLength = WH2N((USHORT)IPPacket->TotalSize); - /* Identification */ - IPHeader->Id = 0; - /* One fragment at offset 0 */ - IPHeader->FlagsFragOfs = 0; - /* Time-to-Live is 128 */ - IPHeader->Ttl = 128; - /* User Datagram Protocol */ - IPHeader->Protocol = IPPROTO_UDP; - /* Checksum is 0 (for later calculation of this) */ - IPHeader->Checksum = 0; - /* Source address */ - IPHeader->SrcAddr = LocalAddress->Address.IPv4Address; - /* Destination address. FIXME: IPv4 only */ - IPHeader->DstAddr = RemoteAddress->Address.IPv4Address; + + AddGenericHeaderIPv4 + ( RemoteAddress, RemotePort, + LocalAddress, LocalPort, + IPPacket, DataLength, IPPROTO_UDP, + sizeof(UDP_HEADER), (PVOID *)&UDPHeader ); /* Build UDP header */ - UDPHeader = (PUDP_HEADER)(((PCHAR)IPHeader) + sizeof(IPv4_HEADER)); + UDPHeader = (PUDP_HEADER)(IPPacket->Data - sizeof(UDP_HEADER)); /* Port values are already big-endian values */ UDPHeader->SourcePort = LocalPort; UDPHeader->DestPort = RemotePort; @@ -89,7 +57,7 @@ NTSTATUS AddUDPHeaderIPv4( IPPacket->Data = ((PCHAR)UDPHeader) + sizeof(UDP_HEADER); TI_DbgPrint(MID_TRACE, ("Packet: %d ip %d udp %d payload\n", - (PCHAR)UDPHeader - (PCHAR)IPHeader, + (PCHAR)UDPHeader - (PCHAR)IPPacket->Header, (PCHAR)IPPacket->Data - (PCHAR)UDPHeader, DataLength)); diff --git a/reactos/drivers/net/afd/afd/bind.c b/reactos/drivers/net/afd/afd/bind.c index 7312c9fc6f6..68235244ff6 100644 --- a/reactos/drivers/net/afd/afd/bind.c +++ b/reactos/drivers/net/afd/afd/bind.c @@ -74,10 +74,6 @@ AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* This will be the from address for subsequent recvfrom calls */ TdiBuildConnectionInfo( &FCB->AddressFrom, FCB->LocalAddress ); - /* Allocate our backup buffer */ - FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size ); - FCB->PollState |= AFD_EVENT_SEND; - /* A datagram socket is always sendable */ AFD_DbgPrint(MID_TRACE,("Calling TdiReceiveDatagram\n")); diff --git a/reactos/drivers/net/afd/afd/main.c b/reactos/drivers/net/afd/afd/main.c index 6eed0fe59e1..e12fe5488aa 100644 --- a/reactos/drivers/net/afd/afd/main.c +++ b/reactos/drivers/net/afd/afd/main.c @@ -132,6 +132,18 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, } FileObject->FsContext = FCB; + + /* It seems that UDP sockets are writable from inception */ + if( FCB->Flags & SGID_CONNECTIONLESS ) { + AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n")); + /* Allocate our backup buffer */ + FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size ); + FCB->Send.Window = ExAllocatePool( NonPagedPool, FCB->Send.Size ); + /* A datagram socket is always sendable */ + FCB->PollState |= AFD_EVENT_SEND; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } + Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); @@ -215,6 +227,8 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB->PollState |= AFD_EVENT_CLOSE; PollReeval( FCB->DeviceExt, FileObject ); + KillSelectsForFCB( FCB->DeviceExt, FileObject ); + if( FCB->EventSelect ) ObDereferenceObject( FCB->EventSelect ); FileObject->FsContext = NULL; diff --git a/reactos/drivers/net/afd/afd/select.c b/reactos/drivers/net/afd/afd/select.c index e5507b8b32b..b203dff5127 100644 --- a/reactos/drivers/net/afd/afd/select.c +++ b/reactos/drivers/net/afd/afd/select.c @@ -43,13 +43,23 @@ VOID RemoveSelect( PAFD_ACTIVE_POLL Poll ) { VOID SignalSocket( PAFD_ACTIVE_POLL Poll, PAFD_POLL_INFO PollReq, NTSTATUS Status ) { + int i; PIRP Irp = Poll->Irp; AFD_DbgPrint(MID_TRACE,("Called (Status %x)\n", Status)); + KeCancelTimer( &Poll->Timer ); Poll->Irp->IoStatus.Status = Status; Poll->Irp->IoStatus.Information = FIELD_OFFSET(AFD_POLL_INFO, Handles) + sizeof(AFD_HANDLE) * PollReq->HandleCount; CopyBackStatus( PollReq->Handles, PollReq->HandleCount ); + for( i = 0; i < PollReq->HandleCount; i++ ) { + AFD_DbgPrint + (MAX_TRACE, + ("Handle(%x): Got %x,%x\n", + PollReq->Handles[i].Handle, + PollReq->Handles[i].Events, + PollReq->Handles[i].Status)); + } UnlockHandles( AFD_HANDLES(PollReq), PollReq->HandleCount ); AFD_DbgPrint(MID_TRACE,("Completing\n")); IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); @@ -83,6 +93,41 @@ VOID SelectTimeout( PKDPC Dpc, AFD_DbgPrint(MID_TRACE,("Timeout\n")); } +VOID KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject ) { + KIRQL OldIrql; + PLIST_ENTRY ListEntry; + PAFD_ACTIVE_POLL Poll; + PIRP Irp; + PAFD_POLL_INFO PollReq; + int i; + + AFD_DbgPrint(MID_TRACE,("Killing selects that refer to %x\n", FileObject)); + + KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); + + ListEntry = DeviceExt->Polls.Flink; + while ( ListEntry != &DeviceExt->Polls ) { + Poll = CONTAINING_RECORD(ListEntry, AFD_ACTIVE_POLL, ListEntry); + ListEntry = ListEntry->Flink; + Irp = Poll->Irp; + PollReq = Irp->AssociatedIrp.SystemBuffer; + + for( i = 0; i < PollReq->HandleCount; i++ ) { + AFD_DbgPrint(MAX_TRACE,("Req: %x, This %x\n", + PollReq->Handles[i].Handle, FileObject)); + if( (PVOID)PollReq->Handles[i].Handle == FileObject ) { + ZeroEvents( PollReq->Handles, PollReq->HandleCount ); + SignalSocket( Poll, PollReq, STATUS_SUCCESS ); + } + } + } + + KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); + + AFD_DbgPrint(MID_TRACE,("Done\n")); +} + VOID KillExclusiveSelects( PAFD_DEVICE_EXTENSION DeviceExt ) { KIRQL OldIrql; PLIST_ENTRY ListEntry; diff --git a/reactos/drivers/net/afd/afd/write.c b/reactos/drivers/net/afd/afd/write.c index 9f87e746e2f..69d09ed1311 100644 --- a/reactos/drivers/net/afd/afd/write.c +++ b/reactos/drivers/net/afd/afd/write.c @@ -165,6 +165,9 @@ NTSTATUS DDKAPI PacketSocketSendComplete /* It's ok if the FCB already died */ if( !SocketAcquireStateLock( FCB ) ) return STATUS_SUCCESS; + FCB->PollState |= AFD_EVENT_SEND; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + FCB->SendIrp.InFlightRequest = NULL; /* Request is not in flight any longer */ @@ -361,6 +364,7 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE ); FCB->EventsFired &= ~AFD_EVENT_SEND; + FCB->PollState &= ~AFD_EVENT_SEND; /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND ) diff --git a/reactos/drivers/net/afd/include/afd.h b/reactos/drivers/net/afd/include/afd.h index 5814364f061..ac42942e75a 100644 --- a/reactos/drivers/net/afd/include/afd.h +++ b/reactos/drivers/net/afd/include/afd.h @@ -262,6 +262,8 @@ NTSTATUS STDCALL AfdEnumEvents( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ); VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceObject, PFILE_OBJECT FileObject ); +VOID KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject ); /* tdi.c */ diff --git a/reactos/drivers/net/tcpip/include/rawip.h b/reactos/drivers/net/tcpip/include/rawip.h index 26efd3d8b50..26b7a35398a 100644 --- a/reactos/drivers/net/tcpip/include/rawip.h +++ b/reactos/drivers/net/tcpip/include/rawip.h @@ -7,6 +7,8 @@ #ifndef __RAWIP_H #define __RAWIP_H + + NTSTATUS RawIPSendDatagram( PADDRESS_FILE AddrFile, PTDI_CONNECTION_INFORMATION ConnInfo, @@ -24,6 +26,17 @@ NTSTATUS RawIPStartup( NTSTATUS RawIPShutdown( VOID); +NTSTATUS AddGenericHeaderIPv4( + PIP_ADDRESS RemoteAddress, + USHORT RemotePort, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PIP_PACKET IPPacket, + UINT DataLength, + UINT Protocol, + UINT ExtraLength, + PVOID *NextHeader ); + #endif /* __RAWIP_H */ /* EOF */ diff --git a/reactos/drivers/net/tcpip/tcpip/dispatch.c b/reactos/drivers/net/tcpip/tcpip/dispatch.c index a9b183d52e0..378f2665c38 100644 --- a/reactos/drivers/net/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/net/tcpip/tcpip/dispatch.c @@ -924,12 +924,15 @@ NTSTATUS DispTdiSendDatagram( ("About to call send routine %x\n", (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send))); - Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)( - Request.Handle.AddressHandle, - DgramInfo->SendDatagramInformation, - DataBuffer, - BufferSize, - &Irp->IoStatus.Information); + if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send) ) + Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)( + Request.Handle.AddressHandle, + DgramInfo->SendDatagramInformation, + DataBuffer, + BufferSize, + &Irp->IoStatus.Information); + else + Status = STATUS_UNSUCCESSFUL; if (Status != STATUS_PENDING) { DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information); diff --git a/reactos/lib/msafd/misc/dllmain.c b/reactos/lib/msafd/misc/dllmain.c index b177d81ca28..749dcef4743 100644 --- a/reactos/lib/msafd/misc/dllmain.c +++ b/reactos/lib/msafd/misc/dllmain.c @@ -16,8 +16,8 @@ #include #ifdef DBG -//DWORD DebugTraceLevel = DEBUG_ULTRA; -DWORD DebugTraceLevel = 0; +DWORD DebugTraceLevel = DEBUG_ULTRA; +//DWORD DebugTraceLevel = 0; #endif /* DBG */ HANDLE GlobalHeap; @@ -123,8 +123,11 @@ WSPSocket( Socket->SanData = NULL; /* Ask alex about this */ - if( Socket->SharedData.SocketType == SOCK_DGRAM ) + if( Socket->SharedData.SocketType == SOCK_DGRAM || + Socket->SharedData.SocketType == SOCK_RAW ) { + AFD_DbgPrint(MID_TRACE,("Connectionless socket\n")); Socket->SharedData.ServiceFlags1 |= XP1_CONNECTIONLESS; + } /* Packet Size */ SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR);