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
Modified: trunk/reactos/drivers/lib/ip/transport/datagram/datagram.c
Modified: trunk/reactos/drivers/lib/ip/transport/rawip/rawip.c
Modified: trunk/reactos/drivers/lib/ip/transport/udp/udp.c
Modified: trunk/reactos/drivers/net/afd/afd/bind.c
Modified: trunk/reactos/drivers/net/afd/afd/main.c
Modified: trunk/reactos/drivers/net/afd/afd/select.c
Modified: trunk/reactos/drivers/net/afd/afd/write.c
Modified: trunk/reactos/drivers/net/afd/include/afd.h
Modified: trunk/reactos/drivers/net/tcpip/include/rawip.h
Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c
Modified: trunk/reactos/lib/msafd/misc/dllmain.c

Modified: trunk/reactos/drivers/lib/ip/transport/datagram/datagram.c
--- trunk/reactos/drivers/lib/ip/transport/datagram/datagram.c	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/lib/ip/transport/datagram/datagram.c	2005-01-22 06:47:33 UTC (rev 13207)
@@ -86,6 +86,10 @@
       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,

Modified: trunk/reactos/drivers/lib/ip/transport/rawip/rawip.c
--- trunk/reactos/drivers/lib/ip/transport/rawip/rawip.c	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/lib/ip/transport/rawip/rawip.c	2005-01-22 06:47:33 UTC (rev 13207)
@@ -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"
 
+NTSTATUS AddGenericHeaderIPv4(
+    PIP_ADDRESS RemoteAddress,
+    USHORT RemotePort,
+    PIP_ADDRESS LocalAddress,
+    USHORT LocalPort,
+    PIP_PACKET IPPacket,
+    UINT DataLength,
+    UINT Protocol,
+    UINT ExtraLength,
+    PVOID *NextHeader ) 
+/*
+ * 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;
+}
 
-BOOLEAN RawIPInitialized = FALSE;
 
-
-NTSTATUS BuildRawIPPacket(
+NTSTATUS BuildRawIpPacket(
     PIP_PACKET Packet,
-    UINT DataLength,
+    PIP_ADDRESS RemoteAddress,
+    USHORT RemotePort,
     PIP_ADDRESS LocalAddress,
-    USHORT LocalPort )
+    USHORT LocalPort,
+    PCHAR DataBuffer,
+    UINT DataLen ) 
 /*
- * FUNCTION: Builds an UDP packet
+ * 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 @@
     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 @@
  *     Status of operation
  */
 {
-    NDIS_STATUS Status;
     IP_PACKET Packet;
+    PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress;
+    IP_ADDRESS RemoteAddress;
+    USHORT RemotePort;
+    NTSTATUS Status;
     PNEIGHBOR_CACHE_ENTRY NCE;
-    IP_ADDRESS RemoteAddress;
 
-    Status = AllocatePacketWithBuffer( &Packet.NdisPacket,
-				       BufferData,
-				       BufferLen );
+    TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
+			   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;
+
+    default:
+	return STATUS_UNSUCCESSFUL;
+    }
     
-    TI_DbgPrint(MID_TRACE,("Packet.NdisPacket %x\n", Packet.NdisPacket));
+    Status = BuildRawIpPacket( &Packet,
+                               &RemoteAddress,
+                               RemotePort,
+                               &AddrFile->Address,
+                               AddrFile->Port,
+                               BufferData,
+                               DataSize );
+    
+    if( !NT_SUCCESS(Status) ) 
+	return Status;
 
-    *DataUsed = BufferLen;
+    TI_DbgPrint(MID_TRACE,("About to get route to destination\n"));
 
-    if( Status == NDIS_STATUS_SUCCESS )
-	Status = BuildRawIPPacket( &Packet,
-				   BufferLen,
-				   &AddrFile->Address,
-				   AddrFile->Port );
+    if(!(NCE = RouteGetRouteToDestination( &RemoteAddress )))
+	return STATUS_UNSUCCESSFUL;
 
-    if( Status == NDIS_STATUS_SUCCESS ) {
-	RemoteAddress.Type = IP_ADDRESS_V4;
-	RtlCopyMemory( &RemoteAddress.Address.IPv4Address,
-		       BufferData + FIELD_OFFSET(IPv4_HEADER, DstAddr),
-		       sizeof(IPv4_RAW_ADDRESS) );
+    TI_DbgPrint(MID_TRACE,("About to send datagram\n"));
 
-	if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
-	    FreeNdisPacket( Packet.NdisPacket );
-	    return STATUS_NO_SUCH_DEVICE;
-	}
-	
-	IPSendDatagram( &Packet, NCE, RawIPSendComplete, NULL );
-    } else
-	FreeNdisPacket( Packet.NdisPacket );
+    IPSendDatagram( &Packet, NCE, RawIpSendPacketComplete, NULL );
 
-    return Status;
+    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"));
+}
 
-VOID RawIPReceive(
-    PIP_INTERFACE Interface,
-    PIP_PACKET IPPacket)
+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: Receives and queues a raw IP datagram
+ * FUNCTION: Attempts to receive an RawIp datagram from a remote address
  * ARGUMENTS:
- *     NTE      = Pointer to net table entry which the packet was received on
- *     IPPacket = Pointer to an IP packet that was received
+ *     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 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
+ *     This is the high level interface for receiving RawIp datagrams
  */
 {
-    PIP_ADDRESS DstAddress;
-
+    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;
+}
 
-    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));
+VOID RawIpReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
+/*
+ * 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 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;
 
-        /* FIXME: IPv6 is not supported */
-        return;
+  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
 
-    default:
-        return;
-    }
+  switch (IPPacket->Type) {
+  /* IPv4 packet */
+  case IP_ADDRESS_V4:
+    IPv4Header = IPPacket->Header;
+    DstAddress = &IPPacket->DstAddr;
+    SrcAddress = &IPPacket->SrcAddr;
+    DataSize = IPPacket->TotalSize;
+    break;
 
-    /* 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 */
+  /* IPv6 packet */
+  case IP_ADDRESS_V6:
+    TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 datagram (%i bytes).\n", IPPacket->TotalSize));
 
-#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)));
-    }
-#endif
-    TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+    /* 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)
+NTSTATUS RawIPStartup(VOID)
 /*
- * FUNCTION: Initializes the Raw IP subsystem
+ * FUNCTION: Initializes the UDP subsystem
  * RETURNS:
  *     Status of operation
  */
 {
-    RawIPInitialized = TRUE;
+#ifdef __NTDRIVER__
+  RtlZeroMemory(&UDPStats, sizeof(UDP_STATISTICS));
+#endif
 
-    return STATUS_SUCCESS;
+  /* Register this protocol with IP layer */
+  IPRegisterProtocol(IPPROTO_ICMP, RawIpReceive);
+
+  return STATUS_SUCCESS;
 }
 
 
-NTSTATUS RawIPShutdown(
-    VOID)
+NTSTATUS RawIPShutdown(VOID)
 /*
- * FUNCTION: Shuts down the Raw IP subsystem
+ * FUNCTION: Shuts down the UDP subsystem
  * RETURNS:
  *     Status of operation
  */
 {
-    if (!RawIPInitialized)
-        return STATUS_SUCCESS;
+  /* Deregister this protocol with IP layer */
+  IPRegisterProtocol(IPPROTO_ICMP, NULL);
 
-    return STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
 /* EOF */

Modified: trunk/reactos/drivers/lib/ip/transport/udp/udp.c
--- trunk/reactos/drivers/lib/ip/transport/udp/udp.c	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/lib/ip/transport/udp/udp.c	2005-01-22 06:47:33 UTC (rev 13207)
@@ -33,51 +33,19 @@
  *     Status of operation
  */
 {
-    PIPv4_HEADER IPHeader;
     PUDP_HEADER UDPHeader;
-    ULONG BufferSize;
     
     TI_DbgPrint(MID_TRACE, ("Packet: %x NdisPacket %x\n", 
 			    IPPacket, IPPacket->NdisPacket));
+
+    AddGenericHeaderIPv4
+        ( RemoteAddress, RemotePort,
+          LocalAddress, LocalPort,
+          IPPacket, DataLength, IPPROTO_UDP, 
+          sizeof(UDP_HEADER), (PVOID *)&UDPHeader );
     
-    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;
-    
     /* 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 @@
     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));
 

Modified: trunk/reactos/drivers/net/afd/afd/bind.c
--- trunk/reactos/drivers/net/afd/afd/bind.c	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/net/afd/afd/bind.c	2005-01-22 06:47:33 UTC (rev 13207)
@@ -74,10 +74,6 @@
 	/* 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"));
 	

Modified: trunk/reactos/drivers/net/afd/afd/main.c
--- trunk/reactos/drivers/net/afd/afd/main.c	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/net/afd/afd/main.c	2005-01-22 06:47:33 UTC (rev 13207)
@@ -132,6 +132,18 @@
     }
 
     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 @@
 
     FCB->PollState |= AFD_EVENT_CLOSE;
     PollReeval( FCB->DeviceExt, FileObject );
+    KillSelectsForFCB( FCB->DeviceExt, FileObject );
+
     if( FCB->EventSelect ) ObDereferenceObject( FCB->EventSelect );
 
     FileObject->FsContext = NULL;

Modified: trunk/reactos/drivers/net/afd/afd/select.c
--- trunk/reactos/drivers/net/afd/afd/select.c	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/net/afd/afd/select.c	2005-01-22 06:47:33 UTC (rev 13207)
@@ -43,13 +43,23 @@
 
 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 @@
     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;

Modified: trunk/reactos/drivers/net/afd/afd/write.c
--- trunk/reactos/drivers/net/afd/afd/write.c	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/net/afd/afd/write.c	2005-01-22 06:47:33 UTC (rev 13207)
@@ -165,6 +165,9 @@
     /* 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 @@
     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 ) 

Modified: trunk/reactos/drivers/net/afd/include/afd.h
--- trunk/reactos/drivers/net/afd/include/afd.h	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/net/afd/include/afd.h	2005-01-22 06:47:33 UTC (rev 13207)
@@ -262,6 +262,8 @@
 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 */
 

Modified: trunk/reactos/drivers/net/tcpip/include/rawip.h
--- trunk/reactos/drivers/net/tcpip/include/rawip.h	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/net/tcpip/include/rawip.h	2005-01-22 06:47:33 UTC (rev 13207)
@@ -7,6 +7,8 @@
 #ifndef __RAWIP_H
 #define __RAWIP_H
 
+
+
 NTSTATUS RawIPSendDatagram(
     PADDRESS_FILE AddrFile,
     PTDI_CONNECTION_INFORMATION ConnInfo,
@@ -24,6 +26,17 @@
 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 */

Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c
--- trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c	2005-01-22 06:47:33 UTC (rev 13207)
@@ -924,12 +924,15 @@
 		    ("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);

Modified: trunk/reactos/lib/msafd/misc/dllmain.c
--- trunk/reactos/lib/msafd/misc/dllmain.c	2005-01-22 03:54:23 UTC (rev 13206)
+++ trunk/reactos/lib/msafd/misc/dllmain.c	2005-01-22 06:47:33 UTC (rev 13207)
@@ -16,8 +16,8 @@
 #include <rosrtl/string.h>
 
 #ifdef DBG
-//DWORD DebugTraceLevel = DEBUG_ULTRA;
-DWORD DebugTraceLevel = 0;
+DWORD DebugTraceLevel = DEBUG_ULTRA;
+//DWORD DebugTraceLevel = 0;
 #endif /* DBG */
 
 HANDLE GlobalHeap;
@@ -123,8 +123,11 @@
 	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);