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