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-2024 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.4.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_misc.h"
46 #include "ipv6/ipv6_pmtu.h"
47 #include "ipv6/icmpv6.h"
48 #include "ipv6/mld.h"
49 #include "ipv6/ndp.h"
51 #include "mibs/ip_mib_module.h"
52 #include "debug.h"
53 
54 //Check TCP/IP stack configuration
55 #if (IPV6_SUPPORT == ENABLED)
56 
57 
58 /**
59  * @brief Enable support for ICMPv6 Echo Request messages
60  * @param[in] interface Underlying network interface
61  * @param[in] enable This flag specifies whether the host will respond to
62  * ICMPv6 Echo Requests. When the flag is set to FALSE, incoming ICMPv6 Echo
63  * Request messages will be dropped
64  * @return Error code
65  **/
66 
68 {
69  //Check parameters
70  if(interface == NULL)
72 
73  //Get exclusive access
75  //Enable or disable support for Echo Request messages
76  interface->ipv6Context.enableEchoReq = enable;
77  //Release exclusive access
79 
80  //Successful processing
81  return NO_ERROR;
82 }
83 
84 
85 /**
86  * @brief Enable support for multicast ICMPv6 Echo Request messages
87  * @param[in] interface Underlying network interface
88  * @param[in] enable This flag specifies whether the host will respond to
89  * multicast ICMPv6 Echo Requests. When the flag is set to FALSE, incoming
90  * ICMPv6 Echo Request messages destined to a multicast address will be
91  * dropped
92  * @return Error code
93  **/
94 
96  bool_t enable)
97 {
98  //Check parameters
99  if(interface == NULL)
101 
102  //Get exclusive access
104  //Enable or disable support for multicast Echo Request messages
105  interface->ipv6Context.enableMulticastEchoReq = enable;
106  //Release exclusive access
108 
109  //Successful processing
110  return NO_ERROR;
111 }
112 
113 
114 /**
115  * @brief Incoming ICMPv6 message processing
116  * @param[in] interface Underlying network interface
117  * @param[in] pseudoHeader IPv6 pseudo header
118  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
119  * @param[in] offset Offset to the first byte of the ICMPv6 message
120  * @param[in] hopLimit Hop Limit field from IPv6 header
121  **/
122 
124  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
125  size_t offset, 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  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
270  size_t offset)
271 {
272  size_t length;
273  Icmpv6DestUnreachableMessage *icmpHeader;
274 
275  //Retrieve the length of the Destination Unreachable message
276  length = netBufferGetLength(buffer) - offset;
277 
278  //Ensure the packet length is correct
280  return;
281 
282  //Point to the ICMPv6 header
283  icmpHeader = netBufferAt(buffer, offset);
284 
285  //Sanity check
286  if(icmpHeader == NULL)
287  return;
288 
289  //Debug message
290  TRACE_INFO("ICMPv6 Destination Unreachable message received (%" PRIuSIZE " bytes)...\r\n", length);
291  //Dump message contents for debugging purpose
293 }
294 
295 
296 /**
297  * @brief Packet Too Big message processing
298  * @param[in] interface Underlying network interface
299  * @param[in] pseudoHeader IPv6 pseudo header
300  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
301  * @param[in] offset Offset to the first byte of the ICMPv6 message
302  **/
303 
305  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
306  size_t offset)
307 {
308  size_t length;
309  Icmpv6PacketTooBigMessage *icmpHeader;
310 
311 #if (IPV6_PMTU_SUPPORT == ENABLED)
312  uint32_t tentativePathMtu;
313  Ipv6Header *ipHeader;
314 #endif
315 
316  //Retrieve the length of the Packet Too Big message
317  length = netBufferGetLength(buffer) - offset;
318 
319  //Ensure the packet length is correct
320  if(length < sizeof(Icmpv6PacketTooBigMessage))
321  return;
322 
323  //Point to the ICMPv6 header
324  icmpHeader = netBufferAt(buffer, offset);
325 
326  //Sanity check
327  if(icmpHeader == NULL)
328  return;
329 
330  //Debug message
331  TRACE_INFO("ICMPv6 Packet Too Big message received (%" PRIuSIZE " bytes)...\r\n", length);
332  //Dump message contents for debugging purpose
333  icmpv6DumpPacketTooBigMessage(icmpHeader);
334 
335 #if (IPV6_PMTU_SUPPORT == ENABLED)
336  //Move to the beginning of the original IPv6 packet
337  offset += sizeof(Icmpv6PacketTooBigMessage);
339 
340  //Ensure the packet length is correct
341  if(length < sizeof(Ipv6Header))
342  return;
343 
344  //Point to the original IPv6 header
345  ipHeader = netBufferAt(buffer, offset);
346 
347  //Sanity check
348  if(ipHeader == NULL)
349  return;
350 
351  //The node uses the value in the MTU field in the Packet Too Big
352  //message as a tentative PMTU value
353  tentativePathMtu = ntohl(icmpHeader->mtu);
354 
355  //Update the PMTU for the specified destination address
356  ipv6UpdatePathMtu(interface, &ipHeader->destAddr, tentativePathMtu);
357 #endif
358 }
359 
360 
361 /**
362  * @brief Echo Request message processing
363  * @param[in] interface Underlying network interface
364  * @param[in] requestPseudoHeader IPv6 pseudo header
365  * @param[in] request Multi-part buffer containing the incoming ICMPv6 message
366  * @param[in] requestOffset Offset to the first byte of the ICMPv6 message
367  **/
368 
370  const Ipv6PseudoHeader *requestPseudoHeader, const NetBuffer *request,
371  size_t requestOffset)
372 {
373  error_t error;
374  size_t requestLength;
375  size_t replyOffset;
376  size_t replyLength;
377  NetBuffer *reply;
378  Icmpv6EchoMessage *requestHeader;
379  Icmpv6EchoMessage *replyHeader;
380  Ipv6PseudoHeader replyPseudoHeader;
381 
382  //Retrieve the length of the Echo Request message
383  requestLength = netBufferGetLength(request) - requestOffset;
384 
385  //Ensure the packet length is correct
386  if(requestLength < sizeof(Icmpv6EchoMessage))
387  return;
388 
389  //Point to the Echo Request header
390  requestHeader = netBufferAt(request, requestOffset);
391 
392  //Sanity check
393  if(requestHeader == NULL)
394  return;
395 
396  //Debug message
397  TRACE_INFO("ICMPv6 Echo Request message received (%" PRIuSIZE " bytes)...\r\n", requestLength);
398  //Dump message contents for debugging purpose
399  icmpv6DumpEchoMessage(requestHeader);
400 
401  //If support for Echo Request messages has been explicitly disabled, then
402  //the host shall not respond to the incoming request
403  if(!interface->ipv6Context.enableEchoReq)
404  return;
405 
406  //Check whether the destination address of the Echo Request message is
407  //a multicast address
408  if(ipv6IsMulticastAddr(&requestPseudoHeader->destAddr))
409  {
410  //If support for multicast Echo Request messages has been explicitly
411  //disabled, then the host shall not respond to the incoming request
412  if(!interface->ipv6Context.enableMulticastEchoReq)
413  return;
414 
415  //The source address of the reply must be a unicast address belonging to
416  //the interface on which the multicast Echo Request message was received
417  error = ipv6SelectSourceAddr(&interface, &requestPseudoHeader->srcAddr,
418  &replyPseudoHeader.srcAddr);
419  //Any error to report?
420  if(error)
421  return;
422  }
423  else
424  {
425  //The destination address of the Echo Request message is a unicast address
426  replyPseudoHeader.srcAddr = requestPseudoHeader->destAddr;
427  }
428 
429  //Allocate memory to hold the Echo Reply message
430  reply = ipAllocBuffer(sizeof(Icmpv6EchoMessage), &replyOffset);
431  //Failed to allocate memory?
432  if(reply == NULL)
433  return;
434 
435  //Point to the Echo Reply header
436  replyHeader = netBufferAt(reply, replyOffset);
437 
438  //Format Echo Reply header
439  replyHeader->type = ICMPV6_TYPE_ECHO_REPLY;
440  replyHeader->code = 0;
441  replyHeader->checksum = 0;
442  replyHeader->identifier = requestHeader->identifier;
443  replyHeader->sequenceNumber = requestHeader->sequenceNumber;
444 
445  //Point to the first data byte
446  requestOffset += sizeof(Icmpv6EchoMessage);
447  requestLength -= sizeof(Icmpv6EchoMessage);
448 
449  //The data received in the ICMPv6 Echo Request message must be returned
450  //entirely and unmodified in the ICMPv6 Echo Reply message
451  error = netBufferConcat(reply, request, requestOffset, requestLength);
452 
453  //Check status code
454  if(!error)
455  {
456  NetTxAncillary ancillary;
457 
458  //Get the length of the resulting message
459  replyLength = netBufferGetLength(reply) - replyOffset;
460 
461  //Format IPv6 pseudo header
462  replyPseudoHeader.destAddr = requestPseudoHeader->srcAddr;
463  replyPseudoHeader.length = htonl(replyLength);
464  replyPseudoHeader.reserved[0] = 0;
465  replyPseudoHeader.reserved[1] = 0;
466  replyPseudoHeader.reserved[2] = 0;
467  replyPseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
468 
469  //Message checksum calculation
470  replyHeader->checksum = ipCalcUpperLayerChecksumEx(&replyPseudoHeader,
471  sizeof(Ipv6PseudoHeader), reply, replyOffset, replyLength);
472 
473  //Total number of ICMP messages which this entity attempted to send
474  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
475  //Increment per-message type ICMP counter
476  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[ICMPV6_TYPE_ECHO_REPLY], 1);
477 
478  //Debug message
479  TRACE_INFO("Sending ICMPv6 Echo Reply message (%" PRIuSIZE " bytes)...\r\n", replyLength);
480  //Dump message contents for debugging purpose
481  icmpv6DumpEchoMessage(replyHeader);
482 
483  //Additional options can be passed to the stack along with the packet
484  ancillary = NET_DEFAULT_TX_ANCILLARY;
485 
486  //Send Echo Reply message
487  ipv6SendDatagram(interface, &replyPseudoHeader, reply, replyOffset,
488  &ancillary);
489  }
490 
491  //Free previously allocated memory block
492  netBufferFree(reply);
493 }
494 
495 
496 /**
497  * @brief Send an ICMPv6 Error message
498  * @param[in] interface Underlying network interface
499  * @param[in] type Message type
500  * @param[in] code Specific message code
501  * @param[in] parameter Specific message parameter
502  * @param[in] ipPacket Multi-part buffer that holds the invoking IPv6 packet
503  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
504  * @return Error code
505  **/
506 
508  uint8_t code, uint32_t parameter, const NetBuffer *ipPacket,
509  size_t ipPacketOffset)
510 {
511  error_t error;
512  size_t offset;
513  size_t length;
514  NetBuffer *icmpMessage;
515  Icmpv6ErrorMessage *icmpHeader;
516  Ipv6Header *ipHeader;
517  Ipv6PseudoHeader pseudoHeader;
518 
519  //Retrieve the length of the invoking IPv6 packet
520  length = netBufferGetLength(ipPacket) - ipPacketOffset;
521 
522  //Check the length of the IPv6 packet
523  if(length < sizeof(Ipv6Header))
524  return ERROR_INVALID_LENGTH;
525 
526  //Point to the header of the invoking packet
527  ipHeader = netBufferAt(ipPacket, ipPacketOffset);
528 
529  //Sanity check
530  if(ipHeader == NULL)
531  return ERROR_FAILURE;
532 
533  //Check the type of the invoking packet
534  if(ipHeader->nextHeader == IPV6_ICMPV6_HEADER)
535  {
536  //Make sure the ICMPv6 message is valid
537  if(length >= (sizeof(Ipv6Header) + sizeof(Icmpv6Header)))
538  {
539  //Point to the ICMPv6 header
540  icmpHeader = netBufferAt(ipPacket, ipPacketOffset + sizeof(Ipv6Header));
541 
542  //Sanity check
543  if(icmpHeader != NULL)
544  {
545  //An ICMPv6 error message must not be originated as a result
546  //of receiving an ICMPv6 error or redirect message
547  if(icmpHeader->type == ICMPV6_TYPE_DEST_UNREACHABLE ||
548  icmpHeader->type == ICMPV6_TYPE_PACKET_TOO_BIG ||
549  icmpHeader->type == ICMPV6_TYPE_TIME_EXCEEDED ||
550  icmpHeader->type == ICMPV6_TYPE_PARAM_PROBLEM ||
551  icmpHeader->type == ICMPV6_TYPE_REDIRECT)
552  {
553  //Do not send the ICMPv6 error message...
554  return ERROR_INVALID_TYPE;
555  }
556  }
557  }
558  }
559 
560  //An ICMPv6 error message must not be originated as a result of
561  //receiving a packet destined to an IPv6 multicast address
562  if(ipv6IsMulticastAddr(&ipHeader->destAddr))
563  {
564  //There are two exceptions to this rule
566  {
567  //The Packet Too Big Message to allow Path MTU discovery to
568  //work for IPv6 multicast
569  }
570  else if(type == ICMPV6_TYPE_PARAM_PROBLEM &&
572  {
573  //The Parameter Problem Message, reporting an unrecognized IPv6
574  //option that has the Option Type highest-order two bits set to 10
575  }
576  else
577  {
578  //Do not send the ICMPv6 error message...
579  return ERROR_INVALID_ADDRESS;
580  }
581  }
582 
583  //An ICMPv6 error message must not be originated as a result of receiving a
584  //packet whose source address does not uniquely identify a single node (e.g.
585  //the IPv6 unspecified address, an IPv6 multicast address, or an address
586  //known by the ICMPv6 message originator to be an IPv6 anycast address)
587  if(ipv6IsAnycastAddr(interface, &ipHeader->srcAddr))
588  return ERROR_INVALID_ADDRESS;
589 
590  //Return as much of invoking IPv6 packet as possible without the ICMPv6
591  //packet exceeding the minimum IPv6 MTU
593  sizeof(Icmpv6ErrorMessage));
594 
595  //Allocate a memory buffer to hold the ICMPv6 message
596  icmpMessage = ipAllocBuffer(sizeof(Icmpv6ErrorMessage), &offset);
597 
598  //Failed to allocate memory?
599  if(icmpMessage == NULL)
600  return ERROR_OUT_OF_MEMORY;
601 
602  //Point to the ICMPv6 header
603  icmpHeader = netBufferAt(icmpMessage, offset);
604 
605  //Format ICMPv6 Error message
606  icmpHeader->type = type;
607  icmpHeader->code = code;
608  icmpHeader->checksum = 0;
609  icmpHeader->parameter = htonl(parameter);
610 
611  //Copy incoming IPv6 packet contents
612  error = netBufferConcat(icmpMessage, ipPacket, ipPacketOffset, length);
613 
614  //Check status code
615  if(!error)
616  {
617  //Get the length of the resulting message
618  length = netBufferGetLength(icmpMessage) - offset;
619 
620  //Format IPv6 pseudo header
621  pseudoHeader.destAddr = ipHeader->srcAddr;
622  pseudoHeader.length = htonl(length);
623  pseudoHeader.reserved[0] = 0;
624  pseudoHeader.reserved[1] = 0;
625  pseudoHeader.reserved[2] = 0;
626  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
627 
628  //Select the relevant source address
629  error = ipv6SelectSourceAddr(&interface, &pseudoHeader.destAddr,
630  &pseudoHeader.srcAddr);
631 
632  //Check status code
633  if(!error)
634  {
635  NetTxAncillary ancillary;
636 
637  //Message checksum calculation
638  icmpHeader->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
639  sizeof(Ipv6PseudoHeader), icmpMessage, offset, length);
640 
641  //Total number of ICMP messages which this entity attempted to send
642  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
643  //Increment per-message type ICMP counter
644  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[type], 1);
645 
646  //Debug message
647  TRACE_INFO("Sending ICMPv6 Error message (%" PRIuSIZE " bytes)...\r\n", length);
648  //Dump message contents for debugging purpose
649  icmpv6DumpErrorMessage(icmpHeader);
650 
651  //Additional options can be passed to the stack along with the packet
652  ancillary = NET_DEFAULT_TX_ANCILLARY;
653 
654  //Send ICMPv6 Error message
655  error = ipv6SendDatagram(interface, &pseudoHeader, icmpMessage, offset,
656  &ancillary);
657  }
658  }
659 
660  //Free previously allocated memory
661  netBufferFree(icmpMessage);
662 
663  //Return status code
664  return error;
665 }
666 
667 
668 /**
669  * @brief Dump ICMPv6 message for debugging purpose
670  * @param[in] message Pointer to the ICMP message
671  **/
672 
674 {
675  //Dump ICMPv6 message
676  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
677  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
678  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
679 }
680 
681 
682 /**
683  * @brief Dump ICMPv6 Destination Unreachable message
684  * @param[in] message Pointer to the ICMPv6 message
685  **/
686 
688 {
689  //Dump ICMPv6 message
690  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
691  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
692  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
693 }
694 
695 
696 /**
697  * @brief Dump ICMPv6 Packet Too Big message
698  * @param[in] message Pointer to the ICMPv6 message
699  **/
700 
702 {
703  //Dump ICMPv6 message
704  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
705  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
706  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
707  TRACE_DEBUG(" MTU = %" PRIu32 "\r\n", ntohl(message->mtu));
708 }
709 
710 
711 /**
712  * @brief Dump ICMPv6 Echo Request or Echo Reply message
713  * @param[in] message Pointer to the ICMPv6 message
714  **/
715 
717 {
718  //Dump ICMPv6 message
719  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
720  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
721  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
722  TRACE_DEBUG(" Identifier = 0x%04" PRIX16 "\r\n", ntohs(message->identifier));
723  TRACE_DEBUG(" Sequence Number = 0x%04" PRIX16 "\r\n", ntohs(message->sequenceNumber));
724 }
725 
726 
727 /**
728  * @brief Dump generic ICMPv6 Error message
729  * @param[in] message Pointer to the ICMPv6 message
730  **/
731 
733 {
734  //Dump ICMP message
735  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
736  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
737  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
738  TRACE_DEBUG(" Parameter = %" PRIu32 "\r\n", ntohl(message->parameter));
739 }
740 
741 #endif
uint8_t message[]
Definition: chap.h:154
uint8_t type
Definition: coap_common.h:176
uint8_t code
Definition: coap_common.h:179
#define PRIuSIZE
int bool_t
Definition: compiler_port.h:53
#define ntohl(value)
Definition: cpu_endian.h:422
#define htonl(value)
Definition: cpu_endian.h:414
#define ntohs(value)
Definition: cpu_endian.h:421
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_WARNING(...)
Definition: debug.h:85
#define TRACE_INFO(...)
Definition: debug.h:95
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ ERROR_INVALID_TYPE
Definition: error.h:115
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint8_t parameter
Definition: icmp.h:125
void icmpv6ProcessMessage(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Incoming ICMPv6 message processing.
Definition: icmpv6.c:123
void icmpv6DumpMessage(const Icmpv6Header *message)
Dump ICMPv6 message for debugging purpose.
Definition: icmpv6.c:673
void icmpv6ProcessPacketTooBig(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Packet Too Big message processing.
Definition: icmpv6.c:304
void icmpv6ProcessDestUnreachable(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Destination Unreachable message processing.
Definition: icmpv6.c:268
void icmpv6DumpErrorMessage(const Icmpv6ErrorMessage *message)
Dump generic ICMPv6 Error message.
Definition: icmpv6.c:732
void icmpv6ProcessEchoRequest(NetInterface *interface, const Ipv6PseudoHeader *requestPseudoHeader, const NetBuffer *request, size_t requestOffset)
Echo Request message processing.
Definition: icmpv6.c:369
error_t icmpv6EnableMulticastEchoRequests(NetInterface *interface, bool_t enable)
Enable support for multicast ICMPv6 Echo Request messages.
Definition: icmpv6.c:95
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:507
error_t icmpv6EnableEchoRequests(NetInterface *interface, bool_t enable)
Enable support for ICMPv6 Echo Request messages.
Definition: icmpv6.c:67
void icmpv6DumpDestUnreachableMessage(const Icmpv6DestUnreachableMessage *message)
Dump ICMPv6 Destination Unreachable message.
Definition: icmpv6.c:687
void icmpv6DumpEchoMessage(const Icmpv6EchoMessage *message)
Dump ICMPv6 Echo Request or Echo Reply message.
Definition: icmpv6.c:716
void icmpv6DumpPacketTooBigMessage(const Icmpv6PacketTooBigMessage *message)
Dump ICMPv6 Packet Too Big message.
Definition: icmpv6.c:701
ICMPv6 (Internet Control Message Protocol Version 6)
Icmpv6DestUnreachableMessage
Definition: icmpv6.h:158
Icmpv6ErrorMessage
Definition: icmpv6.h:139
Icmpv6PacketTooBigMessage
Definition: icmpv6.h:177
@ ICMPV6_TYPE_NEIGHBOR_SOL
Definition: icmpv6.h:64
@ ICMPV6_TYPE_DEST_UNREACHABLE
Definition: icmpv6.h:53
@ ICMPV6_TYPE_ROUTER_ADV
Definition: icmpv6.h:63
@ ICMPV6_TYPE_PACKET_TOO_BIG
Definition: icmpv6.h:54
@ ICMPV6_TYPE_REDIRECT
Definition: icmpv6.h:66
@ ICMPV6_TYPE_NEIGHBOR_ADV
Definition: icmpv6.h:65
@ ICMPV6_TYPE_TIME_EXCEEDED
Definition: icmpv6.h:55
@ ICMPV6_TYPE_MULTICAST_LISTENER_QUERY
Definition: icmpv6.h:59
@ ICMPV6_TYPE_MULTICAST_LISTENER_REPORT_V1
Definition: icmpv6.h:60
@ ICMPV6_TYPE_ROUTER_SOL
Definition: icmpv6.h:62
@ ICMPV6_TYPE_ECHO_REQUEST
Definition: icmpv6.h:57
@ ICMPV6_TYPE_PARAM_PROBLEM
Definition: icmpv6.h:56
@ ICMPV6_TYPE_ECHO_REPLY
Definition: icmpv6.h:58
@ ICMPV6_CODE_UNKNOWN_IPV6_OPTION
Definition: icmpv6.h:103
Icmpv6Header
Definition: icmpv6.h:125
Icmpv6EchoMessage
Definition: icmpv6.h:233
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:744
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:719
IPv4 and IPv6 common routines.
IP MIB module.
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
error_t ipv6SendDatagram(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 datagram.
Definition: ipv6.c:1667
IPv6 (Internet Protocol Version 6)
uint8_t hopLimit
Definition: ipv6.h:274
#define IPV6_DEFAULT_MTU
Definition: ipv6.h:108
@ IPV6_ICMPV6_HEADER
Definition: ipv6.h:186
#define Ipv6PseudoHeader
Definition: ipv6.h:42
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:132
#define Ipv6Header
Definition: ipv6.h:36
error_t ipv6SelectSourceAddr(NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:895
bool_t ipv6IsAnycastAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is an anycast address.
Definition: ipv6_misc.c:1089
bool_t ipv6IsTentativeAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is a tentative address.
Definition: ipv6_misc.c:1125
Helper functions for IPv6.
void ipv6UpdatePathMtu(NetInterface *interface, const Ipv6Addr *destAddr, size_t tentativePathMtu)
Update the PMTU for the specified path.
Definition: ipv6_pmtu.c:93
Path MTU Discovery for IPv6.
void mldProcessListenerQuery(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Process incoming Multicast Listener Query message.
Definition: mld.c:268
void mldProcessListenerReport(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Process incoming Multicast Listener Report message.
Definition: mld.c:372
MLD (Multicast Listener Discovery for IPv6)
void ndpProcessNeighborSol(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Neighbor Solicitation message processing.
Definition: ndp.c:867
void ndpProcessRedirect(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Redirect message processing.
Definition: ndp.c:1359
void ndpProcessNeighborAdv(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Neighbor Advertisement message processing.
Definition: ndp.c:1112
void ndpProcessRouterAdv(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Router Advertisement message processing.
Definition: ndp.c:578
NDP (Neighbor Discovery Protocol)
uint8_t ipPacket[]
Definition: ndp.h:431
void ndpProcessRouterSol(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Router Solicitation message processing.
Helper functions for router advertisement service.
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netMutex
Definition: net_legacy.h:195
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:415
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
error_t netBufferConcat(NetBuffer *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Concatenate two multi-part buffers.
Definition: net_mem.c:444
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:71
#define NetTxAncillary
Definition: net_misc.h:36
#define MIN(a, b)
Definition: os_port.h:63
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint8_t length
Definition: tcp.h:368