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