- Properly implement ICMP

- Now Raw IP works correctly because it isn't being hacked to handle ICMP packets

svn path=/trunk/; revision=42087
This commit is contained in:
Cameron Gutman 2009-07-19 14:48:48 +00:00
parent a86419a500
commit b43fbb516b
7 changed files with 135 additions and 9 deletions

View file

@ -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,

View file

@ -14,7 +14,7 @@ NTSTATUS RawIPSendDatagram(
ULONG DataSize,
PULONG DataUsed);
VOID RawIPReceive(
VOID RawIpReceive(
PIP_INTERFACE Interface,
PIP_PACKET IPPacket);

View file

@ -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;

View file

@ -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;

View file

@ -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"));

View file

@ -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 );
}
}

View file

@ -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;
}