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
ICMPStartup()15 NTSTATUS ICMPStartup()
16 {
17 IPRegisterProtocol(IPPROTO_ICMP, ICMPReceive);
18
19 return STATUS_SUCCESS;
20 }
21
ICMPShutdown()22 NTSTATUS ICMPShutdown()
23 {
24 IPRegisterProtocol(IPPROTO_ICMP, NULL);
25
26 return STATUS_SUCCESS;
27 }
28
ICMPSendDatagram(PADDRESS_FILE AddrFile,PTDI_CONNECTION_INFORMATION ConnInfo,PCHAR BufferData,ULONG DataSize,PULONG DataUsed)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
ICMPReceive(PIP_INTERFACE Interface,PIP_PACKET IPPacket)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
ICMPReply(PIP_INTERFACE Interface,PIP_PACKET IPPacket,UCHAR Type,UCHAR Code)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