icmpv6.c
Go to the documentation of this file.
1 /**
2  * @file icmpv6.c
3  * @brief ICMPv6 (Internet Control Message Protocol Version 6)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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  * @section Description
28  *
29  * ICMPv6 is used by IPv6 nodes to report errors encountered in
30  * processing packets, and to perform other Internet-layer functions.
31  * ICMPv6 is an integral part of IPv6 and must be fully implemented
32  * by every IPv6 node. Refer to the RFC 2463 for more details
33  *
34  * @author Oryx Embedded SARL (www.oryx-embedded.com)
35  * @version 2.5.0
36  **/
37 
38 //Switch to the appropriate trace level
39 #define TRACE_LEVEL ICMPV6_TRACE_LEVEL
40 
41 //Dependencies
42 #include "core/net.h"
43 #include "core/ip.h"
44 #include "ipv6/ipv6.h"
45 #include "ipv6/ipv6_pmtu.h"
46 #include "ipv6/ipv6_misc.h"
47 #include "ipv6/icmpv6.h"
48 #include "ipv6/ndp.h"
50 #include "mld/mld_node_misc.h"
51 #include "mibs/ip_mib_module.h"
52 #include "debug.h"
53 
54 //Check TCP/IP stack configuration
55 #if (IPV6_SUPPORT == ENABLED)
56 
57 
58 /**
59  * @brief Enable support for ICMPv6 Echo Request messages
60  * @param[in] interface Underlying network interface
61  * @param[in] enable This flag specifies whether the host will respond to
62  * ICMPv6 Echo Requests. When the flag is set to FALSE, incoming ICMPv6 Echo
63  * Request messages will be dropped
64  * @return Error code
65  **/
66 
68 {
69  //Check parameters
70  if(interface == NULL)
72 
73  //Get exclusive access
75  //Enable or disable support for Echo Request messages
76  interface->ipv6Context.enableEchoReq = enable;
77  //Release exclusive access
79 
80  //Successful processing
81  return NO_ERROR;
82 }
83 
84 
85 /**
86  * @brief Enable support for multicast ICMPv6 Echo Request messages
87  * @param[in] interface Underlying network interface
88  * @param[in] enable This flag specifies whether the host will respond to
89  * multicast ICMPv6 Echo Requests. When the flag is set to FALSE, incoming
90  * ICMPv6 Echo Request messages destined to a multicast address will be
91  * dropped
92  * @return Error code
93  **/
94 
96  bool_t enable)
97 {
98  //Check parameters
99  if(interface == NULL)
101 
102  //Get exclusive access
104  //Enable or disable support for multicast Echo Request messages
105  interface->ipv6Context.enableMulticastEchoReq = enable;
106  //Release exclusive access
108 
109  //Successful processing
110  return NO_ERROR;
111 }
112 
113 
114 /**
115  * @brief Incoming ICMPv6 message processing
116  * @param[in] interface Underlying network interface
117  * @param[in] pseudoHeader IPv6 pseudo header
118  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
119  * @param[in] offset Offset to the first byte of the ICMPv6 message
120  * @param[in] ancillary Additional options passed to the stack along with
121  * the packet
122  **/
123 
125  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
126  size_t offset, const NetRxAncillary *ancillary)
127 {
128  size_t length;
129  Icmpv6Header *header;
130 
131  //Total number of ICMP messages which the entity received
132  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsInMsgs, 1);
133 
134  //Retrieve the length of the ICMPv6 message
135  length = netBufferGetLength(buffer) - offset;
136 
137  //Ensure the message length is correct
138  if(length < sizeof(Icmpv6Header))
139  {
140  //Number of ICMP messages which the entity received but determined
141  //as having ICMP-specific errors
142  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsInErrors, 1);
143 
144  //Silently discard incoming message
145  return;
146  }
147 
148  //Point to the ICMPv6 message header
149  header = netBufferAt(buffer, offset, 0);
150 
151  //Sanity check
152  if(header == NULL)
153  return;
154 
155  //Debug message
156  TRACE_INFO("ICMPv6 message received (%" PRIuSIZE " bytes)...\r\n", length);
157  //Dump message contents for debugging purpose
158  icmpv6DumpMessage(header);
159 
160  //Verify checksum value
161  if(ipCalcUpperLayerChecksumEx(pseudoHeader,
162  sizeof(Ipv6PseudoHeader), buffer, offset, length) != 0x0000)
163  {
164  //Debug message
165  TRACE_WARNING("Wrong ICMPv6 header checksum!\r\n");
166 
167  //Number of ICMP messages which the entity received but determined
168  //as having ICMP-specific errors
169  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsInErrors, 1);
170 
171  //Exit immediately
172  return;
173  }
174 
175  //Check whether the destination address is the tentative address
176  if(ipv6IsTentativeAddr(interface, &pseudoHeader->destAddr))
177  {
178  //The interface must accept Neighbor Solicitation and
179  //Neighbor Advertisement messages
180  if(header->type != ICMPV6_TYPE_NEIGHBOR_SOL &&
181  header->type != ICMPV6_TYPE_NEIGHBOR_ADV)
182  {
183  //Other packets addressed to the tentative address
184  //should be silently discarded
185  return;
186  }
187  }
188 
189  //Increment per-message type ICMP counter
190  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsInPkts[header->type], 1);
191 
192  //Check the type of message
193  switch(header->type)
194  {
195  //Destination Unreachable message?
197  //Process Destination Unreachable message
198  icmpv6ProcessDestUnreachable(interface, pseudoHeader, buffer, offset);
199  break;
200  //Packet Too Big message?
202  //Process Packet Too Big message
203  icmpv6ProcessPacketTooBig(interface, pseudoHeader, buffer, offset);
204  break;
205  //Echo Request message?
207  //Process Echo Request message
208  icmpv6ProcessEchoRequest(interface, pseudoHeader, buffer, offset);
209  break;
210 #if (MLD_NODE_SUPPORT == ENABLED)
211  //MLD message?
216  //Process MLD message
217  mldProcessMessage(interface, pseudoHeader, buffer, offset, ancillary);
218  break;
219 #endif
220 #if (NDP_ROUTER_ADV_SUPPORT == ENABLED)
221  //Router Solicitation message?
223  //Process Router Solicitation message
224  ndpProcessRouterSol(interface, pseudoHeader, buffer, offset, ancillary);
225  break;
226 #endif
227 #if (NDP_SUPPORT == ENABLED)
228  //Router Advertisement message?
230  //Process Router Advertisement message
231  ndpProcessRouterAdv(interface, pseudoHeader, buffer, offset, ancillary);
232  break;
233  //Neighbor Solicitation message?
235  //Process Neighbor Solicitation message
236  ndpProcessNeighborSol(interface, pseudoHeader, buffer, offset, ancillary);
237  break;
238  //Neighbor Advertisement message?
240  //Process Neighbor Advertisement message
241  ndpProcessNeighborAdv(interface, pseudoHeader, buffer, offset, ancillary);
242  break;
243  //Redirect message?
245  //Process Redirect message
246  ndpProcessRedirect(interface, pseudoHeader, buffer, offset, ancillary);
247  break;
248 #endif
249  //Unknown type?
250  default:
251  //Debug message
252  TRACE_WARNING("Unknown ICMPv6 message type!\r\n");
253  //Discard incoming ICMPv6 message
254  break;
255  }
256 }
257 
258 
259 /**
260  * @brief Destination Unreachable message processing
261  * @param[in] interface Underlying network interface
262  * @param[in] pseudoHeader IPv6 pseudo header
263  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
264  * @param[in] offset Offset to the first byte of the ICMPv6 message
265  **/
266 
268  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
269  size_t offset)
270 {
271  size_t length;
272  Icmpv6DestUnreachableMessage *icmpHeader;
273 
274  //Retrieve the length of the Destination Unreachable message
275  length = netBufferGetLength(buffer) - offset;
276 
277  //Ensure the packet length is correct
279  return;
280 
281  //Point to the ICMPv6 header
282  icmpHeader = netBufferAt(buffer, offset, 0);
283 
284  //Sanity check
285  if(icmpHeader == NULL)
286  return;
287 
288  //Debug message
289  TRACE_INFO("ICMPv6 Destination Unreachable message received (%" PRIuSIZE " bytes)...\r\n", length);
290  //Dump message contents for debugging purpose
292 }
293 
294 
295 /**
296  * @brief Packet Too Big message processing
297  * @param[in] interface Underlying network interface
298  * @param[in] pseudoHeader IPv6 pseudo header
299  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
300  * @param[in] offset Offset to the first byte of the ICMPv6 message
301  **/
302 
304  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
305  size_t offset)
306 {
307  size_t length;
308  Icmpv6PacketTooBigMessage *icmpHeader;
309 
310 #if (IPV6_PMTU_SUPPORT == ENABLED)
311  uint32_t tentativePathMtu;
312  Ipv6Header *ipHeader;
313 #endif
314 
315  //Retrieve the length of the Packet Too Big message
316  length = netBufferGetLength(buffer) - offset;
317 
318  //Ensure the packet length is correct
319  if(length < sizeof(Icmpv6PacketTooBigMessage))
320  return;
321 
322  //Point to the ICMPv6 header
323  icmpHeader = netBufferAt(buffer, offset, 0);
324 
325  //Sanity check
326  if(icmpHeader == NULL)
327  return;
328 
329  //Debug message
330  TRACE_INFO("ICMPv6 Packet Too Big message received (%" PRIuSIZE " bytes)...\r\n", length);
331  //Dump message contents for debugging purpose
332  icmpv6DumpPacketTooBigMessage(icmpHeader);
333 
334 #if (IPV6_PMTU_SUPPORT == ENABLED)
335  //Move to the beginning of the original IPv6 packet
336  offset += sizeof(Icmpv6PacketTooBigMessage);
338 
339  //Ensure the packet length is correct
340  if(length < sizeof(Ipv6Header))
341  return;
342 
343  //Point to the original IPv6 header
344  ipHeader = netBufferAt(buffer, offset, 0);
345 
346  //Sanity check
347  if(ipHeader == NULL)
348  return;
349 
350  //The node uses the value in the MTU field in the Packet Too Big
351  //message as a tentative PMTU value
352  tentativePathMtu = ntohl(icmpHeader->mtu);
353 
354  //Update the PMTU for the specified destination address
355  ipv6UpdatePathMtu(interface, &ipHeader->destAddr, tentativePathMtu);
356 #endif
357 }
358 
359 
360 /**
361  * @brief Echo Request message processing
362  * @param[in] interface Underlying network interface
363  * @param[in] requestPseudoHeader IPv6 pseudo header
364  * @param[in] request Multi-part buffer containing the incoming ICMPv6 message
365  * @param[in] requestOffset Offset to the first byte of the ICMPv6 message
366  **/
367 
369  const Ipv6PseudoHeader *requestPseudoHeader, const NetBuffer *request,
370  size_t requestOffset)
371 {
372  error_t error;
373  size_t requestLength;
374  size_t replyOffset;
375  size_t replyLength;
376  NetBuffer *reply;
377  Icmpv6EchoMessage *requestHeader;
378  Icmpv6EchoMessage *replyHeader;
379  Ipv6PseudoHeader replyPseudoHeader;
380 
381  //Retrieve the length of the Echo Request message
382  requestLength = netBufferGetLength(request) - requestOffset;
383 
384  //Ensure the packet length is correct
385  if(requestLength < sizeof(Icmpv6EchoMessage))
386  return;
387 
388  //Point to the Echo Request header
389  requestHeader = netBufferAt(request, requestOffset, 0);
390 
391  //Sanity check
392  if(requestHeader == NULL)
393  return;
394 
395  //Debug message
396  TRACE_INFO("ICMPv6 Echo Request message received (%" PRIuSIZE " bytes)...\r\n", requestLength);
397  //Dump message contents for debugging purpose
398  icmpv6DumpEchoMessage(requestHeader);
399 
400  //If support for Echo Request messages has been explicitly disabled, then
401  //the host shall not respond to the incoming request
402  if(!interface->ipv6Context.enableEchoReq)
403  return;
404 
405  //Check whether the destination address of the Echo Request message is
406  //a multicast address
407  if(ipv6IsMulticastAddr(&requestPseudoHeader->destAddr))
408  {
409  //If support for multicast Echo Request messages has been explicitly
410  //disabled, then the host shall not respond to the incoming request
411  if(!interface->ipv6Context.enableMulticastEchoReq)
412  return;
413 
414  //The source address of the reply must be a unicast address belonging to
415  //the interface on which the multicast Echo Request message was received
416  error = ipv6SelectSourceAddr(&interface, &requestPseudoHeader->srcAddr,
417  &replyPseudoHeader.srcAddr);
418  //Any error to report?
419  if(error)
420  return;
421  }
422  else
423  {
424  //The destination address of the Echo Request message is a unicast address
425  replyPseudoHeader.srcAddr = requestPseudoHeader->destAddr;
426  }
427 
428  //Allocate memory to hold the Echo Reply message
429  reply = ipAllocBuffer(sizeof(Icmpv6EchoMessage), &replyOffset);
430  //Failed to allocate memory?
431  if(reply == NULL)
432  return;
433 
434  //Point to the Echo Reply header
435  replyHeader = netBufferAt(reply, replyOffset, 0);
436 
437  //Format Echo Reply header
438  replyHeader->type = ICMPV6_TYPE_ECHO_REPLY;
439  replyHeader->code = 0;
440  replyHeader->checksum = 0;
441  replyHeader->identifier = requestHeader->identifier;
442  replyHeader->sequenceNumber = requestHeader->sequenceNumber;
443 
444  //Point to the first data byte
445  requestOffset += sizeof(Icmpv6EchoMessage);
446  requestLength -= sizeof(Icmpv6EchoMessage);
447 
448  //Check the length of the payload
449  if(requestLength > 0)
450  {
451  //The data received in the ICMPv6 Echo Request message must be returned
452  //entirely and unmodified in the ICMPv6 Echo Reply message
453  error = netBufferConcat(reply, request, requestOffset, requestLength);
454  }
455  else
456  {
457  //The Echo Request message is empty
458  error = NO_ERROR;
459  }
460 
461  //Check status code
462  if(!error)
463  {
464  NetTxAncillary ancillary;
465 
466  //Get the length of the resulting message
467  replyLength = netBufferGetLength(reply) - replyOffset;
468 
469  //Format IPv6 pseudo header
470  replyPseudoHeader.destAddr = requestPseudoHeader->srcAddr;
471  replyPseudoHeader.length = htonl(replyLength);
472  replyPseudoHeader.reserved[0] = 0;
473  replyPseudoHeader.reserved[1] = 0;
474  replyPseudoHeader.reserved[2] = 0;
475  replyPseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
476 
477  //Message checksum calculation
478  replyHeader->checksum = ipCalcUpperLayerChecksumEx(&replyPseudoHeader,
479  sizeof(Ipv6PseudoHeader), reply, replyOffset, replyLength);
480 
481  //Total number of ICMP messages which this entity attempted to send
482  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
483  //Increment per-message type ICMP counter
484  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[ICMPV6_TYPE_ECHO_REPLY], 1);
485 
486  //Debug message
487  TRACE_INFO("Sending ICMPv6 Echo Reply message (%" PRIuSIZE " bytes)...\r\n", replyLength);
488  //Dump message contents for debugging purpose
489  icmpv6DumpEchoMessage(replyHeader);
490 
491  //Additional options can be passed to the stack along with the packet
492  ancillary = NET_DEFAULT_TX_ANCILLARY;
493 
494  //Send Echo Reply message
495  ipv6SendDatagram(interface, &replyPseudoHeader, reply, replyOffset,
496  &ancillary);
497  }
498 
499  //Free previously allocated memory block
500  netBufferFree(reply);
501 }
502 
503 
504 /**
505  * @brief Send an ICMPv6 Error message
506  * @param[in] interface Underlying network interface
507  * @param[in] type Message type
508  * @param[in] code Specific message code
509  * @param[in] parameter Specific message parameter
510  * @param[in] ipPacket Multi-part buffer that holds the invoking IPv6 packet
511  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
512  * @return Error code
513  **/
514 
516  uint8_t code, uint32_t parameter, const NetBuffer *ipPacket,
517  size_t ipPacketOffset)
518 {
519  error_t error;
520  size_t offset;
521  size_t length;
522  NetBuffer *icmpMessage;
523  Icmpv6ErrorMessage *icmpHeader;
524  Ipv6Header *ipHeader;
525  Ipv6PseudoHeader pseudoHeader;
526 
527  //Retrieve the length of the invoking IPv6 packet
528  length = netBufferGetLength(ipPacket) - ipPacketOffset;
529 
530  //Check the length of the IPv6 packet
531  if(length < sizeof(Ipv6Header))
532  return ERROR_INVALID_LENGTH;
533 
534  //Point to the header of the invoking packet
535  ipHeader = netBufferAt(ipPacket, ipPacketOffset, sizeof(Ipv6Header));
536  //Sanity check
537  if(ipHeader == NULL)
538  return ERROR_FAILURE;
539 
540  //Check the type of the invoking packet
541  if(ipHeader->nextHeader == IPV6_ICMPV6_HEADER)
542  {
543  //Make sure the ICMPv6 message is valid
544  if(length >= (sizeof(Ipv6Header) + sizeof(Icmpv6Header)))
545  {
546  //Point to the ICMPv6 header
547  icmpHeader = netBufferAt(ipPacket, ipPacketOffset + sizeof(Ipv6Header),
548  sizeof(Icmpv6Header));
549 
550  //Sanity check
551  if(icmpHeader != NULL)
552  {
553  //An ICMPv6 error message must not be originated as a result of
554  //receiving an ICMPv6 error or redirect message
555  if(icmpHeader->type == ICMPV6_TYPE_DEST_UNREACHABLE ||
556  icmpHeader->type == ICMPV6_TYPE_PACKET_TOO_BIG ||
557  icmpHeader->type == ICMPV6_TYPE_TIME_EXCEEDED ||
558  icmpHeader->type == ICMPV6_TYPE_PARAM_PROBLEM ||
559  icmpHeader->type == ICMPV6_TYPE_REDIRECT)
560  {
561  return ERROR_INVALID_TYPE;
562  }
563  }
564  }
565  }
566 
567  //An ICMPv6 error message must not be originated as a result of receiving a
568  //packet destined to an IPv6 multicast address
569  if(ipv6IsMulticastAddr(&ipHeader->destAddr))
570  {
571  //There are two exceptions to this rule
573  {
574  //The Packet Too Big Message to allow Path MTU discovery to
575  //work for IPv6 multicast
576  }
577  else if(type == ICMPV6_TYPE_PARAM_PROBLEM &&
579  {
580  //The Parameter Problem Message, reporting an unrecognized IPv6
581  //option that has the Option Type highest-order two bits set to 10
582  }
583  else
584  {
585  //Report an error
586  return ERROR_INVALID_ADDRESS;
587  }
588  }
589 
590  //An ICMPv6 error message must not be originated as a result of receiving a
591  //packet whose source address does not uniquely identify a single node (e.g.
592  //the IPv6 unspecified address, an IPv6 multicast address, or an address
593  //known by the ICMPv6 message originator to be an IPv6 anycast address)
594  if(ipv6IsAnycastAddr(interface, &ipHeader->srcAddr))
595  return ERROR_INVALID_ADDRESS;
596 
597  //Return as much of invoking IPv6 packet as possible without the ICMPv6
598  //packet exceeding the minimum IPv6 MTU
600  sizeof(Icmpv6ErrorMessage));
601 
602  //Allocate a memory buffer to hold the ICMPv6 message
603  icmpMessage = ipAllocBuffer(sizeof(Icmpv6ErrorMessage), &offset);
604 
605  //Failed to allocate memory?
606  if(icmpMessage == NULL)
607  return ERROR_OUT_OF_MEMORY;
608 
609  //Point to the ICMPv6 header
610  icmpHeader = netBufferAt(icmpMessage, offset, 0);
611 
612  //Format ICMPv6 Error message
613  icmpHeader->type = type;
614  icmpHeader->code = code;
615  icmpHeader->checksum = 0;
616  icmpHeader->parameter = htonl(parameter);
617 
618  //Copy incoming IPv6 packet contents
619  error = netBufferConcat(icmpMessage, ipPacket, ipPacketOffset, length);
620 
621  //Check status code
622  if(!error)
623  {
624  //Get the length of the resulting message
625  length = netBufferGetLength(icmpMessage) - offset;
626 
627  //Format IPv6 pseudo header
628  pseudoHeader.destAddr = ipHeader->srcAddr;
629  pseudoHeader.length = htonl(length);
630  pseudoHeader.reserved[0] = 0;
631  pseudoHeader.reserved[1] = 0;
632  pseudoHeader.reserved[2] = 0;
633  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
634 
635  //Select the relevant source address
636  error = ipv6SelectSourceAddr(&interface, &pseudoHeader.destAddr,
637  &pseudoHeader.srcAddr);
638 
639  //Check status code
640  if(!error)
641  {
642  NetTxAncillary ancillary;
643 
644  //Message checksum calculation
645  icmpHeader->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
646  sizeof(Ipv6PseudoHeader), icmpMessage, offset, length);
647 
648  //Total number of ICMP messages which this entity attempted to send
649  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
650  //Increment per-message type ICMP counter
651  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[type], 1);
652 
653  //Debug message
654  TRACE_INFO("Sending ICMPv6 Error message (%" PRIuSIZE " bytes)...\r\n", length);
655  //Dump message contents for debugging purpose
656  icmpv6DumpErrorMessage(icmpHeader);
657 
658  //Additional options can be passed to the stack along with the packet
659  ancillary = NET_DEFAULT_TX_ANCILLARY;
660 
661  //Send ICMPv6 Error message
662  error = ipv6SendDatagram(interface, &pseudoHeader, icmpMessage, offset,
663  &ancillary);
664  }
665  }
666 
667  //Free previously allocated memory
668  netBufferFree(icmpMessage);
669 
670  //Return status code
671  return error;
672 }
673 
674 
675 /**
676  * @brief Dump ICMPv6 message for debugging purpose
677  * @param[in] message Pointer to the ICMP message
678  **/
679 
681 {
682  //Dump ICMPv6 message
683  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
684  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
685  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
686 }
687 
688 
689 /**
690  * @brief Dump ICMPv6 Destination Unreachable message
691  * @param[in] message Pointer to the ICMPv6 message
692  **/
693 
695 {
696  //Dump ICMPv6 message
697  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
698  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
699  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
700 }
701 
702 
703 /**
704  * @brief Dump ICMPv6 Packet Too Big message
705  * @param[in] message Pointer to the ICMPv6 message
706  **/
707 
709 {
710  //Dump ICMPv6 message
711  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
712  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
713  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
714  TRACE_DEBUG(" MTU = %" PRIu32 "\r\n", ntohl(message->mtu));
715 }
716 
717 
718 /**
719  * @brief Dump ICMPv6 Echo Request or Echo Reply message
720  * @param[in] message Pointer to the ICMPv6 message
721  **/
722 
724 {
725  //Dump ICMPv6 message
726  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
727  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
728  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
729  TRACE_DEBUG(" Identifier = 0x%04" PRIX16 "\r\n", ntohs(message->identifier));
730  TRACE_DEBUG(" Sequence Number = 0x%04" PRIX16 "\r\n", ntohs(message->sequenceNumber));
731 }
732 
733 
734 /**
735  * @brief Dump generic ICMPv6 Error message
736  * @param[in] message Pointer to the ICMPv6 message
737  **/
738 
740 {
741  //Dump ICMP message
742  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
743  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
744  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
745  TRACE_DEBUG(" Parameter = %" PRIu32 "\r\n", ntohl(message->parameter));
746 }
747 
748 #endif
@ ICMPV6_TYPE_ROUTER_ADV
Definition: icmpv6.h:63
IPv6 (Internet Protocol Version 6)
@ ICMPV6_TYPE_PACKET_TOO_BIG
Definition: icmpv6.h:54
@ ICMPV6_TYPE_DEST_UNREACHABLE
Definition: icmpv6.h:53
void icmpv6ProcessDestUnreachable(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Destination Unreachable message processing.
Definition: icmpv6.c:267
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:710
uint8_t code
Definition: coap_common.h:179
int bool_t
Definition: compiler_port.h:61
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:72
void icmpv6DumpEchoMessage(const Icmpv6EchoMessage *message)
Dump ICMPv6 Echo Request or Echo Reply message.
Definition: icmpv6.c:723
void icmpv6DumpErrorMessage(const Icmpv6ErrorMessage *message)
Dump generic ICMPv6 Error message.
Definition: icmpv6.c:739
#define netMutex
Definition: net_legacy.h:195
Icmpv6EchoMessage
Definition: icmpv6.h:233
void icmpv6DumpPacketTooBigMessage(const Icmpv6PacketTooBigMessage *message)
Dump ICMPv6 Packet Too Big message.
Definition: icmpv6.c:708
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint8_t message[]
Definition: chap.h:154
#define Ipv6Header
Definition: ipv6.h:36
Icmpv6ErrorMessage
Definition: icmpv6.h:139
uint8_t type
Definition: coap_common.h:176
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
bool_t ipv6IsTentativeAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is a tentative address.
Definition: ipv6_misc.c:1100
@ IPV6_ICMPV6_HEADER
Definition: ipv6.h:193
void ipv6UpdatePathMtu(NetInterface *interface, const Ipv6Addr *destAddr, size_t tentativePathMtu)
Update the PMTU for the specified path.
Definition: ipv6_pmtu.c:93
uint8_t parameter
Definition: icmp.h:173
@ ICMPV6_TYPE_MCAST_LISTENER_QUERY
Definition: icmpv6.h:59
void icmpv6DumpDestUnreachableMessage(const Icmpv6DestUnreachableMessage *message)
Dump ICMPv6 Destination Unreachable message.
Definition: icmpv6.c:694
uint8_t ipPacket[]
Definition: ndp.h:431
@ ICMPV6_TYPE_ECHO_REQUEST
Definition: icmpv6.h:57
error_t netBufferConcat(NetBuffer *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Concatenate two multi-part buffers.
Definition: net_mem.c:460
@ ICMPV6_TYPE_ECHO_REPLY
Definition: icmpv6.h:58
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:139
error_t icmpv6SendErrorMessage(NetInterface *interface, uint8_t type, uint8_t code, uint32_t parameter, const NetBuffer *ipPacket, size_t ipPacketOffset)
Send an ICMPv6 Error message.
Definition: icmpv6.c:515
void ndpProcessRouterSol(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Router Solicitation message processing.
void ndpProcessRedirect(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Redirect message processing.
Definition: ndp.c:1460
ICMPv6 (Internet Control Message Protocol Version 6)
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define htonl(value)
Definition: cpu_endian.h:414
error_t
Error codes.
Definition: error.h:43
#define Ipv6PseudoHeader
Definition: ipv6.h:42
@ ICMPV6_TYPE_REDIRECT
Definition: icmpv6.h:66
error_t ipv6SelectSourceAddr(NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:870
@ ICMPV6_TYPE_MCAST_LISTENER_REPORT_V1
Definition: icmpv6.h:60
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void icmpv6DumpMessage(const Icmpv6Header *message)
Dump ICMPv6 message for debugging purpose.
Definition: icmpv6.c:680
@ ICMPV6_CODE_UNKNOWN_IPV6_OPTION
Definition: icmpv6.h:103
#define NetRxAncillary
Definition: net_misc.h:40
void icmpv6ProcessMessage(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Incoming ICMPv6 message processing.
Definition: icmpv6.c:124
#define NetInterface
Definition: net.h:36
void icmpv6ProcessPacketTooBig(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Packet Too Big message processing.
Definition: icmpv6.c:303
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
@ ERROR_INVALID_LENGTH
Definition: error.h:111
Helper functions for IPv6.
@ ICMPV6_TYPE_NEIGHBOR_ADV
Definition: icmpv6.h:65
#define NetTxAncillary
Definition: net_misc.h:36
@ ERROR_INVALID_TYPE
Definition: error.h:115
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:63
error_t icmpv6EnableMulticastEchoRequests(NetInterface *interface, bool_t enable)
Enable support for multicast ICMPv6 Echo Request messages.
Definition: icmpv6.c:95
Path MTU Discovery for IPv6.
NDP (Neighbor Discovery Protocol)
void ndpProcessNeighborSol(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Neighbor Solicitation message processing.
Definition: ndp.c:966
void ndpProcessNeighborAdv(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Neighbor Advertisement message processing.
Definition: ndp.c:1212
#define ntohs(value)
Definition: cpu_endian.h:421
#define TRACE_WARNING(...)
Definition: debug.h:93
#define TRACE_DEBUG(...)
Definition: debug.h:119
error_t icmpv6EnableEchoRequests(NetInterface *interface, bool_t enable)
Enable support for ICMPv6 Echo Request messages.
Definition: icmpv6.c:67
uint16_t ipCalcUpperLayerChecksumEx(const void *pseudoHeader, size_t pseudoHeaderLen, const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP upper-layer checksum over a multi-part buffer.
Definition: ip.c:685
@ ICMPV6_TYPE_ROUTER_SOL
Definition: icmpv6.h:62
#define IPV6_DEFAULT_MTU
Definition: ipv6.h:115
IPv4 and IPv6 common routines.
error_t ipv6SendDatagram(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 datagram.
Definition: ipv6.c:1713
void mldProcessMessage(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Process incoming MLD message.
Definition: mld_common.c:226
IP MIB module.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
bool_t ipv6IsAnycastAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is an anycast address.
Definition: ipv6_misc.c:1064
@ ICMPV6_TYPE_MCAST_LISTENER_DONE_V1
Definition: icmpv6.h:61
void * netBufferAt(const NetBuffer *buffer, size_t offset, size_t length)
Returns a pointer to a data segment.
Definition: net_mem.c:418
Icmpv6DestUnreachableMessage
Definition: icmpv6.h:158
@ ICMPV6_TYPE_PARAM_PROBLEM
Definition: icmpv6.h:56
@ ICMPV6_TYPE_MCAST_LISTENER_REPORT_V2
Definition: icmpv6.h:67
Helper functions for MLD node.
#define PRIuSIZE
Icmpv6Header
Definition: icmpv6.h:125
Helper functions for router advertisement service.
TCP/IP stack core.
@ ICMPV6_TYPE_NEIGHBOR_SOL
Definition: icmpv6.h:64
void ndpProcessRouterAdv(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Router Advertisement message processing.
Definition: ndp.c:676
#define ntohl(value)
Definition: cpu_endian.h:422
void icmpv6ProcessEchoRequest(NetInterface *interface, const Ipv6PseudoHeader *requestPseudoHeader, const NetBuffer *request, size_t requestOffset)
Echo Request message processing.
Definition: icmpv6.c:368
@ NO_ERROR
Success.
Definition: error.h:44
@ ICMPV6_TYPE_TIME_EXCEEDED
Definition: icmpv6.h:55
Debugging facilities.
Icmpv6PacketTooBigMessage
Definition: icmpv6.h:177