ReactOS 0.4.15-dev-7924-g5949c20
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
16{
17 HANDLE IcmpFile;
22
27 NULL,
28 NULL);
29
31 &IcmpFile,
35 NULL,
39 0,
40 NULL,
41 0);
42
43 if (!NT_SUCCESS(Status))
44 {
47 }
48
49 return IcmpFile;
50}
51
56 _In_ DWORD ReplySize)
57{
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
78 _In_ HANDLE IcmpHandle,
84 _In_ LPVOID RequestData,
88 _In_ DWORD ReplySize,
90{
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 {
141 }
142
143 if (Event == NULL && ApcRoutine == NULL)
144 {
146 }
147 else
148 {
149 hEvent = Event;
150 }
151
153 IcmpHandle,
154 hEvent,
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
200BOOL
201WINAPI
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
217HANDLE
218WINAPI
220{
221 HANDLE IcmpFile;
226
229 &DeviceName,
231 NULL,
232 NULL);
233
235 &IcmpFile,
239 NULL,
243 0,
244 NULL,
245 0);
246
247 if (!NT_SUCCESS(Status))
248 {
251 }
252
253 return IcmpFile;
254}
255
256DWORD
257WINAPI
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
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
283DWORD
284WINAPI
286 _In_ HANDLE IcmpHandle,
291 _In_ LPVOID RequestData,
295 _In_ DWORD ReplySize,
297{
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
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,
377 ReplySize,
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
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
421DWORD
422WINAPI
424 _In_ HANDLE IcmpHandle,
426 _In_ LPVOID RequestData,
430 _In_ DWORD ReplySize,
432{
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
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,
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
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 WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
LONG NTSTATUS
Definition: precomp.h:26
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
BOOL WINAPI IcmpCloseHandle(_In_ HANDLE IcmpHandle)
Definition: icmp.c:202
DWORD WINAPI IcmpParseReplies(_In_ LPVOID ReplyBuffer, _In_ DWORD ReplySize)
Definition: icmp.c:258
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
HANDLE WINAPI Icmp6CreateFile(void)
Definition: icmp.c:15
DWORD WINAPI Icmp6ParseReplies(_In_ LPVOID ReplyBuffer, _In_ DWORD ReplySize)
Definition: icmp.c:54
HANDLE WINAPI IcmpCreateFile(void)
Definition: icmp.c:219
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
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 _IO_STATUS_BLOCK IO_STATUS_BLOCK
struct _IO_STATUS_BLOCK * PIO_STATUS_BLOCK
Definition: change.c:34
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
_Must_inspect_result_ _In_ PFLT_PORT _In_ ULONG _Out_writes_bytes_opt_ ReplyLength PVOID ReplyBuffer
Definition: fltkernel.h:1902
#define FILE_OPEN_IF
Definition: from_kernel.h:56
Status
Definition: gdiplustypes.h:25
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
struct icmp_echo_request * PICMP_ECHO_REQUEST
#define IP_BUF_TOO_SMALL
Definition: ipexport.h:114
struct icmp_echo_request ICMP_ECHO_REQUEST
struct icmp_echo_reply * PICMP_ECHO_REPLY
struct _ICMPV6_ECHO_REQUEST ICMPV6_ECHO_REQUEST
#define IP_GENERAL_FAILURE
Definition: ipexport.h:138
struct _ICMPV6_ECHO_REQUEST * PICMPV6_ECHO_REQUEST
#define IP_SUCCESS
Definition: ipexport.h:113
ICMPV6_ECHO_REPLY_LH * PICMPV6_ECHO_REPLY
Definition: ipexport.h:195
static HANDLE hEvent
Definition: comm.c:54
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID ApcContext
Definition: iofuncs.h:727
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE ApcRoutine
Definition: iofuncs.h:726
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
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)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)
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)
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:877
#define GENERIC_EXECUTE
Definition: nt_native.h:91
#define STATUS_PENDING
Definition: ntstatus.h:82
#define L(x)
Definition: ntvdm.h:50
BYTE * PBYTE
Definition: pedump.c:66
ULONG IPAddr
Definition: pfhook.h:35
static ULONG Timeout
Definition: ping.c:61
static ULONG RequestSize
Definition: ping.c:63
UINT32 Status
Definition: ipexport.h:85
UINT16 Reserved
Definition: ipexport.h:88
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
#define IOCTL_ICMP_ECHO_REQUEST
Definition: tcpioctl.h:49
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
Definition: wdfio.h:322
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS RequestOptions
Definition: wdfiotarget.h:867
#define CopyMemory
Definition: winbase.h:1710
#define WINAPI
Definition: msvc.h:6
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Out_ PPHYSICAL_ADDRESS DestinationAddress
Definition: iotypes.h:1128
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS SourceAddress
Definition: iotypes.h:1127