mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 18:37:08 +00:00
[TCPIP] Implement IOCTL_ICMP_ECHO_REQUEST in tcpip.sys
Also clean up ICMP handling code in sdk/lib/drivers/ip CORE-10760
This commit is contained in:
parent
dd2ff41dfc
commit
740a859e92
9 changed files with 505 additions and 241 deletions
|
@ -26,95 +26,6 @@ NTSTATUS ICMPShutdown()
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN PrepareICMPPacket(
|
||||
PADDRESS_FILE AddrFile,
|
||||
PIP_INTERFACE Interface,
|
||||
PIP_PACKET IPPacket,
|
||||
PIP_ADDRESS Destination,
|
||||
PCHAR Data,
|
||||
UINT DataSize)
|
||||
/*
|
||||
* FUNCTION: Prepares an ICMP packet
|
||||
* ARGUMENTS:
|
||||
* NTE = Pointer to net table entry to use
|
||||
* Destination = Pointer to destination address
|
||||
* DataSize = Size of dataarea
|
||||
* RETURNS:
|
||||
* Pointer to IP packet, NULL if there is not enough free resources
|
||||
*/
|
||||
{
|
||||
PNDIS_PACKET NdisPacket;
|
||||
NDIS_STATUS NdisStatus;
|
||||
PIPv4_HEADER IPHeader;
|
||||
ULONG Size;
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Called. DataSize (%d).\n", DataSize));
|
||||
|
||||
IPInitializePacket(IPPacket, IP_ADDRESS_V4);
|
||||
|
||||
/* No special flags */
|
||||
IPPacket->Flags = 0;
|
||||
|
||||
Size = sizeof(IPv4_HEADER) + DataSize;
|
||||
|
||||
/* Allocate NDIS packet */
|
||||
NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Size );
|
||||
|
||||
if( !NT_SUCCESS(NdisStatus) ) return FALSE;
|
||||
|
||||
IPPacket->NdisPacket = NdisPacket;
|
||||
IPPacket->MappedHeader = TRUE;
|
||||
|
||||
GetDataPtr( IPPacket->NdisPacket, 0,
|
||||
(PCHAR *)&IPPacket->Header, &IPPacket->TotalSize );
|
||||
ASSERT(IPPacket->TotalSize == Size);
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Size (%d). Data at (0x%X).\n", Size, Data));
|
||||
TI_DbgPrint(DEBUG_ICMP, ("NdisPacket at (0x%X).\n", NdisPacket));
|
||||
|
||||
IPPacket->HeaderSize = sizeof(IPv4_HEADER);
|
||||
IPPacket->Data = ((PCHAR)IPPacket->Header) + IPPacket->HeaderSize;
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Copying Address: %x -> %x\n",
|
||||
&IPPacket->DstAddr, Destination));
|
||||
|
||||
RtlCopyMemory(&IPPacket->DstAddr, Destination, sizeof(IP_ADDRESS));
|
||||
RtlCopyMemory(IPPacket->Data, Data, DataSize);
|
||||
|
||||
/* Build IPv4 header. FIXME: IPv4 only */
|
||||
|
||||
IPHeader = (PIPv4_HEADER)IPPacket->Header;
|
||||
|
||||
/* Version = 4, Length = 5 DWORDs */
|
||||
IPHeader->VerIHL = 0x45;
|
||||
/* Normal Type-of-Service */
|
||||
IPHeader->Tos = 0;
|
||||
/* Length of data and header */
|
||||
IPHeader->TotalLength = WH2N((USHORT)DataSize + sizeof(IPv4_HEADER));
|
||||
/* Identification */
|
||||
IPHeader->Id = (USHORT)Random();
|
||||
/* One fragment at offset 0 */
|
||||
IPHeader->FlagsFragOfs = 0;
|
||||
/* Set TTL */
|
||||
if (AddrFile)
|
||||
IPHeader->Ttl = AddrFile->TTL;
|
||||
else
|
||||
IPHeader->Ttl = 128;
|
||||
/* Internet Control Message Protocol */
|
||||
IPHeader->Protocol = IPPROTO_ICMP;
|
||||
/* Checksum is 0 (for later calculation of this) */
|
||||
IPHeader->Checksum = 0;
|
||||
/* Source address */
|
||||
IPHeader->SrcAddr = Interface->Unicast.Address.IPv4Address;
|
||||
/* Destination address */
|
||||
IPHeader->DstAddr = Destination->Address.IPv4Address;
|
||||
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("Leaving\n"));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NTSTATUS ICMPSendDatagram(
|
||||
PADDRESS_FILE AddrFile,
|
||||
PTDI_CONNECTION_INFORMATION ConnInfo,
|
||||
|
@ -132,79 +43,10 @@ NTSTATUS ICMPSendDatagram(
|
|||
* Status of operation
|
||||
*/
|
||||
{
|
||||
IP_PACKET Packet;
|
||||
PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress;
|
||||
IP_ADDRESS RemoteAddress, LocalAddress;
|
||||
NTSTATUS Status;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
KIRQL OldIrql;
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Sending ICMP datagram (0x%x)\n", AddrFile));
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
default:
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("About to get route to destination\n"));
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
|
||||
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
|
||||
*/
|
||||
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress )))
|
||||
{
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
return STATUS_NETWORK_UNREACHABLE;
|
||||
}
|
||||
|
||||
LocalAddress = NCE->Interface->Unicast;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL )))
|
||||
{
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
Status = PrepareICMPPacket( AddrFile,
|
||||
NCE->Interface,
|
||||
&Packet,
|
||||
&RemoteAddress,
|
||||
BufferData,
|
||||
DataSize );
|
||||
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
|
||||
if( !NT_SUCCESS(Status) )
|
||||
return Status;
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("About to send datagram\n"));
|
||||
|
||||
Status = IPSendDatagram(&Packet, NCE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
*DataUsed = DataSize;
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("Leaving\n"));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
/* just forward the call to RawIP handler */
|
||||
return RawIPSendDatagram(AddrFile, ConnInfo, BufferData, DataSize, DataUsed);
|
||||
}
|
||||
|
||||
|
||||
|
@ -218,81 +60,34 @@ VOID ICMPReceive(
|
|||
* IPPacket = Pointer to an IP packet that was received
|
||||
*/
|
||||
{
|
||||
PICMP_HEADER ICMPHeader;
|
||||
PICMP_HEADER ICMPHeader = (PICMP_HEADER)IPPacket->Data;
|
||||
UINT32 DataSize = IPPacket->TotalSize - IPPacket->HeaderSize;
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
|
||||
TI_DbgPrint(DEBUG_ICMP, ("ICMPReceive: Size (%d) HeaderSize (%d) Type (%d) Code (%d) Checksum (0x%x)\n",
|
||||
IPPacket->TotalSize, IPPacket->HeaderSize, ICMPHeader->Type, ICMPHeader->Code, ICMPHeader->Checksum));
|
||||
|
||||
ICMPHeader = (PICMP_HEADER)IPPacket->Data;
|
||||
/* Discard too short packets */
|
||||
if (DataSize < sizeof(ICMP_HEADER))
|
||||
{
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Packet doesn't fit ICMP header. Discarded\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Size (%d).\n", IPPacket->TotalSize));
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("HeaderSize (%d).\n", IPPacket->HeaderSize));
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Type (%d).\n", ICMPHeader->Type));
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Code (%d).\n", ICMPHeader->Code));
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Checksum (0x%X).\n", ICMPHeader->Checksum));
|
||||
|
||||
/* Checksum ICMP header and data */
|
||||
if (!IPv4CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) {
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum.\n"));
|
||||
/* Discard packet */
|
||||
/* Discard packets with bad checksum */
|
||||
if (!IPv4CorrectChecksum(IPPacket->Data, DataSize))
|
||||
{
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum. Packet discarded\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
RawIpReceive(Interface, IPPacket);
|
||||
|
||||
switch (ICMPHeader->Type) {
|
||||
case ICMP_TYPE_ECHO_REQUEST:
|
||||
ICMPReply( Interface, IPPacket, ICMP_TYPE_ECHO_REPLY, 0 );
|
||||
break;
|
||||
|
||||
case ICMP_TYPE_ECHO_REPLY:
|
||||
break;
|
||||
|
||||
default:
|
||||
TI_DbgPrint(DEBUG_ICMP,
|
||||
("Discarded ICMP datagram of unknown type %d.\n",
|
||||
ICMPHeader->Type));
|
||||
/* Discard packet */
|
||||
break;
|
||||
if (ICMPHeader->Type == ICMP_TYPE_ECHO_REQUEST)
|
||||
{
|
||||
ICMPReply(Interface, IPPacket, ICMP_TYPE_ECHO_REPLY, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID ICMPTransmit(
|
||||
PIP_PACKET IPPacket,
|
||||
PIP_TRANSMIT_COMPLETE Complete,
|
||||
PVOID Context)
|
||||
/*
|
||||
* FUNCTION: Transmits an ICMP packet
|
||||
* ARGUMENTS:
|
||||
* NTE = Pointer to net table entry to use (NULL if don't care)
|
||||
* IPPacket = Pointer to IP packet to transmit
|
||||
*/
|
||||
{
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
|
||||
|
||||
/* Calculate checksum of ICMP header and data */
|
||||
((PICMP_HEADER)IPPacket->Data)->Checksum = (USHORT)
|
||||
IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0);
|
||||
|
||||
/* Get a route to the destination address */
|
||||
if ((NCE = RouteGetRouteToDestination(&IPPacket->DstAddr))) {
|
||||
/* Send the packet */
|
||||
IPSendDatagram(IPPacket, NCE);
|
||||
} else {
|
||||
/* No route to destination (or no free resources) */
|
||||
TI_DbgPrint(DEBUG_ICMP, ("No route to destination address 0x%X.\n",
|
||||
IPPacket->DstAddr.Address.IPv4Address));
|
||||
IPPacket->Free(IPPacket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID ICMPReply(
|
||||
PIP_INTERFACE Interface,
|
||||
PIP_PACKET IPPacket,
|
||||
|
@ -314,19 +109,36 @@ VOID ICMPReply(
|
|||
{
|
||||
UINT DataSize;
|
||||
IP_PACKET NewPacket;
|
||||
ADDRESS_FILE FakeAddrFile;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Called. Type (%d) Code (%d).\n", Type, Code));
|
||||
|
||||
DataSize = IPPacket->TotalSize - IPPacket->HeaderSize;
|
||||
|
||||
if( !PrepareICMPPacket(NULL, Interface, &NewPacket, &IPPacket->SrcAddr,
|
||||
IPPacket->Data, DataSize) ) return;
|
||||
/* First check if we have a route to sender */
|
||||
NCE = RouteGetRouteToDestination(&IPPacket->SrcAddr);
|
||||
if (!NCE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is the only data needed to generate a packet */
|
||||
FakeAddrFile.Protocol = IPPROTO_ICMP;
|
||||
FakeAddrFile.TTL = 128;
|
||||
|
||||
if (!NT_SUCCESS(BuildRawIpPacket(
|
||||
&FakeAddrFile, &NewPacket, &IPPacket->SrcAddr, 0, &Interface->Unicast, 0, IPPacket->Data, DataSize)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
((PICMP_HEADER)NewPacket.Data)->Type = Type;
|
||||
((PICMP_HEADER)NewPacket.Data)->Code = Code;
|
||||
((PICMP_HEADER)NewPacket.Data)->Checksum = 0;
|
||||
((PICMP_HEADER)NewPacket.Data)->Checksum = (USHORT)IPv4Checksum(NewPacket.Data, DataSize, 0);
|
||||
|
||||
ICMPTransmit(&NewPacket, NULL, NULL);
|
||||
IPSendDatagram(&NewPacket, NCE);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -46,7 +46,7 @@ NTSTATUS AddGenericHeaderIPv4(
|
|||
&IPPacket->TotalSize );
|
||||
IPPacket->MappedHeader = TRUE;
|
||||
|
||||
IPPacket->HeaderSize = 20;
|
||||
IPPacket->HeaderSize = sizeof(IPv4_HEADER);
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n",
|
||||
BufferSize, IPPacket->Header));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue