ReactOS  0.4.15-dev-509-g96a357b
icmp.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS IP Helper API
3  * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE: ICMP functions
5  * COPYRIGHT: 2016 Tim Crawford (crawfxrd@gmail.com)
6  * 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
7  */
8 
9 #include "iphlpapi_private.h"
10 
12 
13 HANDLE
14 WINAPI
16 {
17  HANDLE IcmpFile;
22 
25  &DeviceName,
27  NULL,
28  NULL);
29 
31  &IcmpFile,
35  NULL,
39  0,
40  NULL,
41  0);
42 
43  if (!NT_SUCCESS(Status))
44  {
46  return INVALID_HANDLE_VALUE;
47  }
48 
49  return IcmpFile;
50 }
51 
52 DWORD
53 WINAPI
56  _In_ DWORD ReplySize)
57 {
58  PICMPV6_ECHO_REPLY pEcho;
59 
60  if (ReplyBuffer == NULL || ReplySize == 0)
61  return 0;
62 
64 
65  // XXX: MSDN also says IP_TTL_EXPIRED_TRANSIT.
66  if (pEcho->Status == IP_SUCCESS)
67  {
68  return 1;
69  }
70 
71  SetLastError(pEcho->Status);
72  return 0;
73 }
74 
75 DWORD
76 WINAPI
78  _In_ HANDLE IcmpHandle,
84  _In_ LPVOID RequestData,
86  _In_ PIP_OPTION_INFORMATION RequestOptions,
88  _In_ DWORD ReplySize,
90 {
91  HANDLE hEvent;
95  //ULONG OutputBufferLength;
98 
100 
101  if (ReplySize < sizeof(ICMPV6_ECHO_REPLY) + sizeof(IO_STATUS_BLOCK))
102  {
104  return 0;
105  }
106 
107  // IO_STATUS_BLOCK will be stored inside ReplyBuffer (in the end)
108  // that's because the function may return before device request ends
110  ReplySize -= sizeof(IO_STATUS_BLOCK);
111 
113  if (InputBuffer == NULL)
114  {
116  return 0;
117  }
118 
120 
121  Request->DestinationAddress.sin6_port = DestinationAddress->sin6_port;
122  Request->DestinationAddress.sin6_flowinfo = DestinationAddress->sin6_flowinfo;
123  CopyMemory(&(Request->DestinationAddress.sin6_addr), &(DestinationAddress->sin6_addr), sizeof(Request->DestinationAddress.sin6_addr));
124  Request->DestinationAddress.sin6_scope_id = DestinationAddress->sin6_scope_id;
125 
126  Request->SourceAddress.sin6_port = SourceAddress->sin6_port;
127  Request->SourceAddress.sin6_flowinfo = SourceAddress->sin6_flowinfo;
128  CopyMemory(&(Request->SourceAddress.sin6_addr), &(SourceAddress->sin6_addr), sizeof(Request->SourceAddress.sin6_addr));
129  Request->SourceAddress.sin6_scope_id = SourceAddress->sin6_scope_id;
130 
131  // XXX: What is this and why is it sometimes 0x72?
132  Request->Unknown1 = 0x72;
133 
134  Request->Timeout = Timeout;
135  Request->Ttl = RequestOptions->Ttl;
136  Request->Flags = RequestOptions->Flags;
137 
138  if (RequestSize > 0)
139  {
140  CopyMemory((PBYTE)InputBuffer + sizeof(ICMPV6_ECHO_REQUEST), RequestData, RequestSize);
141  }
142 
143  if (Event == NULL && ApcRoutine == NULL)
144  {
146  }
147  else
148  {
149  hEvent = Event;
150  }
151 
153  IcmpHandle,
154  hEvent,
155  ApcRoutine,
156  ApcContext,
159  InputBuffer,
161  ReplyBuffer,
162  ReplySize); // TODO: Determine how Windows calculates OutputBufferLength.
163 
164  if (Event != NULL || ApcRoutine != NULL)
165  {
168  return 0;
169  }
170 
171  if (Status == STATUS_PENDING)
172  {
174 
175  if (NT_SUCCESS(Status))
176  {
178  }
179  }
180 
183 
184  if (!NT_SUCCESS(Status))
185  {
187  return 0;
188  }
189 
191  if (Status != IP_SUCCESS)
192  {
194  return 0;
195  }
196 
197  return 1;
198 }
199 
200 BOOL
201 WINAPI
203  _In_ HANDLE IcmpHandle)
204 {
206 
207  Status = NtClose(IcmpHandle);
208  if (!NT_SUCCESS(Status))
209  {
211  return FALSE;
212  }
213 
214  return TRUE;
215 }
216 
217 HANDLE
218 WINAPI
220 {
221  HANDLE IcmpFile;
226 
229  &DeviceName,
231  NULL,
232  NULL);
233 
235  &IcmpFile,
238  &IoStatusBlock,
239  NULL,
242  FILE_OPEN_IF,
243  0,
244  NULL,
245  0);
246 
247  if (!NT_SUCCESS(Status))
248  {
250  return INVALID_HANDLE_VALUE;
251  }
252 
253  return IcmpFile;
254 }
255 
256 DWORD
257 WINAPI
260  _In_ DWORD ReplySize)
261 {
262  PICMP_ECHO_REPLY pEcho;
263  DWORD nReplies;
264 
265  if (ReplyBuffer == NULL || ReplySize == 0)
266  return 0;
267 
268  // TODO: Handle ReplyBuffer having more than 1 ICMP_ECHO_REPLY.
269 
270  pEcho = (PICMP_ECHO_REPLY)ReplyBuffer;
271 
272  if (pEcho->Reserved == 0)
273  {
274  SetLastError(pEcho->Status);
275  }
276 
277  nReplies = pEcho->Reserved;
278  pEcho->Reserved = 0;
279 
280  return nReplies;
281 }
282 
283 DWORD
284 WINAPI
286  _In_ HANDLE IcmpHandle,
291  _In_ LPVOID RequestData,
293  _In_opt_ PIP_OPTION_INFORMATION RequestOptions,
295  _In_ DWORD ReplySize,
297 {
298  HANDLE hEvent;
302  DWORD nReplies;
304 
305  if (ReplySize < sizeof(ICMP_ECHO_REPLY) + sizeof(IO_STATUS_BLOCK))
306  {
308  return 0;
309  }
310 
311  if (ReplySize < RequestSize + sizeof(ICMP_ECHO_REPLY))
312  {
314  return 0;
315  }
316 
317  // IO_STATUS_BLOCK will be stored inside ReplyBuffer (in the end)
318  // that's because the function may return before device request ends
320  ReplySize -= sizeof(IO_STATUS_BLOCK);
321 
323  if (InputBuffer == NULL)
324  {
326  return 0;
327  }
328 
330  Request->Address = DestinationAddress;
331  Request->Timeout = Timeout;
332  Request->OptionsOffset = sizeof(ICMP_ECHO_REQUEST);
333  Request->DataOffset = sizeof(ICMP_ECHO_REQUEST);
334 
335  if (RequestOptions != NULL)
336  {
337  Request->HasOptions = TRUE;
338  Request->Ttl = RequestOptions->Ttl;
339  Request->Tos = RequestOptions->Tos;
340  Request->Flags = RequestOptions->Flags;
341 
342  if (RequestOptions->OptionsSize > 0)
343  {
344  Request->OptionsSize = RequestOptions->OptionsSize;
345  Request->DataOffset += Request->OptionsSize;
346 
347  CopyMemory(
349  RequestOptions->OptionsData,
350  Request->OptionsSize);
351  }
352  }
353 
354  if (RequestSize > 0)
355  {
356  Request->DataSize = RequestSize;
357  CopyMemory((PUCHAR)InputBuffer + Request->DataOffset, RequestData, RequestSize);
358  }
359 
360  if (Event == NULL && ApcRoutine == NULL)
361  {
363  }
364  else
365  {
366  hEvent = Event;
367  }
368 
370  IcmpHandle,
371  hEvent,
372  ApcRoutine,
373  ApcContext,
376  InputBuffer,
377  ReplySize,
378  ReplyBuffer,
379  ReplySize); // TODO: Determine how Windows calculates OutputBufferLength.
380 
381  // If called asynchronously, return for the caller to handle.
382  if (Event != NULL || ApcRoutine != NULL)
383  {
386  return 0;
387  }
388 
389  // Otherwise handle it like IcmpSendEcho.
390  if (Status == STATUS_PENDING)
391  {
393 
394  if (NT_SUCCESS(Status))
395  {
397  }
398  }
399 
402 
403  if (!NT_SUCCESS(Status))
404  {
406  return 0;
407  }
408 
409  Status = ((PICMP_ECHO_REPLY)ReplyBuffer)->Status;
410  if (Status != IP_SUCCESS)
411  {
413  }
414 
415  nReplies = ((PICMP_ECHO_REPLY)ReplyBuffer)->Reserved;
416  ((PICMP_ECHO_REPLY)ReplyBuffer)->Reserved = 0;
417 
418  return nReplies;
419 }
420 
421 DWORD
422 WINAPI
424  _In_ HANDLE IcmpHandle,
426  _In_ LPVOID RequestData,
428  _In_opt_ PIP_OPTION_INFORMATION RequestOptions,
430  _In_ DWORD ReplySize,
432 {
433  HANDLE hEvent;
438  DWORD nReplies;
440 
441  if (Timeout == 0 || Timeout == (DWORD)-1)
442  {
444  return 0;
445  }
446 
447  if (ReplySize < sizeof(ICMP_ECHO_REPLY))
448  {
450  return 0;
451  }
452 
453  if (ReplySize < RequestSize + sizeof(ICMP_ECHO_REPLY))
454  {
456  return 0;
457  }
458 
460  if (RequestOptions != NULL)
461  InputBufferLength += RequestOptions->OptionsSize;
462 
463  if (InputBufferLength < ReplySize)
464  InputBufferLength = ReplySize;
465 
467  if (InputBuffer == NULL)
468  {
470  return 0;
471  }
472 
474  Request->Address = DestinationAddress;
475  Request->Timeout = Timeout;
476  Request->OptionsOffset = sizeof(ICMP_ECHO_REQUEST);
477  Request->DataOffset = sizeof(ICMP_ECHO_REQUEST);
478 
479  if (RequestOptions != NULL)
480  {
481  Request->HasOptions = TRUE;
482  Request->Ttl = RequestOptions->Ttl;
483  Request->Tos = RequestOptions->Tos;
484  Request->Flags = RequestOptions->Flags;
485 
486  if (RequestOptions->OptionsSize > 0)
487  {
488  Request->OptionsSize = RequestOptions->OptionsSize;
489  Request->DataOffset += Request->OptionsSize;
490 
491  CopyMemory(
493  RequestOptions->OptionsData,
494  Request->OptionsSize);
495  }
496  }
497 
498  if (RequestSize > 0)
499  {
500  Request->DataSize = RequestSize;
501  CopyMemory((PUCHAR)InputBuffer + Request->DataOffset, RequestData, RequestSize);
502  }
503 
505  if (hEvent == NULL)
506  {
508  return 0;
509  }
510 
512  IcmpHandle,
513  hEvent,
514  NULL,
515  NULL,
516  &IoStatusBlock,
518  InputBuffer,
520  ReplyBuffer,
521  ReplySize);
522 
523  if (Status == STATUS_PENDING)
524  {
526 
527  if (NT_SUCCESS(Status))
528  {
530  }
531  }
532 
535 
536  if (!NT_SUCCESS(Status))
537  {
539  return 0;
540  }
541 
542  Status = ((PICMP_ECHO_REPLY)ReplyBuffer)->Status;
543  if (Status != IP_SUCCESS)
544  {
546  }
547 
548  nReplies = ((PICMP_ECHO_REPLY)ReplyBuffer)->Reserved;
549  ((PICMP_ECHO_REPLY)ReplyBuffer)->Reserved = 0;
550 
551  return nReplies;
552 }
#define IP_BUF_TOO_SMALL
Definition: ipexport.h:114
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID ApcContext
Definition: iofuncs.h:719
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:407
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:877
BOOL WINAPI IcmpCloseHandle(_In_ HANDLE IcmpHandle)
Definition: icmp.c:202
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define IOCTL_ICMP_ECHO_REQUEST
Definition: tcpioctl.h:49
struct icmp_echo_request ICMP_ECHO_REQUEST
struct icmp_echo_reply * PICMP_ECHO_REPLY
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:400
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
WCHAR DeviceName[]
Definition: adapter.cpp:21
CHAR InputBuffer[80]
Definition: conmgr.c:33
#define FILE_SHARE_READ
Definition: compat.h:125
#define _In_opt_
Definition: no_sal2.h:213
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
static HANDLE hEvent
Definition: comm.c:54
_In_ NDIS_HANDLE _In_ PNDIS_REQUEST Request
Definition: ndis.h:5173
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
unsigned int BOOL
Definition: ntddk_ex.h:94
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:437
smooth NULL
Definition: ftsmooth.c:416
#define _Out_
Definition: no_sal2.h:323
ULONG IPAddr
Definition: pfhook.h:35
UINT16 Reserved
Definition: ipexport.h:88
struct _ICMPV6_ECHO_REQUEST * PICMPV6_ECHO_REQUEST
#define IP_GENERAL_FAILURE
Definition: ipexport.h:138
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi)
#define GetProcessHeap()
Definition: compat.h:404
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
ICMPV6_ECHO_REPLY_LH * PICMPV6_ECHO_REPLY
Definition: ipexport.h:195
DWORD WINAPI Icmp6SendEcho2(_In_ HANDLE IcmpHandle, _In_opt_ HANDLE Event, _In_opt_ PIO_APC_ROUTINE ApcRoutine, _In_opt_ PVOID ApcContext, _In_ struct sockaddr_in6 *SourceAddress, _In_ struct sockaddr_in6 *DestinationAddress, _In_ LPVOID RequestData, _In_ WORD RequestSize, _In_ PIP_OPTION_INFORMATION RequestOptions, _Out_ LPVOID ReplyBuffer, _In_ DWORD ReplySize, _In_ DWORD Timeout)
Definition: icmp.c:77
struct icmp_echo_request * PICMP_ECHO_REQUEST
DWORD WINAPI Icmp6ParseReplies(_In_ LPVOID ReplyBuffer, _In_ DWORD ReplySize)
Definition: icmp.c:54
#define WINAPI
Definition: msvc.h:6
#define CopyMemory
Definition: winbase.h:1646
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:418
struct _IO_STATUS_BLOCK * PIO_STATUS_BLOCK
Definition: change.c:34
struct _ICMPV6_ECHO_REQUEST ICMPV6_ECHO_REQUEST
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE ApcRoutine
Definition: iofuncs.h:719
DWORD WINAPI IcmpSendEcho2(_In_ HANDLE IcmpHandle, _In_opt_ HANDLE Event, _In_opt_ PIO_APC_ROUTINE ApcRoutine, _In_opt_ PVOID ApcContext, _In_ IPAddr DestinationAddress, _In_ LPVOID RequestData, _In_ WORD RequestSize, _In_opt_ PIP_OPTION_INFORMATION RequestOptions, _Out_ LPVOID ReplyBuffer, _In_ DWORD ReplySize, _In_ DWORD Timeout)
Definition: icmp.c:285
_Must_inspect_result_ _In_ PFLT_PORT _In_ ULONG _Out_writes_bytes_opt_ ReplyLength PVOID ReplyBuffer
Definition: fltkernel.h:1903
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
static const WCHAR L[]
Definition: oid.c:1250
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG InputBufferLength
Definition: fltkernel.h:1372
Status
Definition: gdiplustypes.h:24
#define _In_
Definition: no_sal2.h:204
static ULONG Timeout
Definition: ping.c:61
HANDLE WINAPI Icmp6CreateFile(void)
Definition: icmp.c:15
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
UINT32 Status
Definition: ipexport.h:85
#define IP_SUCCESS
Definition: ipexport.h:113
unsigned int ULONG
Definition: retypes.h:1
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
DWORD WINAPI IcmpParseReplies(_In_ LPVOID ReplyBuffer, _In_ DWORD ReplySize)
Definition: icmp.c:258
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Out_ PPHYSICAL_ADDRESS DestinationAddress
Definition: iotypes.h:1092
#define GENERIC_EXECUTE
Definition: nt_native.h:91
HANDLE WINAPI IcmpCreateFile(void)
Definition: icmp.c:219
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS SourceAddress
Definition: iotypes.h:1092
BYTE * PBYTE
Definition: pedump.c:66
struct _IO_STATUS_BLOCK IO_STATUS_BLOCK
#define HeapFree(x, y, z)
Definition: compat.h:403
DWORD WINAPI IcmpSendEcho(_In_ HANDLE IcmpHandle, _In_ IPAddr DestinationAddress, _In_ LPVOID RequestData, _In_ WORD RequestSize, _In_opt_ PIP_OPTION_INFORMATION RequestOptions, _Out_ LPVOID ReplyBuffer, _In_ DWORD ReplySize, _In_ DWORD Timeout)
Definition: icmp.c:423
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)