diff --git a/reactos/drivers/network/tcpip/include/icmp.h b/reactos/drivers/network/tcpip/include/icmp.h index 8351942831a..bb0e28a890a 100644 --- a/reactos/drivers/network/tcpip/include/icmp.h +++ b/reactos/drivers/network/tcpip/include/icmp.h @@ -48,6 +48,16 @@ typedef struct ICMP_HEADER { /* ICMP codes for ICMP_TYPE_PARAMETER */ #define ICMP_CODE_TP_POINTER 1 /* Pointer indicates the error */ +NTSTATUS ICMPSendDatagram( + PADDRESS_FILE AddrFile, + PTDI_CONNECTION_INFORMATION ConnInfo, + PCHAR BufferData, + ULONG DataSize, + PULONG DataUsed ); + +NTSTATUS ICMPStartup(); + +NTSTATUS ICMPShutdown(); VOID ICMPReceive( PIP_INTERFACE Interface, diff --git a/reactos/drivers/network/tcpip/include/rawip.h b/reactos/drivers/network/tcpip/include/rawip.h index 5bf5e8b73cd..85fa0bdf94b 100644 --- a/reactos/drivers/network/tcpip/include/rawip.h +++ b/reactos/drivers/network/tcpip/include/rawip.h @@ -14,7 +14,7 @@ NTSTATUS RawIPSendDatagram( ULONG DataSize, PULONG DataUsed); -VOID RawIPReceive( +VOID RawIpReceive( PIP_INTERFACE Interface, PIP_PACKET IPPacket); diff --git a/reactos/drivers/network/tcpip/tcpip/fileobjs.c b/reactos/drivers/network/tcpip/tcpip/fileobjs.c index 58ebee0e7bf..bcb20844c92 100644 --- a/reactos/drivers/network/tcpip/tcpip/fileobjs.c +++ b/reactos/drivers/network/tcpip/tcpip/fileobjs.c @@ -291,6 +291,11 @@ NTSTATUS FileOpenAddress( AddrFile->Send = UDPSendDatagram; break; + case IPPROTO_ICMP: + AddrFile->Port = 0; + AddrFile->Send = ICMPSendDatagram; + break; + default: /* Use raw IP for all other protocols */ AddrFile->Port = 0; diff --git a/reactos/drivers/network/tcpip/tcpip/main.c b/reactos/drivers/network/tcpip/tcpip/main.c index e92bcd9351e..9f4f6be431c 100644 --- a/reactos/drivers/network/tcpip/tcpip/main.c +++ b/reactos/drivers/network/tcpip/tcpip/main.c @@ -646,6 +646,7 @@ VOID NTAPI TiUnload( TCPShutdown(); UDPShutdown(); RawIPShutdown(); + ICMPShutdown(); /* Shutdown network level protocol subsystem */ IPShutdown(); @@ -885,6 +886,23 @@ DriverEntry( return Status; } + Status = ICMPStartup(); + if( !NT_SUCCESS(Status) ) { + TCPShutdown(); + UDPShutdown(); + RawIPShutdown(); + IPShutdown(); + ChewShutdown(); + IoDeleteDevice(IPDeviceObject); + IoDeleteDevice(RawIPDeviceObject); + IoDeleteDevice(UDPDeviceObject); + IoDeleteDevice(TCPDeviceObject); + exFreePool(EntityList); + NdisFreePacketPool(GlobalPacketPool); + NdisFreeBufferPool(GlobalBufferPool); + return Status; + } + /* Use direct I/O */ IPDeviceObject->Flags |= DO_DIRECT_IO; RawIPDeviceObject->Flags |= DO_DIRECT_IO; diff --git a/reactos/lib/drivers/ip/network/icmp.c b/reactos/lib/drivers/ip/network/icmp.c index 4fea4c7a419..ae022b8800b 100644 --- a/reactos/lib/drivers/ip/network/icmp.c +++ b/reactos/lib/drivers/ip/network/icmp.c @@ -10,6 +10,19 @@ #include "precomp.h" +NTSTATUS ICMPStartup() +{ + IPRegisterProtocol(IPPROTO_ICMP, ICMPReceive); + + return STATUS_SUCCESS; +} + +NTSTATUS ICMPShutdown() +{ + IPRegisterProtocol(IPPROTO_ICMP, NULL); + + return STATUS_SUCCESS; +} VOID SendICMPComplete( PVOID Context, @@ -118,6 +131,89 @@ BOOLEAN PrepareICMPPacket( return TRUE; } +VOID ICMPSendPacketComplete +( PVOID Context, PNDIS_PACKET Packet, NDIS_STATUS Status ) { + FreeNdisPacket( Packet ); +} + +NTSTATUS ICMPSendDatagram( + PADDRESS_FILE AddrFile, + PTDI_CONNECTION_INFORMATION ConnInfo, + PCHAR BufferData, + ULONG DataSize, + PULONG DataUsed ) +/* + * FUNCTION: Sends an ICMP datagram to a remote address + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * Buffer = Pointer to NDIS buffer with data + * DataSize = Size in bytes of data to be sent + * RETURNS: + * Status of operation + */ +{ + IP_PACKET Packet; + PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress; + IP_ADDRESS RemoteAddress, LocalAddress; + USHORT RemotePort; + NTSTATUS Status; + PNEIGHBOR_CACHE_ENTRY NCE; + + 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,("About to get route to destination\n")); + + if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) + return STATUS_NETWORK_UNREACHABLE; + + LocalAddress = AddrFile->Address; + if (AddrIsUnspecified(&LocalAddress)) + { + /* If the local address is unspecified (0), + * then use the unicast address of the + * interface we're sending over + */ + LocalAddress = NCE->Interface->Unicast; + } + + Status = PrepareICMPPacket( NCE->Interface, + &Packet, + &RemoteAddress, + BufferData, + DataSize ); + + if( !NT_SUCCESS(Status) ) + return Status; + + TI_DbgPrint(MID_TRACE,("About to send datagram\n")); + + if (!NT_SUCCESS(Status = IPSendDatagram( &Packet, NCE, ICMPSendPacketComplete, NULL ))) + { + FreeNdisPacket(Packet.NdisPacket); + return Status; + } + + TI_DbgPrint(MID_TRACE,("Leaving\n")); + + return STATUS_SUCCESS; +} + + VOID ICMPReceive( PIP_INTERFACE Interface, @@ -145,6 +241,8 @@ VOID ICMPReceive( TI_DbgPrint(DEBUG_ICMP, ("Checksum (0x%X).\n", ICMPHeader->Checksum)); + RawIpReceive(Interface, IPPacket); + /* Checksum ICMP header and data */ if (!IPv4CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) { TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum.\n")); diff --git a/reactos/lib/drivers/ip/network/ip.c b/reactos/lib/drivers/ip/network/ip.c index c6f0f464bb5..3653fd282ba 100644 --- a/reactos/lib/drivers/ip/network/ip.c +++ b/reactos/lib/drivers/ip/network/ip.c @@ -113,11 +113,6 @@ VOID IPDispatchProtocol( { /* Call the appropriate protocol handler */ (*ProtocolTable[Protocol])(Interface, IPPacket); - - /* Special case for ICMP -- ICMP can be caught by a SOCK_RAW but also - * must be handled here. */ - if( Protocol == IPPROTO_ICMP ) - ICMPReceive( Interface, IPPacket ); } } diff --git a/reactos/lib/drivers/ip/transport/rawip/rawip.c b/reactos/lib/drivers/ip/transport/rawip/rawip.c index aeb4cf12260..d77f753d1c8 100644 --- a/reactos/lib/drivers/ip/transport/rawip/rawip.c +++ b/reactos/lib/drivers/ip/transport/rawip/rawip.c @@ -126,7 +126,7 @@ NTSTATUS BuildRawIpPacket( Status = AddGenericHeaderIPv4 (RemoteAddress, RemotePort, LocalAddress, LocalPort, Packet, DataLen, - IPPROTO_ICMP, /* XXX Figure out a better way to do this */ + IPPROTO_RAW, 0, (PVOID *)&Payload ); break; case IP_ADDRESS_V6: @@ -332,7 +332,7 @@ NTSTATUS RawIPStartup(VOID) #endif /* Register this protocol with IP layer */ - IPRegisterProtocol(IPPROTO_ICMP, RawIpReceive); + IPRegisterProtocol(IPPROTO_RAW, RawIpReceive); return STATUS_SUCCESS; } @@ -346,7 +346,7 @@ NTSTATUS RawIPShutdown(VOID) */ { /* Deregister this protocol with IP layer */ - IPRegisterProtocol(IPPROTO_ICMP, NULL); + IPRegisterProtocol(IPPROTO_RAW, NULL); return STATUS_SUCCESS; }