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-2019 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 1.9.6
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"
51 #include "ipv6/ndp_router_adv.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 multicast 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  * multicast Echo Requests. When the flag is set to FALSE, incoming Echo
64  * Request messages destined to a multicast address 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 multicast Echo Request messages
77  interface->ipv6Context.enableMulticastEchoReq = enable;
78  //Release exclusive access
80 
81  //Successful processing
82  return NO_ERROR;
83 }
84 
85 
86 /**
87  * @brief Incoming ICMPv6 message processing
88  * @param[in] interface Underlying network interface
89  * @param[in] pseudoHeader IPv6 pseudo header
90  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
91  * @param[in] offset Offset to the first byte of the ICMPv6 message
92  * @param[in] hopLimit Hop Limit field from IPv6 header
93  **/
94 
95 void icmpv6ProcessMessage(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader,
96  const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
97 {
98  size_t length;
99  Icmpv6Header *header;
100 
101  //Total number of ICMP messages which the entity received
102  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsInMsgs, 1);
103 
104  //Retrieve the length of the ICMPv6 message
105  length = netBufferGetLength(buffer) - offset;
106 
107  //Ensure the message length is correct
108  if(length < sizeof(Icmpv6Header))
109  {
110  //Number of ICMP messages which the entity received but determined
111  //as having ICMP-specific errors
112  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsInErrors, 1);
113 
114  //Silently discard incoming message
115  return;
116  }
117 
118  //Point to the ICMPv6 message header
119  header = netBufferAt(buffer, offset);
120 
121  //Sanity check
122  if(header == NULL)
123  return;
124 
125  //Debug message
126  TRACE_INFO("ICMPv6 message received (%" PRIuSIZE " bytes)...\r\n", length);
127  //Dump message contents for debugging purpose
128  icmpv6DumpMessage(header);
129 
130  //Verify checksum value
131  if(ipCalcUpperLayerChecksumEx(pseudoHeader,
132  sizeof(Ipv6PseudoHeader), buffer, offset, length) != 0x0000)
133  {
134  //Debug message
135  TRACE_WARNING("Wrong ICMPv6 header checksum!\r\n");
136 
137  //Number of ICMP messages which the entity received but determined
138  //as having ICMP-specific errors
139  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsInErrors, 1);
140 
141  //Exit immediately
142  return;
143  }
144 
145  //Check whether the destination address is the tentative address
146  if(ipv6IsTentativeAddr(interface, &pseudoHeader->destAddr))
147  {
148  //The interface must accept Neighbor Solicitation and
149  //Neighbor Advertisement messages
150  if(header->type != ICMPV6_TYPE_NEIGHBOR_SOL &&
151  header->type != ICMPV6_TYPE_NEIGHBOR_ADV)
152  {
153  //Other packets addressed to the tentative address
154  //should be silently discarded
155  return;
156  }
157  }
158 
159  //Increment per-message type ICMP counter
160  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsInPkts[header->type], 1);
161 
162  //Check the type of message
163  switch(header->type)
164  {
165  //Destination Unreachable message?
167  //Process Destination Unreachable message
168  icmpv6ProcessDestUnreachable(interface, pseudoHeader, buffer, offset);
169  break;
170  //Packet Too Big message?
172  //Process Packet Too Big message
173  icmpv6ProcessPacketTooBig(interface, pseudoHeader, buffer, offset);
174  break;
175  //Echo Request message?
177  //Process Echo Request message
178  icmpv6ProcessEchoRequest(interface, pseudoHeader, buffer, offset);
179  break;
180 #if (MLD_SUPPORT == ENABLED)
181  //Multicast Listener Query message?
183  //Process Multicast Listener Query message
184  mldProcessListenerQuery(interface, pseudoHeader, buffer, offset, hopLimit);
185  break;
186  //Version 1 Multicast Listener Report message?
188  //Process Version 1 Multicast Listener Report message
189  mldProcessListenerReport(interface, pseudoHeader, buffer, offset, hopLimit);
190  break;
191 #endif
192 #if (NDP_ROUTER_ADV_SUPPORT == ENABLED)
193  //Router Solicitation message?
195  //Process Router Solicitation message
196  ndpProcessRouterSol(interface, pseudoHeader, buffer, offset, hopLimit);
197  break;
198 #endif
199 #if (NDP_SUPPORT == ENABLED)
200  //Router Advertisement message?
202  //Process Router Advertisement message
203  ndpProcessRouterAdv(interface, pseudoHeader, buffer, offset, hopLimit);
204  break;
205  //Neighbor Solicitation message?
207  //Process Neighbor Solicitation message
208  ndpProcessNeighborSol(interface, pseudoHeader, buffer, offset, hopLimit);
209  break;
210  //Neighbor Advertisement message?
212  //Process Neighbor Advertisement message
213  ndpProcessNeighborAdv(interface, pseudoHeader, buffer, offset, hopLimit);
214  break;
215  //Redirect message?
217  //Process Redirect message
218  ndpProcessRedirect(interface, pseudoHeader, buffer, offset, hopLimit);
219  break;
220 #endif
221  //Unknown type?
222  default:
223  //Debug message
224  TRACE_WARNING("Unknown ICMPv6 message type!\r\n");
225  //Discard incoming ICMPv6 message
226  break;
227  }
228 }
229 
230 
231 /**
232  * @brief Destination Unreachable message processing
233  * @param[in] interface Underlying network interface
234  * @param[in] pseudoHeader IPv6 pseudo header
235  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
236  * @param[in] offset Offset to the first byte of the ICMPv6 message
237  **/
238 
240  Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
241 {
242  size_t length;
243  Icmpv6DestUnreachableMessage *icmpHeader;
244 
245  //Retrieve the length of the Destination Unreachable message
246  length = netBufferGetLength(buffer) - offset;
247 
248  //Ensure the packet length is correct
250  return;
251 
252  //Point to the ICMPv6 header
253  icmpHeader = netBufferAt(buffer, offset);
254 
255  //Sanity check
256  if(icmpHeader == NULL)
257  return;
258 
259  //Debug message
260  TRACE_INFO("ICMPv6 Destination Unreachable message received (%" PRIuSIZE " bytes)...\r\n", length);
261  //Dump message contents for debugging purpose
263 }
264 
265 
266 /**
267  * @brief Packet Too Big message processing
268  * @param[in] interface Underlying network interface
269  * @param[in] pseudoHeader IPv6 pseudo header
270  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
271  * @param[in] offset Offset to the first byte of the ICMPv6 message
272  **/
273 
275  Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
276 {
277  size_t length;
278  Icmpv6PacketTooBigMessage *icmpHeader;
279 
280 #if (IPV6_PMTU_SUPPORT == ENABLED)
281  uint32_t tentativePathMtu;
282  Ipv6Header *ipHeader;
283 #endif
284 
285  //Retrieve the length of the Packet Too Big message
286  length = netBufferGetLength(buffer) - offset;
287 
288  //Ensure the packet length is correct
289  if(length < sizeof(Icmpv6PacketTooBigMessage))
290  return;
291 
292  //Point to the ICMPv6 header
293  icmpHeader = netBufferAt(buffer, offset);
294 
295  //Sanity check
296  if(icmpHeader == NULL)
297  return;
298 
299  //Debug message
300  TRACE_INFO("ICMPv6 Packet Too Big message received (%" PRIuSIZE " bytes)...\r\n", length);
301  //Dump message contents for debugging purpose
302  icmpv6DumpPacketTooBigMessage(icmpHeader);
303 
304 #if (IPV6_PMTU_SUPPORT == ENABLED)
305  //Move to the beginning of the original IPv6 packet
306  offset += sizeof(Icmpv6PacketTooBigMessage);
308 
309  //Ensure the packet length is correct
310  if(length < sizeof(Ipv6Header))
311  return;
312 
313  //Point to the original IPv6 header
314  ipHeader = netBufferAt(buffer, offset);
315 
316  //Sanity check
317  if(ipHeader == NULL)
318  return;
319 
320  //The node uses the value in the MTU field in the Packet Too Big
321  //message as a tentative PMTU value
322  tentativePathMtu = ntohl(icmpHeader->mtu);
323 
324  //Update the PMTU for the specified destination address
325  ipv6UpdatePathMtu(interface, &ipHeader->destAddr, tentativePathMtu);
326 #endif
327 }
328 
329 
330 /**
331  * @brief Echo Request message processing
332  * @param[in] interface Underlying network interface
333  * @param[in] requestPseudoHeader IPv6 pseudo header
334  * @param[in] request Multi-part buffer containing the incoming ICMPv6 message
335  * @param[in] requestOffset Offset to the first byte of the ICMPv6 message
336  **/
337 
338 void icmpv6ProcessEchoRequest(NetInterface *interface, Ipv6PseudoHeader *requestPseudoHeader,
339  const NetBuffer *request, size_t requestOffset)
340 {
341  error_t error;
342  size_t requestLength;
343  size_t replyOffset;
344  size_t replyLength;
345  NetBuffer *reply;
346  Icmpv6EchoMessage *requestHeader;
347  Icmpv6EchoMessage *replyHeader;
348  Ipv6PseudoHeader replyPseudoHeader;
349 
350  //Retrieve the length of the Echo Request message
351  requestLength = netBufferGetLength(request) - requestOffset;
352 
353  //Ensure the packet length is correct
354  if(requestLength < sizeof(Icmpv6EchoMessage))
355  return;
356 
357  //Point to the Echo Request header
358  requestHeader = netBufferAt(request, requestOffset);
359 
360  //Sanity check
361  if(requestHeader == NULL)
362  return;
363 
364  //Debug message
365  TRACE_INFO("ICMPv6 Echo Request message received (%" PRIuSIZE " bytes)...\r\n", requestLength);
366  //Dump message contents for debugging purpose
367  icmpv6DumpEchoMessage(requestHeader);
368 
369  //Check whether the destination address of the Echo Request message is
370  //a multicast address
371  if(ipv6IsMulticastAddr(&requestPseudoHeader->destAddr))
372  {
373  //If support for multicast Echo Request messages has been explicitly
374  //disabled, then the host shall not respond to the incoming request
375  if(!interface->ipv6Context.enableMulticastEchoReq)
376  return;
377 
378  //The source address of the reply must be a unicast address belonging to
379  //the interface on which the multicast Echo Request message was received
380  error = ipv6SelectSourceAddr(&interface, &requestPseudoHeader->srcAddr,
381  &replyPseudoHeader.srcAddr);
382  //Any error to report?
383  if(error)
384  return;
385  }
386  else
387  {
388  //The destination address of the Echo Request message is a unicast address
389  replyPseudoHeader.srcAddr = requestPseudoHeader->destAddr;
390  }
391 
392  //Allocate memory to hold the Echo Reply message
393  reply = ipAllocBuffer(sizeof(Icmpv6EchoMessage), &replyOffset);
394  //Failed to allocate memory?
395  if(reply == NULL)
396  return;
397 
398  //Point to the Echo Reply header
399  replyHeader = netBufferAt(reply, replyOffset);
400 
401  //Format Echo Reply header
402  replyHeader->type = ICMPV6_TYPE_ECHO_REPLY;
403  replyHeader->code = 0;
404  replyHeader->checksum = 0;
405  replyHeader->identifier = requestHeader->identifier;
406  replyHeader->sequenceNumber = requestHeader->sequenceNumber;
407 
408  //Point to the first data byte
409  requestOffset += sizeof(Icmpv6EchoMessage);
410  requestLength -= sizeof(Icmpv6EchoMessage);
411 
412  //The data received in the ICMPv6 Echo Request message must be returned
413  //entirely and unmodified in the ICMPv6 Echo Reply message
414  error = netBufferConcat(reply, request, requestOffset, requestLength);
415 
416  //Check status code
417  if(!error)
418  {
419  //Get the length of the resulting message
420  replyLength = netBufferGetLength(reply) - replyOffset;
421 
422  //Format IPv6 pseudo header
423  replyPseudoHeader.destAddr = requestPseudoHeader->srcAddr;
424  replyPseudoHeader.length = htonl(replyLength);
425  replyPseudoHeader.reserved = 0;
426  replyPseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
427 
428  //Message checksum calculation
429  replyHeader->checksum = ipCalcUpperLayerChecksumEx(&replyPseudoHeader,
430  sizeof(Ipv6PseudoHeader), reply, replyOffset, replyLength);
431 
432  //Total number of ICMP messages which this entity attempted to send
433  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
434  //Increment per-message type ICMP counter
435  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[ICMPV6_TYPE_ECHO_REPLY], 1);
436 
437  //Debug message
438  TRACE_INFO("Sending ICMPv6 Echo Reply message (%" PRIuSIZE " bytes)...\r\n", replyLength);
439  //Dump message contents for debugging purpose
440  icmpv6DumpEchoMessage(replyHeader);
441 
442  //Send Echo Reply message
443  ipv6SendDatagram(interface, &replyPseudoHeader, reply, replyOffset, 0);
444  }
445 
446  //Free previously allocated memory block
447  netBufferFree(reply);
448 }
449 
450 
451 /**
452  * @brief Send an ICMPv6 Error message
453  * @param[in] interface Underlying network interface
454  * @param[in] type Message type
455  * @param[in] code Specific message code
456  * @param[in] parameter Specific message parameter
457  * @param[in] ipPacket Multi-part buffer that holds the invoking IPv6 packet
458  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
459  * @return Error code
460  **/
461 
462 error_t icmpv6SendErrorMessage(NetInterface *interface, uint8_t type, uint8_t code,
463  uint32_t parameter, const NetBuffer *ipPacket, size_t ipPacketOffset)
464 {
465  error_t error;
466  size_t offset;
467  size_t length;
468  NetBuffer *icmpMessage;
469  Icmpv6ErrorMessage *icmpHeader;
470  Ipv6Header *ipHeader;
471  Ipv6PseudoHeader pseudoHeader;
472 
473  //Retrieve the length of the invoking IPv6 packet
474  length = netBufferGetLength(ipPacket) - ipPacketOffset;
475 
476  //Check the length of the IPv6 packet
477  if(length < sizeof(Ipv6Header))
478  return ERROR_INVALID_LENGTH;
479 
480  //Point to the header of the invoking packet
481  ipHeader = netBufferAt(ipPacket, ipPacketOffset);
482 
483  //Sanity check
484  if(ipHeader == NULL)
485  return ERROR_FAILURE;
486 
487  //Check the type of the invoking packet
488  if(ipHeader->nextHeader == IPV6_ICMPV6_HEADER)
489  {
490  //Make sure the ICMPv6 message is valid
491  if(length >= (sizeof(Ipv6Header) + sizeof(Icmpv6Header)))
492  {
493  //Point to the ICMPv6 header
494  icmpHeader = netBufferAt(ipPacket, ipPacketOffset + sizeof(Ipv6Header));
495 
496  //Sanity check
497  if(icmpHeader != NULL)
498  {
499  //An ICMPv6 error message must not be originated as a result
500  //of receiving an ICMPv6 error or redirect message
501  if(icmpHeader->type == ICMPV6_TYPE_DEST_UNREACHABLE ||
502  icmpHeader->type == ICMPV6_TYPE_PACKET_TOO_BIG ||
503  icmpHeader->type == ICMPV6_TYPE_TIME_EXCEEDED ||
504  icmpHeader->type == ICMPV6_TYPE_PARAM_PROBLEM ||
505  icmpHeader->type == ICMPV6_TYPE_REDIRECT)
506  {
507  //Do not send the ICMPv6 error message...
508  return ERROR_INVALID_TYPE;
509  }
510  }
511  }
512  }
513 
514  //An ICMPv6 error message must not be originated as a result of
515  //receiving a packet destined to an IPv6 multicast address
516  if(ipv6IsMulticastAddr(&ipHeader->destAddr))
517  {
518  //There are two exceptions to this rule
520  {
521  //The Packet Too Big Message to allow Path MTU discovery to
522  //work for IPv6 multicast
523  }
524  else if(type == ICMPV6_TYPE_PARAM_PROBLEM &&
526  {
527  //The Parameter Problem Message, reporting an unrecognized IPv6
528  //option that has the Option Type highest-order two bits set to 10
529  }
530  else
531  {
532  //Do not send the ICMPv6 error message...
533  return ERROR_INVALID_ADDRESS;
534  }
535  }
536 
537  //An ICMPv6 error message must not be originated as a result of receiving a
538  //packet whose source address does not uniquely identify a single node (e.g.
539  //the IPv6 unspecified address, an IPv6 multicast address, or an address
540  //known by the ICMPv6 message originator to be an IPv6 anycast address)
541  if(ipv6IsAnycastAddr(interface, &ipHeader->srcAddr))
542  return ERROR_INVALID_ADDRESS;
543 
544  //Return as much of invoking IPv6 packet as possible without
545  //the ICMPv6 packet exceeding the minimum IPv6 MTU
547  sizeof(Ipv6Header) - sizeof(Icmpv6ErrorMessage));
548 
549  //Allocate a memory buffer to hold the ICMPv6 message
550  icmpMessage = ipAllocBuffer(sizeof(Icmpv6ErrorMessage), &offset);
551 
552  //Failed to allocate memory?
553  if(icmpMessage == NULL)
554  return ERROR_OUT_OF_MEMORY;
555 
556  //Point to the ICMPv6 header
557  icmpHeader = netBufferAt(icmpMessage, offset);
558 
559  //Format ICMPv6 Error message
560  icmpHeader->type = type;
561  icmpHeader->code = code;
562  icmpHeader->checksum = 0;
563  icmpHeader->parameter = htonl(parameter);
564 
565  //Copy incoming IPv6 packet contents
566  error = netBufferConcat(icmpMessage, ipPacket, ipPacketOffset, length);
567 
568  //Check status code
569  if(!error)
570  {
571  //Get the length of the resulting message
572  length = netBufferGetLength(icmpMessage) - offset;
573 
574  //Format IPv6 pseudo header
575  pseudoHeader.destAddr = ipHeader->srcAddr;
576  pseudoHeader.length = htonl(length);
577  pseudoHeader.reserved = 0;
578  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
579 
580  //Select the relevant source address
581  error = ipv6SelectSourceAddr(&interface, &pseudoHeader.destAddr,
582  &pseudoHeader.srcAddr);
583 
584  //Check status code
585  if(!error)
586  {
587  //Message checksum calculation
588  icmpHeader->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
589  sizeof(Ipv6PseudoHeader), icmpMessage, offset, length);
590 
591  //Total number of ICMP messages which this entity attempted to send
592  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
593  //Increment per-message type ICMP counter
594  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[type], 1);
595 
596  //Debug message
597  TRACE_INFO("Sending ICMPv6 Error message (%" PRIuSIZE " bytes)...\r\n", length);
598  //Dump message contents for debugging purpose
599  icmpv6DumpErrorMessage(icmpHeader);
600 
601  //Send ICMPv6 Error message
602  error = ipv6SendDatagram(interface, &pseudoHeader, icmpMessage, offset, 0);
603  }
604  }
605 
606  //Free previously allocated memory
607  netBufferFree(icmpMessage);
608 
609  //Return status code
610  return error;
611 }
612 
613 
614 /**
615  * @brief Dump ICMPv6 message for debugging purpose
616  * @param[in] message Pointer to the ICMP message
617  **/
618 
620 {
621  //Dump ICMPv6 message
622  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
623  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
624  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
625 }
626 
627 
628 /**
629  * @brief Dump ICMPv6 Destination Unreachable message
630  * @param[in] message Pointer to the ICMPv6 message
631  **/
632 
634 {
635  //Dump ICMPv6 message
636  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
637  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
638  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
639 }
640 
641 
642 /**
643  * @brief Dump ICMPv6 Packet Too Big message
644  * @param[in] message Pointer to the ICMPv6 message
645  **/
646 
648 {
649  //Dump ICMPv6 message
650  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
651  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
652  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
653  TRACE_DEBUG(" MTU = %" PRIu32 "\r\n", ntohl(message->mtu));
654 }
655 
656 
657 /**
658  * @brief Dump ICMPv6 Echo Request or Echo Reply message
659  * @param[in] message Pointer to the ICMPv6 message
660  **/
661 
663 {
664  //Dump ICMPv6 message
665  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
666  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
667  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
668  TRACE_DEBUG(" Identifier = 0x%04" PRIX16 "\r\n", ntohs(message->identifier));
669  TRACE_DEBUG(" Sequence Number = 0x%04" PRIX16 "\r\n", ntohs(message->sequenceNumber));
670 }
671 
672 
673 /**
674  * @brief Dump generic ICMPv6 Error message
675  * @param[in] message Pointer to the ICMPv6 message
676  **/
677 
679 {
680  //Dump ICMP message
681  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
682  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
683  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
684  TRACE_DEBUG(" Parameter = %" PRIu32 "\r\n", ntohl(message->parameter));
685 }
686 
687 #endif
void ndpProcessNeighborSol(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Neighbor Solicitation message processing.
Definition: ndp.c:685
IPv6 (Internet Protocol Version 6)
uint8_t length
Definition: dtls_misc.h:149
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:637
uint8_t code
Definition: coap_common.h:181
int bool_t
Definition: compiler_port.h:49
void icmpv6DumpEchoMessage(const Icmpv6EchoMessage *message)
Dump ICMPv6 Echo Request or Echo Reply message.
Definition: icmpv6.c:662
void icmpv6DumpErrorMessage(const Icmpv6ErrorMessage *message)
Dump generic ICMPv6 Error message.
Definition: icmpv6.c:678
void icmpv6DumpPacketTooBigMessage(const Icmpv6PacketTooBigMessage *message)
Dump ICMPv6 Packet Too Big message.
Definition: icmpv6.c:647
#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:338
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define Ipv6Header
Definition: ipv6.h:36
error_t ipv6SendDatagram(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, uint_t flags)
Send an IPv6 datagram.
Definition: ipv6.c:1576
bool_t ipv6IsTentativeAddr(NetInterface *interface, const Ipv6Addr *ipAddr)
Check whether an IPv6 address is a tentative address.
Definition: ipv6_misc.c:1112
void ndpProcessRouterSol(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Router Solicitation message processing.
void ipv6UpdatePathMtu(NetInterface *interface, const Ipv6Addr *destAddr, size_t tentativePathMtu)
Update the PMTU for the specified path.
Definition: ipv6_pmtu.c:93
void icmpv6DumpDestUnreachableMessage(const Icmpv6DestUnreachableMessage *message)
Dump ICMPv6 Destination Unreachable message.
Definition: icmpv6.c:633
__start_packed struct @173 Icmpv6ErrorMessage
ICMPv6 Error message.
void icmpv6ProcessMessage(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Incoming ICMPv6 message processing.
Definition: icmpv6.c:95
Router advertisement service.
uint8_t ipPacket[]
Definition: ndp.h:430
uint32_t parameter
Definition: icmp.h:123
error_t netBufferConcat(NetBuffer *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Concatenate two multi-part buffers.
Definition: net_mem.c:442
#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:462
void ndpProcessRouterAdv(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Router Advertisement message processing.
Definition: ndp.c:403
ICMPv6 (Internet Control Message Protocol Version 6)
Invalid parameter.
Definition: error.h:47
#define htonl(value)
Definition: cpu_endian.h:393
char_t type
error_t
Error codes.
Definition: error.h:42
void icmpv6ProcessDestUnreachable(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
Destination Unreachable message processing.
Definition: icmpv6.c:239
#define Ipv6PseudoHeader
Definition: ipv6.h:42
error_t ipv6SelectSourceAddr(NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:882
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:413
Generic error code.
Definition: error.h:45
void icmpv6DumpMessage(const Icmpv6Header *message)
Dump ICMPv6 message for debugging purpose.
Definition: icmpv6.c:619
__start_packed struct @172 Icmpv6Header
ICMPv6 header.
#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:68
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
Helper functions for IPv6.
OsMutex netMutex
Definition: net.c:75
#define TRACE_INFO(...)
Definition: debug.h:94
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:274
#define MIN(a, b)
Definition: os_port.h:62
Path MTU Discovery for IPv6.
NDP (Neighbor Discovery Protocol)
#define ntohs(value)
Definition: cpu_endian.h:398
#define TRACE_WARNING(...)
Definition: debug.h:84
#define TRACE_DEBUG(...)
Definition: debug.h:106
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:612
#define IPV6_DEFAULT_MTU
Definition: ipv6.h:109
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
IP MIB module.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
__start_packed struct @178 Icmpv6EchoMessage
ICMPv6 Echo Request and Echo Reply messages.
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:1076
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:919
void ndpProcessRedirect(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Redirect message processing.
Definition: ndp.c:1166
#define PRIuSIZE
Definition: compiler_port.h:78
__start_packed struct @174 Icmpv6DestUnreachableMessage
ICMPv6 Destination Unreachable message.
TCP/IP stack core.
__start_packed struct @175 Icmpv6PacketTooBigMessage
ICMPv6 Packet Too Big message.
#define ntohl(value)
Definition: cpu_endian.h:399
Success.
Definition: error.h:44
Debugging facilities.
MLD (Multicast Listener Discovery for IPv6)