ReactOS  0.4.14-dev-614-gbfd8a84
icmp.c
Go to the documentation of this file.
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 
16 {
18 
19  return STATUS_SUCCESS;
20 }
21 
23 {
25 
26  return STATUS_SUCCESS;
27 }
28 
30  PADDRESS_FILE AddrFile,
32  PIP_PACKET IPPacket,
34  PCHAR Data,
35  UINT DataSize)
36 /*
37  * FUNCTION: Prepares an ICMP packet
38  * ARGUMENTS:
39  * NTE = Pointer to net table entry to use
40  * Destination = Pointer to destination address
41  * DataSize = Size of dataarea
42  * RETURNS:
43  * Pointer to IP packet, NULL if there is not enough free resources
44  */
45 {
46  PNDIS_PACKET NdisPacket;
47  NDIS_STATUS NdisStatus;
48  PIPv4_HEADER IPHeader;
49  ULONG Size;
50 
51  TI_DbgPrint(DEBUG_ICMP, ("Called. DataSize (%d).\n", DataSize));
52 
54 
55  /* No special flags */
56  IPPacket->Flags = 0;
57 
58  Size = sizeof(IPv4_HEADER) + DataSize;
59 
60  /* Allocate NDIS packet */
61  NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Size );
62 
63  if( !NT_SUCCESS(NdisStatus) ) return FALSE;
64 
65  IPPacket->NdisPacket = NdisPacket;
66  IPPacket->MappedHeader = TRUE;
67 
68  GetDataPtr( IPPacket->NdisPacket, 0,
69  (PCHAR *)&IPPacket->Header, &IPPacket->TotalSize );
70  ASSERT(IPPacket->TotalSize == Size);
71 
72  TI_DbgPrint(DEBUG_ICMP, ("Size (%d). Data at (0x%X).\n", Size, Data));
73  TI_DbgPrint(DEBUG_ICMP, ("NdisPacket at (0x%X).\n", NdisPacket));
74 
75  IPPacket->HeaderSize = sizeof(IPv4_HEADER);
76  IPPacket->Data = ((PCHAR)IPPacket->Header) + IPPacket->HeaderSize;
77 
78  TI_DbgPrint(DEBUG_ICMP, ("Copying Address: %x -> %x\n",
79  &IPPacket->DstAddr, Destination));
80 
81  RtlCopyMemory(&IPPacket->DstAddr, Destination, sizeof(IP_ADDRESS));
82  RtlCopyMemory(IPPacket->Data, Data, DataSize);
83 
84  /* Build IPv4 header. FIXME: IPv4 only */
85 
86  IPHeader = (PIPv4_HEADER)IPPacket->Header;
87 
88  /* Version = 4, Length = 5 DWORDs */
89  IPHeader->VerIHL = 0x45;
90  /* Normal Type-of-Service */
91  IPHeader->Tos = 0;
92  /* Length of data and header */
93  IPHeader->TotalLength = WH2N((USHORT)DataSize + sizeof(IPv4_HEADER));
94  /* Identification */
95  IPHeader->Id = (USHORT)Random();
96  /* One fragment at offset 0 */
97  IPHeader->FlagsFragOfs = 0;
98  /* Set TTL */
99  if (AddrFile)
100  IPHeader->Ttl = AddrFile->TTL;
101  else
102  IPHeader->Ttl = 128;
103  /* Internet Control Message Protocol */
104  IPHeader->Protocol = IPPROTO_ICMP;
105  /* Checksum is 0 (for later calculation of this) */
106  IPHeader->Checksum = 0;
107  /* Source address */
108  IPHeader->SrcAddr = Interface->Unicast.Address.IPv4Address;
109  /* Destination address */
110  IPHeader->DstAddr = Destination->Address.IPv4Address;
111 
112 
113  TI_DbgPrint(MID_TRACE,("Leaving\n"));
114 
115  return TRUE;
116 }
117 
119  PADDRESS_FILE AddrFile,
121  PCHAR BufferData,
122  ULONG DataSize,
123  PULONG DataUsed )
124 /*
125  * FUNCTION: Sends an ICMP datagram to a remote address
126  * ARGUMENTS:
127  * Request = Pointer to TDI request
128  * ConnInfo = Pointer to connection information
129  * Buffer = Pointer to NDIS buffer with data
130  * DataSize = Size in bytes of data to be sent
131  * RETURNS:
132  * Status of operation
133  */
134 {
136  PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress;
140  KIRQL OldIrql;
141 
142  TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
143  AddrFile, ConnInfo, BufferData, DataSize));
144  TI_DbgPrint(MID_TRACE,("RemoteAddressTa: %x\n", RemoteAddressTa));
145 
146  switch( RemoteAddressTa->Address[0].AddressType ) {
147  case TDI_ADDRESS_TYPE_IP:
149  RemoteAddress.Address.IPv4Address =
150  RemoteAddressTa->Address[0].Address[0].in_addr;
151  break;
152 
153  default:
154  return STATUS_UNSUCCESSFUL;
155  }
156 
157  TI_DbgPrint(MID_TRACE,("About to get route to destination\n"));
158 
159  LockObject(AddrFile, &OldIrql);
160 
161  LocalAddress = AddrFile->Address;
163  {
164  /* If the local address is unspecified (0),
165  * then use the unicast address of the
166  * interface we're sending over
167  */
169  {
170  UnlockObject(AddrFile, OldIrql);
172  }
173 
174  LocalAddress = NCE->Interface->Unicast;
175  }
176  else
177  {
178  if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL )))
179  {
180  UnlockObject(AddrFile, OldIrql);
182  }
183  }
184 
185  Status = PrepareICMPPacket( AddrFile,
186  NCE->Interface,
187  &Packet,
188  &RemoteAddress,
189  BufferData,
190  DataSize );
191 
192  UnlockObject(AddrFile, OldIrql);
193 
194  if( !NT_SUCCESS(Status) )
195  return Status;
196 
197  TI_DbgPrint(MID_TRACE,("About to send datagram\n"));
198 
199  Status = IPSendDatagram(&Packet, NCE);
200  if (!NT_SUCCESS(Status))
201  return Status;
202 
203  *DataUsed = DataSize;
204 
205  TI_DbgPrint(MID_TRACE,("Leaving\n"));
206 
207  return STATUS_SUCCESS;
208 }
209 
210 
213  PIP_PACKET IPPacket)
214 /*
215  * FUNCTION: Receives an ICMP packet
216  * ARGUMENTS:
217  * NTE = Pointer to net table entry which the packet was received on
218  * IPPacket = Pointer to an IP packet that was received
219  */
220 {
221  PICMP_HEADER ICMPHeader;
222 
223  TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
224 
225  ICMPHeader = (PICMP_HEADER)IPPacket->Data;
226 
227  TI_DbgPrint(DEBUG_ICMP, ("Size (%d).\n", IPPacket->TotalSize));
228 
229  TI_DbgPrint(DEBUG_ICMP, ("HeaderSize (%d).\n", IPPacket->HeaderSize));
230 
231  TI_DbgPrint(DEBUG_ICMP, ("Type (%d).\n", ICMPHeader->Type));
232 
233  TI_DbgPrint(DEBUG_ICMP, ("Code (%d).\n", ICMPHeader->Code));
234 
235  TI_DbgPrint(DEBUG_ICMP, ("Checksum (0x%X).\n", ICMPHeader->Checksum));
236 
237  /* Checksum ICMP header and data */
238  if (!IPv4CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) {
239  TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum.\n"));
240  /* Discard packet */
241  return;
242  }
243 
244  RawIpReceive(Interface, IPPacket);
245 
246  switch (ICMPHeader->Type) {
248  ICMPReply( Interface, IPPacket, ICMP_TYPE_ECHO_REPLY, 0 );
249  break;
250 
252  break;
253 
254  default:
256  ("Discarded ICMP datagram of unknown type %d.\n",
257  ICMPHeader->Type));
258  /* Discard packet */
259  break;
260  }
261 }
262 
263 
265  PIP_PACKET IPPacket,
266  PIP_TRANSMIT_COMPLETE Complete,
267  PVOID Context)
268 /*
269  * FUNCTION: Transmits an ICMP packet
270  * ARGUMENTS:
271  * NTE = Pointer to net table entry to use (NULL if don't care)
272  * IPPacket = Pointer to IP packet to transmit
273  */
274 {
276 
277  TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
278 
279  /* Calculate checksum of ICMP header and data */
280  ((PICMP_HEADER)IPPacket->Data)->Checksum = (USHORT)
281  IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0);
282 
283  /* Get a route to the destination address */
284  if ((NCE = RouteGetRouteToDestination(&IPPacket->DstAddr))) {
285  /* Send the packet */
286  IPSendDatagram(IPPacket, NCE);
287  } else {
288  /* No route to destination (or no free resources) */
289  TI_DbgPrint(DEBUG_ICMP, ("No route to destination address 0x%X.\n",
290  IPPacket->DstAddr.Address.IPv4Address));
291  IPPacket->Free(IPPacket);
292  }
293 }
294 
295 
298  PIP_PACKET IPPacket,
299  UCHAR Type,
300  UCHAR Code)
301 /*
302  * FUNCTION: Transmits an ICMP packet in response to an incoming packet
303  * ARGUMENTS:
304  * NTE = Pointer to net table entry to use
305  * IPPacket = Pointer to IP packet that was received
306  * Type = ICMP message type
307  * Code = ICMP message code
308  * NOTES:
309  * We have received a packet from someone and is unable to
310  * process it due to error(s) in the packet or we have run out
311  * of resources. We transmit an ICMP message to the host to
312  * notify him of the problem
313  */
314 {
315  UINT DataSize;
316  IP_PACKET NewPacket;
317 
318  TI_DbgPrint(DEBUG_ICMP, ("Called. Type (%d) Code (%d).\n", Type, Code));
319 
320  DataSize = IPPacket->TotalSize - IPPacket->HeaderSize;
321 
322  if( !PrepareICMPPacket(NULL, Interface, &NewPacket, &IPPacket->SrcAddr,
323  IPPacket->Data, DataSize) ) return;
324 
325  ((PICMP_HEADER)NewPacket.Data)->Type = Type;
326  ((PICMP_HEADER)NewPacket.Data)->Code = Code;
327  ((PICMP_HEADER)NewPacket.Data)->Checksum = 0;
328 
329  ICMPTransmit(&NewPacket, NULL, NULL);
330 }
331 
332 /* EOF */
BOOLEAN AddrIsUnspecified(PIP_ADDRESS Address)
Definition: address.c:113
signed char * PCHAR
Definition: retypes.h:7
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
IPv4_RAW_ADDRESS IPv4Address
Definition: ip.h:26
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define MID_TRACE
Definition: debug.h:15
VOID(* PIP_TRANSMIT_COMPLETE)(PVOID Context, PNDIS_PACKET Packet, NDIS_STATUS Status)
Definition: transmit.h:10
Type
Definition: Type.h:6
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1548
UCHAR Tos
Definition: ip.h:39
UCHAR TTL
Definition: titypes.h:141
Definition: neighbor.h:28
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
void GetDataPtr(PNDIS_PACKET Packet, UINT Offset, PCHAR *DataOut, PUINT Size)
Definition: routines.c:65
struct _TA_ADDRESS_IP * PTA_IP_ADDRESS
IP_ADDRESS SrcAddr
Definition: ip.h:89
LONG NTSTATUS
Definition: precomp.h:26
USHORT TotalLength
Definition: ip.h:40
VOID ICMPReply(PIP_INTERFACE Interface, PIP_PACKET IPPacket, UCHAR Type, UCHAR Code)
Definition: icmp.c:296
#define WH2N(w)
Definition: addrconv.c:40
PNEIGHBOR_CACHE_ENTRY RouteGetRouteToDestination(PIP_ADDRESS Destination)
Definition: router.c:300
PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(PIP_ADDRESS Address, PIP_INTERFACE Interface)
Definition: neighbor.c:417
OBJECT_FREE_ROUTINE Free
Definition: ip.h:78
VOID IPRegisterProtocol(UINT ProtocolNumber, IP_PROTOCOL_HANDLER Handler)
Definition: ip.c:390
int NDIS_STATUS
Definition: ntddndis.h:471
#define LockObject(Object, Irql)
Definition: titypes.h:34
PVOID Data
Definition: ip.h:85
Definition: ip.h:23
UCHAR KIRQL
Definition: env_spec_w32.h:591
USHORT FlagsFragOfs
Definition: ip.h:42
#define IP_ADDRESS_V4
Definition: ip.h:32
PIP_PACKET IPInitializePacket(PIP_PACKET IPPacket, ULONG Type)
Definition: ip.c:92
#define UnlockObject(Object, OldIrql)
Definition: titypes.h:54
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE)
Definition: transmit.c:223
#define IPv4Checksum(Data, Count, Seed)
Definition: checksum.h:30
UCHAR VerIHL
Definition: ip.h:38
#define AllocatePacketWithBuffer(x, y, z)
Definition: memtrack.h:7
PVOID Header
Definition: ip.h:83
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define DEBUG_ICMP
Definition: debug.h:29
UCHAR Type
Definition: icmp.h:11
struct _TA_ADDRESS_IP::_AddrIp Address[1]
UCHAR Ttl
Definition: ip.h:43
struct IPv4_HEADER IPv4_HEADER
#define ICMP_TYPE_ECHO_REQUEST
Definition: icmp.h:22
#define PCHAR
Definition: match.c:90
#define Code
Definition: deflate.h:80
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:359
UINT Random(VOID)
Definition: routines.c:16
VOID ICMPTransmit(PIP_PACKET IPPacket, PIP_TRANSMIT_COMPLETE Complete, PVOID Context)
Definition: icmp.c:264
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ICMP_TYPE_ECHO_REPLY
Definition: icmp.h:18
UINT TotalSize
Definition: ip.h:86
IPv4_RAW_ADDRESS DstAddr
Definition: ip.h:47
UCHAR Code
Definition: icmp.h:12
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:2891
UCHAR Flags
Definition: ip.h:80
UCHAR Protocol
Definition: ip.h:44
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
NTSTATUS ICMPStartup()
Definition: icmp.c:15
UINT HeaderSize
Definition: ip.h:84
VOID RawIpReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
Definition: rawip.c:267
USHORT Checksum
Definition: ip.h:45
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define TDI_ADDRESS_TYPE_IP
Definition: tdi.h:345
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
IPv4_RAW_ADDRESS SrcAddr
Definition: ip.h:46
unsigned short USHORT
Definition: pedump.c:61
IP_ADDRESS Address
Definition: titypes.h:136
NTSTATUS ICMPShutdown()
Definition: icmp.c:22
unsigned int * PULONG
Definition: retypes.h:1
unsigned int UINT
Definition: ndis.h:50
PNDIS_PACKET NdisPacket
Definition: ip.h:88
struct ICMP_HEADER * PICMP_HEADER
Definition: ip.h:37
NTSTATUS ICMPSendDatagram(PADDRESS_FILE AddrFile, PTDI_CONNECTION_INFORMATION ConnInfo, PCHAR BufferData, ULONG DataSize, PULONG DataUsed)
Definition: icmp.c:118
BOOLEAN MappedHeader
Definition: ip.h:81
unsigned int ULONG
Definition: retypes.h:1
IP_ADDRESS DstAddr
Definition: ip.h:90
Definition: ip.h:77
BOOLEAN PrepareICMPPacket(PADDRESS_FILE AddrFile, PIP_INTERFACE Interface, PIP_PACKET IPPacket, PIP_ADDRESS Destination, PCHAR Data, UINT DataSize)
Definition: icmp.c:29
USHORT Id
Definition: ip.h:41
USHORT Checksum
Definition: icmp.h:13
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define STATUS_NETWORK_UNREACHABLE
Definition: ntstatus.h:690
struct IPv4_HEADER * PIPv4_HEADER
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
union IP_ADDRESS::@990 Address
VOID ICMPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
Definition: icmp.c:211
#define IPv4CorrectChecksum(Data, Count)
Definition: checksum.h:38
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR RemoteAddress
Definition: wsk.h:170
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR LocalAddress
Definition: wsk.h:170