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-2023 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.2.4
36  **/
37 
38 //Switch to the appropriate trace level
39 #define TRACE_LEVEL ICMPV6_TRACE_LEVEL
40 
41 //Dependencies
42 #include <string.h>
43 #include "core/net.h"
44 #include "core/ip.h"
45 #include "ipv6/ipv6.h"
46 #include "ipv6/ipv6_misc.h"
47 #include "ipv6/ipv6_pmtu.h"
48 #include "ipv6/icmpv6.h"
49 #include "ipv6/mld.h"
50 #include "ipv6/ndp.h"
52 #include "mibs/ip_mib_module.h"
53 #include "debug.h"
54 
55 //Check TCP/IP stack configuration
56 #if (IPV6_SUPPORT == ENABLED)
57 
58 
59 /**
60  * @brief Enable support for Echo Request messages
61  * @param[in] interface Underlying network interface
62  * @param[in] enable When the flag is set to TRUE, the host will respond to
63  * Echo Requests. When the flag is set to FALSE, incoming Echo Request
64  * messages will be dropped
65  * @return Error code
66  **/
67 
69 {
70  //Check parameters
71  if(interface == NULL)
73 
74  //Get exclusive access
76  //Enable or disable support for Echo Request messages
77  interface->ipv6Context.enableEchoReq = enable;
78  //Release exclusive access
80 
81  //Successful processing
82  return NO_ERROR;
83 }
84 
85 
86 /**
87  * @brief Enable support for multicast Echo Request messages
88  * @param[in] interface Underlying network interface
89  * @param[in] enable When the flag is set to TRUE, the host will respond to
90  * multicast Echo Requests. When the flag is set to FALSE, incoming Echo
91  * Request messages destined to a multicast address will be 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] hopLimit Hop Limit field from IPv6 header
121  **/
122 
124  Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset,
125  uint8_t hopLimit)
126 {
127  size_t length;
128  Icmpv6Header *header;
129 
130  //Total number of ICMP messages which the entity received
131  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsInMsgs, 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  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsInErrors, 1);
142 
143  //Silently discard incoming message
144  return;
145  }
146 
147  //Point to the ICMPv6 message header
148  header = netBufferAt(buffer, offset);
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  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsInErrors, 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  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsInPkts[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  //Packet Too Big message?
201  //Process Packet Too Big message
202  icmpv6ProcessPacketTooBig(interface, pseudoHeader, buffer, offset);
203  break;
204  //Echo Request message?
206  //Process Echo Request message
207  icmpv6ProcessEchoRequest(interface, pseudoHeader, buffer, offset);
208  break;
209 #if (MLD_SUPPORT == ENABLED)
210  //Multicast Listener Query message?
212  //Process Multicast Listener Query message
213  mldProcessListenerQuery(interface, pseudoHeader, buffer, offset, hopLimit);
214  break;
215  //Version 1 Multicast Listener Report message?
217  //Process Version 1 Multicast Listener Report message
218  mldProcessListenerReport(interface, pseudoHeader, buffer, offset, hopLimit);
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, hopLimit);
226  break;
227 #endif
228 #if (NDP_SUPPORT == ENABLED)
229  //Router Advertisement message?
231  //Process Router Advertisement message
232  ndpProcessRouterAdv(interface, pseudoHeader, buffer, offset, hopLimit);
233  break;
234  //Neighbor Solicitation message?
236  //Process Neighbor Solicitation message
237  ndpProcessNeighborSol(interface, pseudoHeader, buffer, offset, hopLimit);
238  break;
239  //Neighbor Advertisement message?
241  //Process Neighbor Advertisement message
242  ndpProcessNeighborAdv(interface, pseudoHeader, buffer, offset, hopLimit);
243  break;
244  //Redirect message?
246  //Process Redirect message
247  ndpProcessRedirect(interface, pseudoHeader, buffer, offset, hopLimit);
248  break;
249 #endif
250  //Unknown type?
251  default:
252  //Debug message
253  TRACE_WARNING("Unknown ICMPv6 message type!\r\n");
254  //Discard incoming ICMPv6 message
255  break;
256  }
257 }
258 
259 
260 /**
261  * @brief Destination Unreachable message processing
262  * @param[in] interface Underlying network interface
263  * @param[in] pseudoHeader IPv6 pseudo header
264  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
265  * @param[in] offset Offset to the first byte of the ICMPv6 message
266  **/
267 
269  Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, 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);
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  Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
305 {
306  size_t length;
307  Icmpv6PacketTooBigMessage *icmpHeader;
308 
309 #if (IPV6_PMTU_SUPPORT == ENABLED)
310  uint32_t tentativePathMtu;
311  Ipv6Header *ipHeader;
312 #endif
313 
314  //Retrieve the length of the Packet Too Big message
315  length = netBufferGetLength(buffer) - offset;
316 
317  //Ensure the packet length is correct
318  if(length < sizeof(Icmpv6PacketTooBigMessage))
319  return;
320 
321  //Point to the ICMPv6 header
322  icmpHeader = netBufferAt(buffer, offset);
323 
324  //Sanity check
325  if(icmpHeader == NULL)
326  return;
327 
328  //Debug message
329  TRACE_INFO("ICMPv6 Packet Too Big message received (%" PRIuSIZE " bytes)...\r\n", length);
330  //Dump message contents for debugging purpose
331  icmpv6DumpPacketTooBigMessage(icmpHeader);
332 
333 #if (IPV6_PMTU_SUPPORT == ENABLED)
334  //Move to the beginning of the original IPv6 packet
335  offset += sizeof(Icmpv6PacketTooBigMessage);
337 
338  //Ensure the packet length is correct
339  if(length < sizeof(Ipv6Header))
340  return;
341 
342  //Point to the original IPv6 header
343  ipHeader = netBufferAt(buffer, offset);
344 
345  //Sanity check
346  if(ipHeader == NULL)
347  return;
348 
349  //The node uses the value in the MTU field in the Packet Too Big
350  //message as a tentative PMTU value
351  tentativePathMtu = ntohl(icmpHeader->mtu);
352 
353  //Update the PMTU for the specified destination address
354  ipv6UpdatePathMtu(interface, &ipHeader->destAddr, tentativePathMtu);
355 #endif
356 }
357 
358 
359 /**
360  * @brief Echo Request message processing
361  * @param[in] interface Underlying network interface
362  * @param[in] requestPseudoHeader IPv6 pseudo header
363  * @param[in] request Multi-part buffer containing the incoming ICMPv6 message
364  * @param[in] requestOffset Offset to the first byte of the ICMPv6 message
365  **/
366 
368  Ipv6PseudoHeader *requestPseudoHeader, const NetBuffer *request,
369  size_t requestOffset)
370 {
371  error_t error;
372  size_t requestLength;
373  size_t replyOffset;
374  size_t replyLength;
375  NetBuffer *reply;
376  Icmpv6EchoMessage *requestHeader;
377  Icmpv6EchoMessage *replyHeader;
378  Ipv6PseudoHeader replyPseudoHeader;
379 
380  //Retrieve the length of the Echo Request message
381  requestLength = netBufferGetLength(request) - requestOffset;
382 
383  //Ensure the packet length is correct
384  if(requestLength < sizeof(Icmpv6EchoMessage))
385  return;
386 
387  //Point to the Echo Request header
388  requestHeader = netBufferAt(request, requestOffset);
389 
390  //Sanity check
391  if(requestHeader == NULL)
392  return;
393 
394  //Debug message
395  TRACE_INFO("ICMPv6 Echo Request message received (%" PRIuSIZE " bytes)...\r\n", requestLength);
396  //Dump message contents for debugging purpose
397  icmpv6DumpEchoMessage(requestHeader);
398 
399  //If support for Echo Request messages has been explicitly disabled, then
400  //the host shall not respond to the incoming request
401  if(!interface->ipv6Context.enableEchoReq)
402  return;
403 
404  //Check whether the destination address of the Echo Request message is
405  //a multicast address
406  if(ipv6IsMulticastAddr(&requestPseudoHeader->destAddr))
407  {
408  //If support for multicast Echo Request messages has been explicitly
409  //disabled, then the host shall not respond to the incoming request
410  if(!interface->ipv6Context.enableMulticastEchoReq)
411  return;
412 
413  //The source address of the reply must be a unicast address belonging to
414  //the interface on which the multicast Echo Request message was received
415  error = ipv6SelectSourceAddr(&interface, &requestPseudoHeader->srcAddr,
416  &replyPseudoHeader.srcAddr);
417  //Any error to report?
418  if(error)
419  return;
420  }
421  else
422  {
423  //The destination address of the Echo Request message is a unicast address
424  replyPseudoHeader.srcAddr = requestPseudoHeader->destAddr;
425  }
426 
427  //Allocate memory to hold the Echo Reply message
428  reply = ipAllocBuffer(sizeof(Icmpv6EchoMessage), &replyOffset);
429  //Failed to allocate memory?
430  if(reply == NULL)
431  return;
432 
433  //Point to the Echo Reply header
434  replyHeader = netBufferAt(reply, replyOffset);
435 
436  //Format Echo Reply header
437  replyHeader->type = ICMPV6_TYPE_ECHO_REPLY;
438  replyHeader->code = 0;
439  replyHeader->checksum = 0;
440  replyHeader->identifier = requestHeader->identifier;
441  replyHeader->sequenceNumber = requestHeader->sequenceNumber;
442 
443  //Point to the first data byte
444  requestOffset += sizeof(Icmpv6EchoMessage);
445  requestLength -= sizeof(Icmpv6EchoMessage);
446 
447  //The data received in the ICMPv6 Echo Request message must be returned
448  //entirely and unmodified in the ICMPv6 Echo Reply message
449  error = netBufferConcat(reply, request, requestOffset, requestLength);
450 
451  //Check status code
452  if(!error)
453  {
454  NetTxAncillary ancillary;
455 
456  //Get the length of the resulting message
457  replyLength = netBufferGetLength(reply) - replyOffset;
458 
459  //Format IPv6 pseudo header
460  replyPseudoHeader.destAddr = requestPseudoHeader->srcAddr;
461  replyPseudoHeader.length = htonl(replyLength);
462  replyPseudoHeader.reserved[0] = 0;
463  replyPseudoHeader.reserved[1] = 0;
464  replyPseudoHeader.reserved[2] = 0;
465  replyPseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
466 
467  //Message checksum calculation
468  replyHeader->checksum = ipCalcUpperLayerChecksumEx(&replyPseudoHeader,
469  sizeof(Ipv6PseudoHeader), reply, replyOffset, replyLength);
470 
471  //Total number of ICMP messages which this entity attempted to send
472  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
473  //Increment per-message type ICMP counter
474  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[ICMPV6_TYPE_ECHO_REPLY], 1);
475 
476  //Debug message
477  TRACE_INFO("Sending ICMPv6 Echo Reply message (%" PRIuSIZE " bytes)...\r\n", replyLength);
478  //Dump message contents for debugging purpose
479  icmpv6DumpEchoMessage(replyHeader);
480 
481  //Additional options can be passed to the stack along with the packet
482  ancillary = NET_DEFAULT_TX_ANCILLARY;
483 
484  //Send Echo Reply message
485  ipv6SendDatagram(interface, &replyPseudoHeader, reply, replyOffset,
486  &ancillary);
487  }
488 
489  //Free previously allocated memory block
490  netBufferFree(reply);
491 }
492 
493 
494 /**
495  * @brief Send an ICMPv6 Error message
496  * @param[in] interface Underlying network interface
497  * @param[in] type Message type
498  * @param[in] code Specific message code
499  * @param[in] parameter Specific message parameter
500  * @param[in] ipPacket Multi-part buffer that holds the invoking IPv6 packet
501  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
502  * @return Error code
503  **/
504 
506  uint8_t code, uint32_t parameter, const NetBuffer *ipPacket,
507  size_t ipPacketOffset)
508 {
509  error_t error;
510  size_t offset;
511  size_t length;
512  NetBuffer *icmpMessage;
513  Icmpv6ErrorMessage *icmpHeader;
514  Ipv6Header *ipHeader;
515  Ipv6PseudoHeader pseudoHeader;
516 
517  //Retrieve the length of the invoking IPv6 packet
518  length = netBufferGetLength(ipPacket) - ipPacketOffset;
519 
520  //Check the length of the IPv6 packet
521  if(length < sizeof(Ipv6Header))
522  return ERROR_INVALID_LENGTH;
523 
524  //Point to the header of the invoking packet
525  ipHeader = netBufferAt(ipPacket, ipPacketOffset);
526 
527  //Sanity check
528  if(ipHeader == NULL)
529  return ERROR_FAILURE;
530 
531  //Check the type of the invoking packet
532  if(ipHeader->nextHeader == IPV6_ICMPV6_HEADER)
533  {
534  //Make sure the ICMPv6 message is valid
535  if(length >= (sizeof(Ipv6Header) + sizeof(Icmpv6Header)))
536  {
537  //Point to the ICMPv6 header
538  icmpHeader = netBufferAt(ipPacket, ipPacketOffset + sizeof(Ipv6Header));
539 
540  //Sanity check
541  if(icmpHeader != NULL)
542  {
543  //An ICMPv6 error message must not be originated as a result
544  //of receiving an ICMPv6 error or redirect message
545  if(icmpHeader->type == ICMPV6_TYPE_DEST_UNREACHABLE ||
546  icmpHeader->type == ICMPV6_TYPE_PACKET_TOO_BIG ||
547  icmpHeader->type == ICMPV6_TYPE_TIME_EXCEEDED ||
548  icmpHeader->type == ICMPV6_TYPE_PARAM_PROBLEM ||
549  icmpHeader->type == ICMPV6_TYPE_REDIRECT)
550  {
551  //Do not send the ICMPv6 error message...
552  return ERROR_INVALID_TYPE;
553  }
554  }
555  }
556  }
557 
558  //An ICMPv6 error message must not be originated as a result of
559  //receiving a packet destined to an IPv6 multicast address
560  if(ipv6IsMulticastAddr(&ipHeader->destAddr))
561  {
562  //There are two exceptions to this rule
564  {
565  //The Packet Too Big Message to allow Path MTU discovery to
566  //work for IPv6 multicast
567  }
568  else if(type == ICMPV6_TYPE_PARAM_PROBLEM &&
570  {
571  //The Parameter Problem Message, reporting an unrecognized IPv6
572  //option that has the Option Type highest-order two bits set to 10
573  }
574  else
575  {
576  //Do not send the ICMPv6 error message...
577  return ERROR_INVALID_ADDRESS;
578  }
579  }
580 
581  //An ICMPv6 error message must not be originated as a result of receiving a
582  //packet whose source address does not uniquely identify a single node (e.g.
583  //the IPv6 unspecified address, an IPv6 multicast address, or an address
584  //known by the ICMPv6 message originator to be an IPv6 anycast address)
585  if(ipv6IsAnycastAddr(interface, &ipHeader->srcAddr))
586  return ERROR_INVALID_ADDRESS;
587 
588  //Return as much of invoking IPv6 packet as possible without
589  //the ICMPv6 packet exceeding the minimum IPv6 MTU
591  sizeof(Ipv6Header) - sizeof(Icmpv6ErrorMessage));
592 
593  //Allocate a memory buffer to hold the ICMPv6 message
594  icmpMessage = ipAllocBuffer(sizeof(Icmpv6ErrorMessage), &offset);
595 
596  //Failed to allocate memory?
597  if(icmpMessage == NULL)
598  return ERROR_OUT_OF_MEMORY;
599 
600  //Point to the ICMPv6 header
601  icmpHeader = netBufferAt(icmpMessage, offset);
602 
603  //Format ICMPv6 Error message
604  icmpHeader->type = type;
605  icmpHeader->code = code;
606  icmpHeader->checksum = 0;
607  icmpHeader->parameter = htonl(parameter);
608 
609  //Copy incoming IPv6 packet contents
610  error = netBufferConcat(icmpMessage, ipPacket, ipPacketOffset, length);
611 
612  //Check status code
613  if(!error)
614  {
615  //Get the length of the resulting message
616  length = netBufferGetLength(icmpMessage) - offset;
617 
618  //Format IPv6 pseudo header
619  pseudoHeader.destAddr = ipHeader->srcAddr;
620  pseudoHeader.length = htonl(length);
621  pseudoHeader.reserved[0] = 0;
622  pseudoHeader.reserved[1] = 0;
623  pseudoHeader.reserved[2] = 0;
624  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
625 
626  //Select the relevant source address
627  error = ipv6SelectSourceAddr(&interface, &pseudoHeader.destAddr,
628  &pseudoHeader.srcAddr);
629 
630  //Check status code
631  if(!error)
632  {
633  NetTxAncillary ancillary;
634 
635  //Message checksum calculation
636  icmpHeader->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
637  sizeof(Ipv6PseudoHeader), icmpMessage, offset, length);
638 
639  //Total number of ICMP messages which this entity attempted to send
640  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
641  //Increment per-message type ICMP counter
642  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[type], 1);
643 
644  //Debug message
645  TRACE_INFO("Sending ICMPv6 Error message (%" PRIuSIZE " bytes)...\r\n", length);
646  //Dump message contents for debugging purpose
647  icmpv6DumpErrorMessage(icmpHeader);
648 
649  //Additional options can be passed to the stack along with the packet
650  ancillary = NET_DEFAULT_TX_ANCILLARY;
651 
652  //Send ICMPv6 Error message
653  error = ipv6SendDatagram(interface, &pseudoHeader, icmpMessage, offset,
654  &ancillary);
655  }
656  }
657 
658  //Free previously allocated memory
659  netBufferFree(icmpMessage);
660 
661  //Return status code
662  return error;
663 }
664 
665 
666 /**
667  * @brief Dump ICMPv6 message for debugging purpose
668  * @param[in] message Pointer to the ICMP message
669  **/
670 
672 {
673  //Dump ICMPv6 message
674  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
675  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
676  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
677 }
678 
679 
680 /**
681  * @brief Dump ICMPv6 Destination Unreachable message
682  * @param[in] message Pointer to the ICMPv6 message
683  **/
684 
686 {
687  //Dump ICMPv6 message
688  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
689  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
690  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
691 }
692 
693 
694 /**
695  * @brief Dump ICMPv6 Packet Too Big message
696  * @param[in] message Pointer to the ICMPv6 message
697  **/
698 
700 {
701  //Dump ICMPv6 message
702  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
703  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
704  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
705  TRACE_DEBUG(" MTU = %" PRIu32 "\r\n", ntohl(message->mtu));
706 }
707 
708 
709 /**
710  * @brief Dump ICMPv6 Echo Request or Echo Reply 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(" Identifier = 0x%04" PRIX16 "\r\n", ntohs(message->identifier));
721  TRACE_DEBUG(" Sequence Number = 0x%04" PRIX16 "\r\n", ntohs(message->sequenceNumber));
722 }
723 
724 
725 /**
726  * @brief Dump generic ICMPv6 Error message
727  * @param[in] message Pointer to the ICMPv6 message
728  **/
729 
731 {
732  //Dump ICMP message
733  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
734  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
735  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
736  TRACE_DEBUG(" Parameter = %" PRIu32 "\r\n", ntohl(message->parameter));
737 }
738 
739 #endif
void ndpProcessNeighborSol(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Neighbor Solicitation message processing.
Definition: ndp.c:813
@ ICMPV6_TYPE_ROUTER_ADV
Definition: icmpv6.h:63
uint8_t length
Definition: coap_common.h:193
IPv6 (Internet Protocol Version 6)
@ ICMPV6_TYPE_PACKET_TOO_BIG
Definition: icmpv6.h:54
@ ICMPV6_TYPE_DEST_UNREACHABLE
Definition: icmpv6.h:53
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:724
uint8_t code
Definition: coap_common.h:177
int bool_t
Definition: compiler_port.h:53
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:71
void icmpv6DumpEchoMessage(const Icmpv6EchoMessage *message)
Dump ICMPv6 Echo Request or Echo Reply message.
Definition: icmpv6.c:714
void icmpv6DumpErrorMessage(const Icmpv6ErrorMessage *message)
Dump generic ICMPv6 Error message.
Definition: icmpv6.c:730
#define netMutex
Definition: net_legacy.h:195
void icmpv6DumpPacketTooBigMessage(const Icmpv6PacketTooBigMessage *message)
Dump ICMPv6 Packet Too Big message.
Definition: icmpv6.c:699
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
void icmpv6ProcessEchoRequest(NetInterface *interface, Ipv6PseudoHeader *requestPseudoHeader, const NetBuffer *request, size_t requestOffset)
Echo Request message processing.
Definition: icmpv6.c:367
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define Ipv6Header
Definition: ipv6.h:36
@ 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:1109
@ IPV6_ICMPV6_HEADER
Definition: ipv6.h:187
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:123
@ ICMPV6_TYPE_MULTICAST_LISTENER_REPORT_V1
Definition: icmpv6.h:60
__start_packed struct @0 Icmpv6Header
ICMPv6 header.
void icmpv6DumpDestUnreachableMessage(const Icmpv6DestUnreachableMessage *message)
Dump ICMPv6 Destination Unreachable message.
Definition: icmpv6.c:685
error_t icmpv6EnableEchoRequest(NetInterface *interface, bool_t enable)
Enable support for Echo Request messages.
Definition: icmpv6.c:68
void icmpv6ProcessMessage(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Incoming ICMPv6 message processing.
Definition: icmpv6.c:123
uint8_t ipPacket[]
Definition: ndp.h:429
@ 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:442
@ ICMPV6_TYPE_ECHO_REPLY
Definition: icmpv6.h:58
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:133
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:505
void ndpProcessRouterAdv(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Router Advertisement message processing.
Definition: ndp.c:528
ICMPv6 (Internet Control Message Protocol Version 6)
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define htonl(value)
Definition: cpu_endian.h:414
char_t type
error_t
Error codes.
Definition: error.h:43
void icmpv6ProcessDestUnreachable(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Destination Unreachable message processing.
Definition: icmpv6.c:268
#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:879
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:413
@ 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:671
@ ICMPV6_CODE_UNKNOWN_IPV6_OPTION
Definition: icmpv6.h:103
#define NetInterface
Definition: net.h:36
void mldProcessListenerReport(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Process incoming Multicast Listener Report message.
Definition: mld.c:371
error_t icmpv6EnableMulticastEchoRequest(NetInterface *interface, bool_t enable)
Enable support for multicast Echo Request messages.
Definition: icmpv6.c:95
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
@ ICMPV6_TYPE_MULTICAST_LISTENER_QUERY
Definition: icmpv6.h:59
#define TRACE_INFO(...)
Definition: debug.h:95
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
void icmpv6ProcessPacketTooBig(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Packet Too Big message processing.
Definition: icmpv6.c:303
#define MIN(a, b)
Definition: os_port.h:65
Path MTU Discovery for IPv6.
__start_packed struct @6 Icmpv6EchoMessage
ICMPv6 Echo Request and Echo Reply messages.
NDP (Neighbor Discovery Protocol)
#define ntohs(value)
Definition: cpu_endian.h:421
#define TRACE_WARNING(...)
Definition: debug.h:85
#define TRACE_DEBUG(...)
Definition: debug.h:107
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:699
@ ICMPV6_TYPE_ROUTER_SOL
Definition: icmpv6.h:62
#define IPV6_DEFAULT_MTU
Definition: ipv6.h:109
__start_packed struct @3 Icmpv6PacketTooBigMessage
ICMPv6 Packet Too Big message.
IPv4 and IPv6 common routines.
void mldProcessListenerQuery(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Process incoming Multicast Listener Query message.
Definition: mld.c:268
void ndpProcessRouterSol(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Router Solicitation message processing.
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:1073
uint8_t message[]
Definition: chap.h:152
void ndpProcessNeighborAdv(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Neighbor Advertisement message processing.
Definition: ndp.c:1050
error_t ipv6SendDatagram(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 datagram.
Definition: ipv6.c:1637
void ndpProcessRedirect(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Redirect message processing.
Definition: ndp.c:1300
@ ICMPV6_TYPE_PARAM_PROBLEM
Definition: icmpv6.h:56
#define PRIuSIZE
Helper functions for router advertisement service.
TCP/IP stack core.
__start_packed struct @2 Icmpv6DestUnreachableMessage
ICMPv6 Destination Unreachable message.
@ ICMPV6_TYPE_NEIGHBOR_SOL
Definition: icmpv6.h:64
#define ntohl(value)
Definition: cpu_endian.h:422
@ NO_ERROR
Success.
Definition: error.h:44
@ ICMPV6_TYPE_TIME_EXCEEDED
Definition: icmpv6.h:55
Debugging facilities.
MLD (Multicast Listener Discovery for IPv6)
__start_packed struct @1 Icmpv6ErrorMessage
ICMPv6 Error message.