ping.c
Go to the documentation of this file.
1 /**
2  * @file ping.c
3  * @brief Ping utility
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL PING_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/ping.h"
37 #include "core/ip.h"
38 #include "ipv4/ipv4.h"
39 #include "ipv4/ipv4_misc.h"
40 #include "ipv4/icmp.h"
41 #include "ipv6/ipv6.h"
42 #include "ipv6/ipv6_misc.h"
43 #include "ipv6/icmpv6.h"
44 #include "core/socket.h"
45 #include "debug.h"
46 
47 //Check TCP/IP stack configuration
48 #if (PING_SUPPORT == ENABLED && RAW_SOCKET_SUPPORT == ENABLED)
49 
50 //Sequence number field
51 static uint16_t pingSequenceNumber = 0;
52 
53 
54 /**
55  * @brief Test the reachability of a host
56  *
57  * Ping operates by sending an ICMP Echo Request message to the
58  * target host and waiting for an ICMP Echo Reply message
59  *
60  * @param[in] interface Underlying network interface (optional parameter)
61  * @param[in] targetIpAddr IP address of the host to reach
62  * @param[in] size Size of the data payload in bytes
63  * @param[in] ttl Time-To-Live value to be used
64  * @param[in] timeout Maximum time to wait before giving up
65  * @param[out] rtt Round-trip time (optional parameter)
66  * @return Error code
67  **/
68 
69 error_t ping(NetInterface *interface, const IpAddr *targetIpAddr, size_t size,
70  uint8_t ttl, systime_t timeout, systime_t *rtt)
71 {
72  error_t error;
73  PingContext context;
74 
75  //Check parameters
76  if(targetIpAddr == NULL)
78 
79  //Initialize context
80  pingInit(&context);
81 
82  //Start of exception handling block
83  do
84  {
85  //Select the specified network interface
86  error = pingBindToInterface(&context, interface);
87  //Any error to report?
88  if(error)
89  break;
90 
91  //Set timeout value
92  error = pingSetTimeout(&context, timeout);
93  //Any error to report?
94  if(error)
95  break;
96 
97  //Send an ICMP Echo Request message
98  error = pingSendRequest(&context, targetIpAddr, size, ttl);
99  //Any error to report?
100  if(error)
101  break;
102 
103  //Wait for a matching Echo Reply message
104  error = pingWaitForReply(&context, NULL, rtt);
105  //Any error to report?
106  if(error)
107  break;
108 
109  //End of exception handling block
110  } while(0);
111 
112  //Release resources
113  pingRelease(&context);
114 
115  //Return status code
116  return error;
117 }
118 
119 
120 /**
121  * @brief Initialize ping context
122  * @param[in] context Pointer to the ping context
123  **/
124 
125 void pingInit(PingContext *context)
126 {
127  //Make sure the context is valid
128  if(context != NULL)
129  {
130  //Initialize context
131  osMemset(context, 0, sizeof(PingContext));
132 
133  //Attach TCP/IP stack context
134  context->netContext = netGetDefaultContext();
135 
136  //Set the default timeout to be used
137  context->timeout = PING_DEFAULT_TIMEOUT;
138  }
139 }
140 
141 
142 /**
143  * @brief Set timeout value
144  * @param[in] context Pointer to the ping context
145  * @param[in] timeout Maximum time to wait
146  * @return Error code
147  **/
148 
150 {
151  //Invalid context?
152  if(context == NULL)
154 
155  //Save timeout value
156  context->timeout = timeout;
157 
158  //Successful processing
159  return NO_ERROR;
160 }
161 
162 
163 /**
164  * @brief Select a particular network interface
165  * @param[in] context Pointer to the ping context
166  * @param[in] interface Network interface to be used
167  * @return Error code
168  **/
169 
171 {
172  //Invalid context?
173  if(context == NULL)
175 
176  //Select the specified network interface
177  context->interface = interface;
178 
179  //Successful processing
180  return NO_ERROR;
181 }
182 
183 
184 /**
185  * @brief Send an ICMP Echo Request message
186  * @param[in] context Pointer to the ping context
187  * @param[in] targetIpAddr IP address of the host to reach
188  * @param[in] size Size of the data payload, in bytes
189  * @param[in] ttl Time-To-Live value to be used
190  * @return Error code
191  **/
192 
193 error_t pingSendRequest(PingContext *context, const IpAddr *targetIpAddr,
194  size_t size, uint8_t ttl)
195 {
196  error_t error;
197  size_t i;
198  size_t length;
199  NetInterface *interface;
201 
202  //Invalid context?
203  if(context == NULL)
205 
206  //Limit the size of the data payload
207  context->dataPayloadSize = MIN (size, PING_MAX_DATA_SIZE);
208 
209  //Close existing socket, if necessary
210  if(context->socket != NULL)
211  {
212  socketClose(context->socket);
213  context->socket = NULL;
214  }
215 
216  //Identifier field is used to help matching requests and replies
219 
220  //Sequence Number field is incremented each time an Echo Request is sent
221  context->sequenceNumber = pingSequenceNumber++;
222 
223  //Point to the buffer where to format the ICMP message
224  message = (IcmpEchoMessage *) context->buffer;
225 
226  //Format ICMP Echo Request message
228  message->code = 0;
229  message->checksum = 0;
230  message->identifier = htons(context->identifier);
231  message->sequenceNumber = htons(context->sequenceNumber);
232 
233  //Initialize data payload
234  for(i = 0; i < context->dataPayloadSize; i++)
235  {
236  message->data[i] = i & 0xFF;
237  }
238 
239  //Length of the complete ICMP message including header and data
240  length = sizeof(IcmpEchoMessage) + context->dataPayloadSize;
241 
242  //Select the relevant network interface
243  interface = context->interface;
244 
245 #if (IPV4_SUPPORT == ENABLED)
246  //Is target address an IPv4 address?
247  if(targetIpAddr->length == sizeof(Ipv4Addr))
248  {
250 
251  //Select the source IPv4 address and the relevant network interface to
252  //use when pinging the specified host
253  error = ipv4SelectSourceAddr(context->netContext, &interface,
254  targetIpAddr->ipv4Addr, &srcIpAddr);
255  //Any error to report?
256  if(error)
257  return error;
258 
259  //ICMP Echo Request message
261  //Message checksum calculation
262  message->checksum = ipCalcChecksum(message, length);
263 
264  //Open a raw socket
265  context->socket = socketOpenEx(context->netContext, SOCKET_TYPE_RAW_IP,
267  }
268  else
269 #endif
270 #if (IPV6_SUPPORT == ENABLED)
271  //Is target address an IPv6 address?
272  if(targetIpAddr->length == sizeof(Ipv6Addr))
273  {
274  Ipv6PseudoHeader pseudoHeader;
275 
276  //Select the source IPv6 address and the relevant network interface to
277  //use when pinging the specified host
278  error = ipv6SelectSourceAddr(context->netContext, &interface,
279  &targetIpAddr->ipv6Addr, &pseudoHeader.srcAddr);
280  //Any error to report?
281  if(error)
282  return error;
283 
284  //ICMPv6 Echo Request message
286 
287  //Format IPv6 pseudo header
288  pseudoHeader.destAddr = targetIpAddr->ipv6Addr;
289  pseudoHeader.length = htonl(length);
290  pseudoHeader.reserved[0] = 0;
291  pseudoHeader.reserved[1] = 0;
292  pseudoHeader.reserved[2] = 0;
293  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
294 
295  //Message checksum calculation
296  message->checksum = ipCalcUpperLayerChecksum(&pseudoHeader,
297  sizeof(Ipv6PseudoHeader), message, length);
298 
299  //Open a raw socket
300  context->socket = socketOpenEx(context->netContext, SOCKET_TYPE_RAW_IP,
302  }
303  else
304 #endif
305  //Invalid target address?
306  {
307  //Report an error
308  return ERROR_INVALID_ADDRESS;
309  }
310 
311  //Failed to open socket?
312  if(context->socket == NULL)
313  return ERROR_OPEN_FAILED;
314 
315  //Set the TTL value to be used
316  context->socket->ttl = ttl;
317 
318  //Start of exception handling block
319  do
320  {
321  //Associate the newly created socket with the relevant interface
322  error = socketBindToInterface(context->socket, interface);
323  //Unable to bind the socket to the desired interface?
324  if(error)
325  break;
326 
327  //Debug message
328  TRACE_INFO("Sending ICMP echo request to %s (%" PRIuSIZE " bytes)...\r\n",
329  ipAddrToString(targetIpAddr, NULL), length);
330 
331  //Send Echo Request message
332  error = socketSendTo(context->socket, targetIpAddr, 0, message, length,
333  NULL, 0);
334  //Failed to send message ?
335  if(error)
336  break;
337 
338  //Save the time at which the request was sent
339  context->timestamp = osGetSystemTime();
340 
341  //End of exception handling block
342  } while(0);
343 
344  //Any error to report?
345  if(error)
346  {
347  //Clean up side effects
348  socketClose(context->socket);
349  context->socket = NULL;
350  }
351 
352  //Return status code
353  return error;
354 }
355 
356 
357 /**
358  * @brief Check whether an incoming ICMP message is acceptable
359  * @param[in] context Pointer to the ping context
360  * @param[in] srcIpAddr Source IP address
361  * @param[in] destIpAddr Destination IP address
362  * @param[in] message Pointer to the incoming ICMP message
363  * @param[in] length Length of the message, in bytes
364  * @return Error code
365  **/
366 
368  const IpAddr *destIpAddr, const IcmpEchoMessage *message, size_t length)
369 {
370  size_t i;
371 
372  //Malformed ICMP message?
373  if(length < sizeof(IcmpHeader))
374  return ERROR_INVALID_MESSAGE;
375 
376 #if (IPV4_SUPPORT == ENABLED)
377  //Is target address an IPv4 address?
378  if(context->socket->protocol == SOCKET_IP_PROTO_ICMP)
379  {
380  //Check address type
381  if(destIpAddr->length != sizeof(Ipv4Addr))
382  return ERROR_INVALID_MESSAGE;
383 
384  //Check message type
385  if(message->type == ICMP_TYPE_ECHO_REPLY)
386  {
387  //Continue processing
388  }
389  else if(message->type == ICMP_TYPE_TIME_EXCEEDED)
390  {
391  //If the gateway processing a packet finds the TTL field is zero, then
392  //it notifies the source host via an ICMP Time Exceeded message
393  return ERROR_TTL_EXCEEDED;
394  }
395  else
396  {
397  //Report an error
398  return ERROR_INVALID_MESSAGE;
399  }
400 
401  //Verify checksum value
402  if(ipCalcChecksum(message, length) != 0x0000)
403  return ERROR_INVALID_MESSAGE;
404  }
405  else
406 #endif
407 #if (IPV6_SUPPORT == ENABLED)
408  //Is target address an IPv6 address?
409  if(context->socket->protocol == SOCKET_IP_PROTO_ICMPV6)
410  {
411  Ipv6PseudoHeader pseudoHeader;
412 
413  //Check address type
414  if(destIpAddr->length != sizeof(Ipv6Addr))
415  return ERROR_INVALID_MESSAGE;
416 
417  //Check message type
418  if(message->type == ICMPV6_TYPE_ECHO_REPLY)
419  {
420  //Continue processing
421  }
422  else if(message->type == ICMPV6_TYPE_TIME_EXCEEDED)
423  {
424  //If the gateway processing a packet finds the Hop Limit field is zero,
425  //then it notifies the source host via an ICMPv6 Time Exceeded message
426  return ERROR_TTL_EXCEEDED;
427  }
428  else
429  {
430  //Report an error
431  return ERROR_INVALID_MESSAGE;
432  }
433 
434  //Format IPv6 pseudo header
435  pseudoHeader.srcAddr = srcIpAddr->ipv6Addr;
436  pseudoHeader.destAddr = destIpAddr->ipv6Addr;
437  pseudoHeader.length = htonl(length);
438  pseudoHeader.reserved[0] = 0;
439  pseudoHeader.reserved[1] = 0;
440  pseudoHeader.reserved[2] = 0;
441  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
442 
443  //Verify checksum value
444  if(ipCalcUpperLayerChecksum(&pseudoHeader,
445  sizeof(Ipv6PseudoHeader), message, length) != 0x0000)
446  {
447  //The checksum is not valid
448  return ERROR_INVALID_MESSAGE;
449  }
450  }
451  else
452 #endif
453  //Invalid target address?
454  {
455  //Report an error
456  return ERROR_INVALID_ADDRESS;
457  }
458 
459  //Malformed ICMP Echo Reply message?
460  if(length < sizeof(IcmpEchoMessage))
461  return ERROR_INVALID_MESSAGE;
462 
463  //Make sure the response identifier matches the request identifier
464  if(ntohs(message->identifier) != context->identifier)
465  return ERROR_INVALID_MESSAGE;
466 
467  //Make sure the sequence number is correct
468  if(ntohs(message->sequenceNumber) != context->sequenceNumber)
469  return ERROR_INVALID_MESSAGE;
470 
471  //Check message length
472  if(length != (sizeof(IcmpEchoMessage) + context->dataPayloadSize))
473  return ERROR_INVALID_MESSAGE;
474 
475  //Verify data payload
476  for(i = 0; i < context->dataPayloadSize; i++)
477  {
478  //Compare received data against expected data pattern
479  if(message->data[i] != (i & 0xFF))
480  return ERROR_INVALID_MESSAGE;
481  }
482 
483  //The ICMP Echo Reply message is acceptable
484  return NO_ERROR;
485 }
486 
487 
488 /**
489  * @brief Wait for a matching ICMP Echo Reply message
490  * @param[in] context Pointer to the ping context
491  * @param[out] hostIpAddr IP address of the intermediate host (optional parameter)
492  * @param[out] rtt Round-trip time (optional parameter)
493  * @return Error code
494  **/
495 
497  systime_t *rtt)
498 {
499  error_t error;
500  size_t length;
501  systime_t time;
502  systime_t timeout;
505 
506  //Invalid context?
507  if(context == NULL)
509 
510  //Wait for an ICMP Echo Reply message
511  do
512  {
513  //Get current time
514  time = osGetSystemTime();
515 
516  //Compute the timeout to be used
517  if(timeCompare(time, context->timestamp + context->timeout) < 0)
518  {
519  timeout = context->timestamp + context->timeout - time;
520  }
521  else
522  {
523  timeout = 0;
524  }
525 
526  //Adjust receive timeout
527  error = socketSetTimeout(context->socket, timeout);
528  //Any error to report?
529  if(error)
530  break;
531 
532  //Wait for an incoming ICMP message
533  error = socketReceiveEx(context->socket, &srcIpAddr, NULL, &destIpAddr,
534  context->buffer, PING_BUFFER_SIZE, &length, 0);
535 
536 #if (NET_RTOS_SUPPORT == DISABLED)
537  //Catch timeout exception
538  if(error == ERROR_TIMEOUT)
539  {
540  error = ERROR_WOULD_BLOCK;
541  }
542 #endif
543 
544  //Get current time
545  time = osGetSystemTime();
546 
547  //Check status code
548  if(!error)
549  {
550  //Check whether the incoming ICMP message is acceptable
551  error = pingCheckReply(context, &srcIpAddr, &destIpAddr,
552  (IcmpEchoMessage *) context->buffer, length);
553  }
554 
555  //Check status code
556  if(error == NO_ERROR || error == ERROR_TTL_EXCEEDED)
557  {
558  //Calculate round-trip time
559  context->rtt = time - context->timestamp;
560 
561  //Debug message
562  if(error == NO_ERROR)
563  {
564  TRACE_INFO("ICMP echo reply received from %s (%" PRIu32 " ms)...\r\n",
565  ipAddrToString(&srcIpAddr, NULL), context->rtt);
566  }
567  else
568  {
569  TRACE_INFO("ICMP time exceeded received from %s (%" PRIu32 " ms)...\r\n",
570  ipAddrToString(&srcIpAddr, NULL), context->rtt);
571  }
572 
573  //Return the IP address of the host
574  if(hostIpAddr != NULL)
575  {
576  *hostIpAddr = srcIpAddr;
577  }
578 
579  //Return the round-trip time
580  if(rtt != NULL)
581  {
582  *rtt = context->rtt;
583  }
584  }
585  else
586  {
587  //Timeout value exceeded?
588  if(timeCompare(time, context->timestamp + context->timeout) >= 0)
589  {
590  //Report an error
591  error = ERROR_TIMEOUT;
592  }
593  }
594 
595  //Wait for the next incoming ICMP message
596  } while(error == ERROR_INVALID_MESSAGE);
597 
598  //Return status code
599  return error;
600 }
601 
602 
603 /**
604  * @brief Release ping context
605  * @param[in] context Pointer to the ping context
606  **/
607 
608 void pingRelease(PingContext *context)
609 {
610  //Make sure the context is valid
611  if(context != NULL)
612  {
613  //Close underlying socket
614  if(context->socket != NULL)
615  {
616  socketClose(context->socket);
617  context->socket = NULL;
618  }
619  }
620 }
621 
622 #endif
#define htons(value)
Definition: cpu_endian.h:413
#define PING_MAX_DATA_SIZE
Definition: ping.h:55
IPv6 (Internet Protocol Version 6)
error_t pingCheckReply(PingContext *context, const IpAddr *srcIpAddr, const IpAddr *destIpAddr, const IcmpEchoMessage *message, size_t length)
Check whether an incoming ICMP message is acceptable.
Definition: ping.c:367
void pingRelease(PingContext *context)
Release ping context.
Definition: ping.c:608
@ ERROR_WOULD_BLOCK
Definition: error.h:96
IP network address.
Definition: ip.h:90
systime_t timeout
Definition: ping.h:82
uint32_t netGetRandRange(NetContext *context, uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net.c:473
uint8_t message[]
Definition: chap.h:154
@ SOCKET_IP_PROTO_ICMPV6
Definition: socket.h:109
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:2094
error_t pingWaitForReply(PingContext *context, IpAddr *hostIpAddr, systime_t *rtt)
Wait for a matching ICMP Echo Reply message.
Definition: ping.c:496
#define PING_DEFAULT_TIMEOUT
Definition: ping.h:48
error_t pingBindToInterface(PingContext *context, NetInterface *interface)
Select a particular network interface.
Definition: ping.c:170
#define ICMP_QUERY_ID_MAX
Definition: icmp.h:57
char_t * ipAddrToString(const IpAddr *ipAddr, char_t *str)
Convert a binary IP address to a string representation.
Definition: ip.c:810
Ipv6Addr
Definition: ipv6.h:280
#define PING_BUFFER_SIZE
Definition: ping.h:61
@ ICMP_TYPE_TIME_EXCEEDED
Definition: icmp.h:93
NetContext * netContext
TCP/IP stack context.
Definition: ping.h:75
@ IPV6_ICMPV6_HEADER
Definition: ipv6.h:213
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
Ipv4Addr srcIpAddr
Definition: ipcp.h:79
#define IPV4_SUPPORT
Definition: ipv4.h:48
Socket * socket
Raw socket.
Definition: ping.h:77
#define timeCompare(t1, t2)
Definition: os_port.h:40
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:322
Ping context.
Definition: ping.h:74
systime_t timestamp
Definition: ping.h:81
@ ICMPV6_TYPE_ECHO_REQUEST
Definition: icmpv6.h:75
IcmpHeader
Definition: icmp.h:149
@ ERROR_OPEN_FAILED
Definition: error.h:75
@ ICMPV6_TYPE_ECHO_REPLY
Definition: icmpv6.h:76
error_t pingSendRequest(PingContext *context, const IpAddr *targetIpAddr, size_t size, uint8_t ttl)
Send an ICMP Echo Request message.
Definition: ping.c:193
Helper functions for IPv4.
ICMPv6 (Internet Control Message Protocol Version 6)
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define htonl(value)
Definition: cpu_endian.h:414
ICMP (Internet Control Message Protocol)
Ping utility.
error_t
Error codes.
Definition: error.h:43
uint16_t sequenceNumber
Definition: ping.h:80
#define Ipv6PseudoHeader
Definition: ipv6.h:42
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
error_t ipv4SelectSourceAddr(NetContext *context, NetInterface **interface, Ipv4Addr destAddr, Ipv4Addr *srcAddr)
IPv4 source address selection.
Definition: ipv4_misc.c:173
#define NetInterface
Definition: net.h:40
Helper functions for IPv6.
NetContext * netGetDefaultContext(void)
Get default TCP/IP stack context.
Definition: net.c:527
IcmpEchoMessage
Definition: icmp.h:179
@ SOCKET_TYPE_RAW_IP
Definition: socket.h:94
error_t ping(NetInterface *interface, const IpAddr *targetIpAddr, size_t size, uint8_t ttl, systime_t timeout, systime_t *rtt)
Test the reachability of a host.
Definition: ping.c:69
@ ICMP_TYPE_ECHO_REQUEST
Definition: icmp.h:90
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
#define MIN(a, b)
Definition: os_port.h:63
size_t length
Definition: ip.h:91
#define ICMP_QUERY_ID_MIN
Definition: icmp.h:50
#define ENABLED
Definition: os_port.h:37
#define socketBindToInterface
Definition: net_legacy.h:193
uint8_t buffer[PING_BUFFER_SIZE]
Definition: ping.h:84
@ ERROR_TTL_EXCEEDED
Definition: error.h:314
uint32_t systime_t
System time.
#define ntohs(value)
Definition: cpu_endian.h:421
uint16_t ipCalcUpperLayerChecksum(const void *pseudoHeader, size_t pseudoHeaderLen, const void *data, size_t dataLen)
Calculate IP upper-layer checksum.
Definition: ip.c:664
@ ERROR_TIMEOUT
Definition: error.h:95
Ipv4Addr ipv4Addr
Definition: ip.h:95
uint32_t time
IPv4 and IPv6 common routines.
@ ICMP_TYPE_ECHO_REPLY
Definition: icmp.h:85
error_t pingSetTimeout(PingContext *context, systime_t timeout)
Set timeout value.
Definition: ping.c:149
@ SOCKET_IP_PROTO_ICMP
Definition: socket.h:105
Socket * socketOpenEx(NetContext *context, uint_t type, uint_t protocol)
Create a socket.
Definition: socket.c:146
Socket API.
error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length, size_t *written, uint_t flags)
Send a datagram to a specific destination.
Definition: socket.c:1535
NetInterface * interface
Underlying network interface.
Definition: ping.h:76
error_t socketReceiveEx(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
Receive a datagram.
Definition: socket.c:1768
IPv4 (Internet Protocol Version 4)
uint32_t ttl
Definition: dns_common.h:224
Ipv6Addr ipv6Addr
Definition: ip.h:98
#define PRIuSIZE
systime_t rtt
Definition: ping.h:83
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
void pingInit(PingContext *context)
Initialize ping context.
Definition: ping.c:125
uint16_t identifier
Definition: ping.h:79
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:169
error_t ipv6SelectSourceAddr(NetContext *context, NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:891
@ NO_ERROR
Success.
Definition: error.h:44
@ ICMPV6_TYPE_TIME_EXCEEDED
Definition: icmpv6.h:73
Debugging facilities.
size_t dataPayloadSize
Definition: ping.h:78
uint16_t ipCalcChecksum(const void *data, size_t length)
IP checksum calculation.
Definition: ip.c:471
systime_t osGetSystemTime(void)
Retrieve system time.
Ipv4Addr destIpAddr
Definition: ipcp.h:80