1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS TCP/IP protocol driver 4 * FILE: network/icmp.c 5 * PURPOSE: Internet Control Message Protocol routines 6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * REVISIONS: 8 * CSH 01/08-2000 Created 9 */ 10 11 #include "precomp.h" 12 13 #include <icmp.h> 14 15 NTSTATUS ICMPStartup() 16 { 17 IPRegisterProtocol(IPPROTO_ICMP, ICMPReceive); 18 19 return STATUS_SUCCESS; 20 } 21 22 NTSTATUS ICMPShutdown() 23 { 24 IPRegisterProtocol(IPPROTO_ICMP, NULL); 25 26 return STATUS_SUCCESS; 27 } 28 29 NTSTATUS ICMPSendDatagram( 30 PADDRESS_FILE AddrFile, 31 PTDI_CONNECTION_INFORMATION ConnInfo, 32 PCHAR BufferData, 33 ULONG DataSize, 34 PULONG DataUsed ) 35 /* 36 * FUNCTION: Sends an ICMP datagram to a remote address 37 * ARGUMENTS: 38 * Request = Pointer to TDI request 39 * ConnInfo = Pointer to connection information 40 * Buffer = Pointer to NDIS buffer with data 41 * DataSize = Size in bytes of data to be sent 42 * RETURNS: 43 * Status of operation 44 */ 45 { 46 TI_DbgPrint(DEBUG_ICMP, ("Sending ICMP datagram (0x%x)\n", AddrFile)); 47 48 /* just forward the call to RawIP handler */ 49 return RawIPSendDatagram(AddrFile, ConnInfo, BufferData, DataSize, DataUsed); 50 } 51 52 53 VOID ICMPReceive( 54 PIP_INTERFACE Interface, 55 PIP_PACKET IPPacket) 56 /* 57 * FUNCTION: Receives an ICMP packet 58 * ARGUMENTS: 59 * NTE = Pointer to net table entry which the packet was received on 60 * IPPacket = Pointer to an IP packet that was received 61 */ 62 { 63 PICMP_HEADER ICMPHeader = (PICMP_HEADER)IPPacket->Data; 64 UINT32 DataSize = IPPacket->TotalSize - IPPacket->HeaderSize; 65 66 TI_DbgPrint(DEBUG_ICMP, ("ICMPReceive: Size (%d) HeaderSize (%d) Type (%d) Code (%d) Checksum (0x%x)\n", 67 IPPacket->TotalSize, IPPacket->HeaderSize, ICMPHeader->Type, ICMPHeader->Code, ICMPHeader->Checksum)); 68 69 /* Discard too short packets */ 70 if (DataSize < sizeof(ICMP_HEADER)) 71 { 72 TI_DbgPrint(DEBUG_ICMP, ("Packet doesn't fit ICMP header. Discarded\n")); 73 return; 74 } 75 76 /* Discard packets with bad checksum */ 77 if (!IPv4CorrectChecksum(IPPacket->Data, DataSize)) 78 { 79 TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum. Packet discarded\n")); 80 return; 81 } 82 83 RawIpReceive(Interface, IPPacket); 84 85 if (ICMPHeader->Type == ICMP_TYPE_ECHO_REQUEST) 86 { 87 ICMPReply(Interface, IPPacket, ICMP_TYPE_ECHO_REPLY, 0); 88 } 89 } 90 91 VOID ICMPReply( 92 PIP_INTERFACE Interface, 93 PIP_PACKET IPPacket, 94 UCHAR Type, 95 UCHAR Code) 96 /* 97 * FUNCTION: Transmits an ICMP packet in response to an incoming packet 98 * ARGUMENTS: 99 * NTE = Pointer to net table entry to use 100 * IPPacket = Pointer to IP packet that was received 101 * Type = ICMP message type 102 * Code = ICMP message code 103 * NOTES: 104 * We have received a packet from someone and is unable to 105 * process it due to error(s) in the packet or we have run out 106 * of resources. We transmit an ICMP message to the host to 107 * notify him of the problem 108 */ 109 { 110 UINT DataSize; 111 IP_PACKET NewPacket; 112 ADDRESS_FILE FakeAddrFile; 113 PNEIGHBOR_CACHE_ENTRY NCE; 114 115 TI_DbgPrint(DEBUG_ICMP, ("Called. Type (%d) Code (%d).\n", Type, Code)); 116 117 DataSize = IPPacket->TotalSize - IPPacket->HeaderSize; 118 119 /* First check if we have a route to sender */ 120 NCE = RouteGetRouteToDestination(&IPPacket->SrcAddr); 121 if (!NCE) 122 { 123 return; 124 } 125 126 /* This is the only data needed to generate a packet */ 127 FakeAddrFile.Protocol = IPPROTO_ICMP; 128 FakeAddrFile.TTL = 128; 129 130 if (!NT_SUCCESS(BuildRawIpPacket( 131 &FakeAddrFile, &NewPacket, &IPPacket->SrcAddr, 0, &Interface->Unicast, 0, IPPacket->Data, DataSize))) 132 { 133 return; 134 } 135 136 ((PICMP_HEADER)NewPacket.Data)->Type = Type; 137 ((PICMP_HEADER)NewPacket.Data)->Code = Code; 138 ((PICMP_HEADER)NewPacket.Data)->Checksum = 0; 139 ((PICMP_HEADER)NewPacket.Data)->Checksum = (USHORT)IPv4Checksum(NewPacket.Data, DataSize, 0); 140 141 IPSendDatagram(&NewPacket, NCE); 142 } 143 144 /* EOF */ 145