Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers icmpv6.c Source File

icmpv6.c

Go to the documentation of this file.
00001 /**
00002  * @file icmpv6.c
00003  * @brief ICMPv6 (Internet Control Message Protocol Version 6)
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @section Description
00026  *
00027  * ICMPv6 is used by IPv6 nodes to report errors encountered in
00028  * processing packets, and to perform other Internet-layer functions.
00029  * ICMPv6 is an integral part of IPv6 and must be fully implemented
00030  * by every IPv6 node. Refer to the RFC 2463 for more details
00031  *
00032  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00033  * @version 1.7.6
00034  **/
00035 
00036 //Switch to the appropriate trace level
00037 #define TRACE_LEVEL ICMPV6_TRACE_LEVEL
00038 
00039 //Dependencies
00040 #include <string.h>
00041 #include "core/net.h"
00042 #include "core/ip.h"
00043 #include "ipv6/ipv6.h"
00044 #include "ipv6/ipv6_misc.h"
00045 #include "ipv6/ipv6_pmtu.h"
00046 #include "ipv6/icmpv6.h"
00047 #include "ipv6/mld.h"
00048 #include "ipv6/ndp.h"
00049 #include "ipv6/ndp_router_adv.h"
00050 #include "debug.h"
00051 
00052 //Check TCP/IP stack configuration
00053 #if (IPV6_SUPPORT == ENABLED)
00054 
00055 
00056 /**
00057  * @brief Enable support for multicast Echo Request messages
00058  * @param[in] interface Underlying network interface
00059  * @param[in] enable When the flag is set to TRUE, the host will respond to
00060  *   multicast Echo Requests. When the flag is set to FALSE, incoming Echo
00061  *   Request messages destined to a multicast address will be dropped
00062  * @return Error code
00063  **/
00064 
00065 error_t icmpv6EnableMulticastEchoRequest(NetInterface *interface, bool_t enable)
00066 {
00067    //Check parameters
00068    if(interface == NULL)
00069       return ERROR_INVALID_PARAMETER;
00070 
00071    //Get exclusive access
00072    osAcquireMutex(&netMutex);
00073    //Enable or disable support for multicast Echo Request messages
00074    interface->ipv6Context.enableMulticastEchoReq = enable;
00075    //Release exclusive access
00076    osReleaseMutex(&netMutex);
00077 
00078    //Successful processing
00079    return NO_ERROR;
00080 }
00081 
00082 
00083 /**
00084  * @brief Incoming ICMPv6 message processing
00085  * @param[in] interface Underlying network interface
00086  * @param[in] pseudoHeader IPv6 pseudo header
00087  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
00088  * @param[in] offset Offset to the first byte of the ICMPv6 message
00089  * @param[in] hopLimit Hop Limit field from IPv6 header
00090  **/
00091 
00092 void icmpv6ProcessMessage(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader,
00093    const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
00094 {
00095    size_t length;
00096    Icmpv6Header *header;
00097 
00098    //Retrieve the length of the ICMPv6 message
00099    length = netBufferGetLength(buffer) - offset;
00100 
00101    //Ensure the message length is correct
00102    if(length < sizeof(Icmpv6Header))
00103    {
00104       //Debug message
00105       TRACE_WARNING("ICMPv6 message length is invalid!\r\n");
00106       //Exit immediately
00107       return;
00108    }
00109 
00110    //Point to the ICMPv6 message header
00111    header = netBufferAt(buffer, offset);
00112 
00113    //Sanity check
00114    if(header == NULL)
00115       return;
00116 
00117    //Debug message
00118    TRACE_INFO("ICMPv6 message received (%" PRIuSIZE " bytes)...\r\n", length);
00119    //Dump message contents for debugging purpose
00120    icmpv6DumpMessage(header);
00121 
00122    //Verify checksum value
00123    if(ipCalcUpperLayerChecksumEx(pseudoHeader,
00124       sizeof(Ipv6PseudoHeader), buffer, offset, length) != 0x0000)
00125    {
00126       //Debug message
00127       TRACE_WARNING("Wrong ICMPv6 header checksum!\r\n");
00128       //Exit immediately
00129       return;
00130    }
00131 
00132    //Check whether the destination address is the tentative address
00133    if(ipv6IsTentativeAddr(interface, &pseudoHeader->destAddr))
00134    {
00135       //The interface must accept Neighbor Solicitation and
00136       //Neighbor Advertisement messages
00137       if(header->type != ICMPV6_TYPE_NEIGHBOR_SOL &&
00138          header->type != ICMPV6_TYPE_NEIGHBOR_ADV)
00139       {
00140          //Other packets addressed to the tentative address
00141          //should be silently discarded
00142          return;
00143       }
00144    }
00145 
00146    //Check the type of message
00147    switch(header->type)
00148    {
00149    //Destination Unreachable message?
00150    case ICMPV6_TYPE_DEST_UNREACHABLE:
00151       //Process Destination Unreachable message
00152       icmpv6ProcessDestUnreachable(interface, pseudoHeader, buffer, offset);
00153       break;
00154    //Packet Too Big message?
00155    case ICMPV6_TYPE_PACKET_TOO_BIG:
00156       //Process Packet Too Big message
00157       icmpv6ProcessPacketTooBig(interface, pseudoHeader, buffer, offset);
00158       break;
00159    //Echo Request message?
00160    case ICMPV6_TYPE_ECHO_REQUEST:
00161       //Process Echo Request message
00162       icmpv6ProcessEchoRequest(interface, pseudoHeader, buffer, offset);
00163       break;
00164 #if (MLD_SUPPORT == ENABLED)
00165    //Multicast Listener Query message?
00166    case ICMPV6_TYPE_MULTICAST_LISTENER_QUERY:
00167       //Process Multicast Listener Query message
00168       mldProcessListenerQuery(interface, pseudoHeader, buffer, offset, hopLimit);
00169       break;
00170    //Version 1 Multicast Listener Report message?
00171    case ICMPV6_TYPE_MULTICAST_LISTENER_REPORT_V1:
00172       //Process Version 1 Multicast Listener Report message
00173       mldProcessListenerReport(interface, pseudoHeader, buffer, offset, hopLimit);
00174       break;
00175 #endif
00176 #if (NDP_ROUTER_ADV_SUPPORT == ENABLED)
00177    //Router Solicitation message?
00178    case ICMPV6_TYPE_ROUTER_SOL:
00179       //Process Router Solicitation message
00180       ndpProcessRouterSol(interface, pseudoHeader, buffer, offset, hopLimit);
00181       break;
00182 #endif
00183 #if (NDP_SUPPORT == ENABLED)
00184    //Router Advertisement message?
00185    case ICMPV6_TYPE_ROUTER_ADV:
00186       //Process Router Advertisement message
00187       ndpProcessRouterAdv(interface, pseudoHeader, buffer, offset, hopLimit);
00188       break;
00189    //Neighbor Solicitation message?
00190    case ICMPV6_TYPE_NEIGHBOR_SOL:
00191       //Process Neighbor Solicitation message
00192       ndpProcessNeighborSol(interface, pseudoHeader, buffer, offset, hopLimit);
00193       break;
00194    //Neighbor Advertisement message?
00195    case ICMPV6_TYPE_NEIGHBOR_ADV:
00196       //Process Neighbor Advertisement message
00197       ndpProcessNeighborAdv(interface, pseudoHeader, buffer, offset, hopLimit);
00198       break;
00199    //Redirect message?
00200    case ICMPV6_TYPE_REDIRECT:
00201       //Process Redirect message
00202       ndpProcessRedirect(interface, pseudoHeader, buffer, offset, hopLimit);
00203       break;
00204 #endif
00205    //Unknown type?
00206    default:
00207       //Debug message
00208       TRACE_WARNING("Unknown ICMPv6 message type!\r\n");
00209       //Discard incoming ICMPv6 message
00210       break;
00211    }
00212 }
00213 
00214 
00215 /**
00216  * @brief Destination Unreachable message processing
00217  * @param[in] interface Underlying network interface
00218  * @param[in] pseudoHeader IPv6 pseudo header
00219  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
00220  * @param[in] offset Offset to the first byte of the ICMPv6 message
00221  **/
00222 
00223 void icmpv6ProcessDestUnreachable(NetInterface *interface,
00224    Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
00225 {
00226    size_t length;
00227    Icmpv6DestUnreachableMessage *icmpHeader;
00228 
00229    //Retrieve the length of the Destination Unreachable message
00230    length = netBufferGetLength(buffer) - offset;
00231 
00232    //Ensure the packet length is correct
00233    if(length < sizeof(Icmpv6DestUnreachableMessage))
00234       return;
00235 
00236    //Point to the ICMPv6 header
00237    icmpHeader = netBufferAt(buffer, offset);
00238 
00239    //Sanity check
00240    if(icmpHeader == NULL)
00241       return;
00242 
00243    //Debug message
00244    TRACE_INFO("ICMPv6 Destination Unreachable message received (%" PRIuSIZE " bytes)...\r\n", length);
00245    //Dump message contents for debugging purpose
00246    icmpv6DumpDestUnreachableMessage(icmpHeader);
00247 }
00248 
00249 
00250 /**
00251  * @brief Packet Too Big message processing
00252  * @param[in] interface Underlying network interface
00253  * @param[in] pseudoHeader IPv6 pseudo header
00254  * @param[in] buffer Multi-part buffer containing the incoming ICMPv6 message
00255  * @param[in] offset Offset to the first byte of the ICMPv6 message
00256  **/
00257 
00258 void icmpv6ProcessPacketTooBig(NetInterface *interface,
00259    Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
00260 {
00261    size_t length;
00262    Icmpv6PacketTooBigMessage *icmpHeader;
00263 
00264 #if (IPV6_PMTU_SUPPORT == ENABLED)
00265    uint32_t tentativePathMtu;
00266    Ipv6Header* ipHeader;
00267 #endif
00268 
00269    //Retrieve the length of the Packet Too Big message
00270    length = netBufferGetLength(buffer) - offset;
00271 
00272    //Ensure the packet length is correct
00273    if(length < sizeof(Icmpv6PacketTooBigMessage))
00274       return;
00275 
00276    //Point to the ICMPv6 header
00277    icmpHeader = netBufferAt(buffer, offset);
00278 
00279    //Sanity check
00280    if(icmpHeader == NULL)
00281       return;
00282 
00283    //Debug message
00284    TRACE_INFO("ICMPv6 Packet Too Big message received (%" PRIuSIZE " bytes)...\r\n", length);
00285    //Dump message contents for debugging purpose
00286    icmpv6DumpPacketTooBigMessage(icmpHeader);
00287 
00288 #if (IPV6_PMTU_SUPPORT == ENABLED)
00289    //Move to the beginning of the original IPv6 packet
00290    offset += sizeof(Icmpv6PacketTooBigMessage);
00291    length -= sizeof(Icmpv6PacketTooBigMessage);
00292 
00293    //Ensure the packet length is correct
00294    if(length < sizeof(Ipv6Header))
00295       return;
00296 
00297    //Point to the original IPv6 header
00298    ipHeader = netBufferAt(buffer, offset);
00299 
00300    //Sanity check
00301    if(ipHeader == NULL)
00302       return;
00303 
00304    //The node uses the value in the MTU field in the Packet Too Big
00305    //message as a tentative PMTU value
00306    tentativePathMtu = ntohl(icmpHeader->mtu);
00307 
00308    //Update the PMTU for the specified destination address
00309    ipv6UpdatePathMtu(interface, &ipHeader->destAddr, tentativePathMtu);
00310 #endif
00311 }
00312 
00313 
00314 /**
00315  * @brief Echo Request message processing
00316  * @param[in] interface Underlying network interface
00317  * @param[in] requestPseudoHeader IPv6 pseudo header
00318  * @param[in] request Multi-part buffer containing the incoming ICMPv6 message
00319  * @param[in] requestOffset Offset to the first byte of the ICMPv6 message
00320  **/
00321 
00322 void icmpv6ProcessEchoRequest(NetInterface *interface, Ipv6PseudoHeader *requestPseudoHeader,
00323    const NetBuffer *request, size_t requestOffset)
00324 {
00325    error_t error;
00326    size_t requestLength;
00327    size_t replyOffset;
00328    size_t replyLength;
00329    NetBuffer *reply;
00330    Icmpv6EchoMessage *requestHeader;
00331    Icmpv6EchoMessage *replyHeader;
00332    Ipv6PseudoHeader replyPseudoHeader;
00333 
00334    //Retrieve the length of the Echo Request message
00335    requestLength = netBufferGetLength(request) - requestOffset;
00336 
00337    //Ensure the packet length is correct
00338    if(requestLength < sizeof(Icmpv6EchoMessage))
00339       return;
00340 
00341    //Point to the Echo Request header
00342    requestHeader = netBufferAt(request, requestOffset);
00343 
00344    //Sanity check
00345    if(requestHeader == NULL)
00346       return;
00347 
00348    //Debug message
00349    TRACE_INFO("ICMPv6 Echo Request message received (%" PRIuSIZE " bytes)...\r\n", requestLength);
00350    //Dump message contents for debugging purpose
00351    icmpv6DumpEchoMessage(requestHeader);
00352 
00353    //Check whether the destination address of the Echo Request
00354    //message is a multicast address
00355    if(ipv6IsMulticastAddr(&requestPseudoHeader->destAddr))
00356    {
00357       //If support for multicast Echo Request messages has been explicitly
00358       //disabled, then the host shall not respond to the incoming request
00359       if(!interface->ipv6Context.enableMulticastEchoReq)
00360          return;
00361 
00362       //The source address of the reply must be a unicast address belonging to
00363       //the interface on which the multicast Echo Request message was received
00364       error = ipv6SelectSourceAddr(&interface,
00365          &requestPseudoHeader->srcAddr, &replyPseudoHeader.srcAddr);
00366 
00367       //Any error to report?
00368       if(error)
00369          return;
00370    }
00371    else
00372    {
00373       //The destination address of the Echo Request message is a unicast address
00374       replyPseudoHeader.srcAddr = requestPseudoHeader->destAddr;
00375    }
00376 
00377    //Allocate memory to hold the Echo Reply message
00378    reply = ipAllocBuffer(sizeof(Icmpv6EchoMessage), &replyOffset);
00379 
00380    //Failed to allocate memory?
00381    if(reply == NULL)
00382       return;
00383 
00384    //Point to the Echo Reply header
00385    replyHeader = netBufferAt(reply, replyOffset);
00386 
00387    //Format Echo Reply header
00388    replyHeader->type = ICMPV6_TYPE_ECHO_REPLY;
00389    replyHeader->code = 0;
00390    replyHeader->checksum = 0;
00391    replyHeader->identifier = requestHeader->identifier;
00392    replyHeader->sequenceNumber = requestHeader->sequenceNumber;
00393 
00394    //Point to the first data byte
00395    requestOffset += sizeof(Icmpv6EchoMessage);
00396    requestLength -= sizeof(Icmpv6EchoMessage);
00397 
00398    //The data received in the ICMPv6 Echo Request message must be returned
00399    //entirely and unmodified in the ICMPv6 Echo Reply message
00400    error = netBufferConcat(reply, request, requestOffset, requestLength);
00401 
00402    //Check status code
00403    if(!error)
00404    {
00405       //Get the length of the resulting message
00406       replyLength = netBufferGetLength(reply) - replyOffset;
00407 
00408       //Format IPv6 pseudo header
00409       replyPseudoHeader.destAddr = requestPseudoHeader->srcAddr;
00410       replyPseudoHeader.length = htonl(replyLength);
00411       replyPseudoHeader.reserved = 0;
00412       replyPseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
00413 
00414       //Message checksum calculation
00415       replyHeader->checksum = ipCalcUpperLayerChecksumEx(&replyPseudoHeader,
00416          sizeof(Ipv6PseudoHeader), reply, replyOffset, replyLength);
00417 
00418       //Debug message
00419       TRACE_INFO("Sending ICMPv6 Echo Reply message (%" PRIuSIZE " bytes)...\r\n", replyLength);
00420       //Dump message contents for debugging purpose
00421       icmpv6DumpEchoMessage(replyHeader);
00422 
00423       //Send Echo Reply message
00424       ipv6SendDatagram(interface, &replyPseudoHeader, reply, replyOffset, 0);
00425    }
00426 
00427    //Free previously allocated memory block
00428    netBufferFree(reply);
00429 }
00430 
00431 
00432 /**
00433  * @brief Send an ICMPv6 Error message
00434  * @param[in] interface Underlying network interface
00435  * @param[in] type Message type
00436  * @param[in] code Specific message code
00437  * @param[in] parameter Specific message parameter
00438  * @param[in] ipPacket Multi-part buffer that holds the invoking IPv6 packet
00439  * @param[in] ipPacketOffset Offset to the first byte of the IPv6 packet
00440  * @return Error code
00441  **/
00442 
00443 error_t icmpv6SendErrorMessage(NetInterface *interface, uint8_t type, uint8_t code,
00444    uint32_t parameter, const NetBuffer *ipPacket, size_t ipPacketOffset)
00445 {
00446    error_t error;
00447    size_t offset;
00448    size_t length;
00449    NetBuffer *icmpMessage;
00450    Icmpv6ErrorMessage *icmpHeader;
00451    Ipv6Header *ipHeader;
00452    Ipv6PseudoHeader pseudoHeader;
00453 
00454    //Retrieve the length of the invoking IPv6 packet
00455    length = netBufferGetLength(ipPacket) - ipPacketOffset;
00456 
00457    //Check the length of the IPv6 packet
00458    if(length < sizeof(Ipv6Header))
00459       return ERROR_INVALID_LENGTH;
00460 
00461    //Point to the header of the invoking packet
00462    ipHeader = netBufferAt(ipPacket, ipPacketOffset);
00463 
00464    //Sanity check
00465    if(ipHeader == NULL)
00466       return ERROR_FAILURE;
00467 
00468    //Check the type of the invoking packet
00469    if(ipHeader->nextHeader == IPV6_ICMPV6_HEADER)
00470    {
00471       //Make sure the ICMPv6 message is valid
00472       if(length >= (sizeof(Ipv6Header) + sizeof(Icmpv6Header)))
00473       {
00474          //Point to the ICMPv6 header
00475          icmpHeader = netBufferAt(ipPacket, ipPacketOffset + sizeof(Ipv6Header));
00476 
00477          //Sanity check
00478          if(icmpHeader != NULL)
00479          {
00480             //An ICMPv6 error message must not be originated as a result
00481             //of receiving an ICMPv6 error or redirect message
00482             if(icmpHeader->type == ICMPV6_TYPE_DEST_UNREACHABLE ||
00483                icmpHeader->type == ICMPV6_TYPE_PACKET_TOO_BIG ||
00484                icmpHeader->type == ICMPV6_TYPE_TIME_EXCEEDED ||
00485                icmpHeader->type == ICMPV6_TYPE_PARAM_PROBLEM ||
00486                icmpHeader->type == ICMPV6_TYPE_REDIRECT)
00487             {
00488                //Do not send the ICMPv6 error message...
00489                return ERROR_INVALID_TYPE;
00490             }
00491          }
00492       }
00493    }
00494 
00495    //An ICMPv6 error message must not be originated as a result of
00496    //receiving a packet destined to an IPv6 multicast address
00497    if(ipv6IsMulticastAddr(&ipHeader->destAddr))
00498    {
00499       //There are two exceptions to this rule
00500       if(type == ICMPV6_TYPE_PACKET_TOO_BIG)
00501       {
00502          //The Packet Too Big Message to allow Path MTU discovery to
00503          //work for IPv6 multicast
00504       }
00505       else if(type == ICMPV6_TYPE_PARAM_PROBLEM &&
00506          code == ICMPV6_CODE_UNKNOWN_IPV6_OPTION)
00507       {
00508          //The Parameter Problem Message, reporting an unrecognized IPv6
00509          //option that has the Option Type highest-order two bits set to 10
00510       }
00511       else
00512       {
00513          //Do not send the ICMPv6 error message...
00514          return ERROR_INVALID_ADDRESS;
00515       }
00516    }
00517 
00518    //An ICMPv6 error message must not be originated as a result of receiving a
00519    //packet whose source address does not uniquely identify a single node (e.g.
00520    //the IPv6 unspecified address, an IPv6 multicast address, or an address
00521    //known by the ICMPv6 message originator to be an IPv6 anycast address)
00522    if(ipv6IsAnycastAddr(interface, &ipHeader->srcAddr))
00523       return ERROR_INVALID_ADDRESS;
00524 
00525    //Return as much of invoking IPv6 packet as possible without
00526    //the ICMPv6 packet exceeding the minimum IPv6 MTU
00527    length = MIN(length, IPV6_DEFAULT_MTU -
00528       sizeof(Ipv6Header) - sizeof(Icmpv6ErrorMessage));
00529 
00530    //Allocate a memory buffer to hold the ICMPv6 message
00531    icmpMessage = ipAllocBuffer(sizeof(Icmpv6ErrorMessage), &offset);
00532 
00533    //Failed to allocate memory?
00534    if(icmpMessage == NULL)
00535       return ERROR_OUT_OF_MEMORY;
00536 
00537    //Point to the ICMPv6 header
00538    icmpHeader = netBufferAt(icmpMessage, offset);
00539 
00540    //Format ICMPv6 Error message
00541    icmpHeader->type = type;
00542    icmpHeader->code = code;
00543    icmpHeader->checksum = 0;
00544    icmpHeader->parameter = htonl(parameter);
00545 
00546    //Copy incoming IPv6 packet contents
00547    error = netBufferConcat(icmpMessage, ipPacket, ipPacketOffset, length);
00548 
00549    //Check status code
00550    if(!error)
00551    {
00552       //Get the length of the resulting message
00553       length = netBufferGetLength(icmpMessage) - offset;
00554 
00555       //Format IPv6 pseudo header
00556       pseudoHeader.destAddr = ipHeader->srcAddr;
00557       pseudoHeader.length = htonl(length);
00558       pseudoHeader.reserved = 0;
00559       pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
00560 
00561       //Select the relevant source address
00562       error = ipv6SelectSourceAddr(&interface,
00563          &pseudoHeader.destAddr, &pseudoHeader.srcAddr);
00564 
00565       //Check status code
00566       if(!error)
00567       {
00568          //Message checksum calculation
00569          icmpHeader->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
00570             sizeof(Ipv6PseudoHeader), icmpMessage, offset, length);
00571 
00572          //Debug message
00573          TRACE_INFO("Sending ICMPv6 Error message (%" PRIuSIZE " bytes)...\r\n", length);
00574          //Dump message contents for debugging purpose
00575          icmpv6DumpErrorMessage(icmpHeader);
00576 
00577          //Send ICMPv6 Error message
00578          error = ipv6SendDatagram(interface, &pseudoHeader, icmpMessage, offset, 0);
00579       }
00580    }
00581 
00582    //Free previously allocated memory
00583    netBufferFree(icmpMessage);
00584 
00585    //Return status code
00586    return error;
00587 }
00588 
00589 
00590 /**
00591  * @brief Dump ICMPv6 message for debugging purpose
00592  * @param[in] message Pointer to the ICMP message
00593  **/
00594 
00595 void icmpv6DumpMessage(const Icmpv6Header *message)
00596 {
00597    //Dump ICMPv6 message
00598    TRACE_DEBUG("  Type = %" PRIu8 "\r\n", message->type);
00599    TRACE_DEBUG("  Code = %" PRIu8 "\r\n", message->code);
00600    TRACE_DEBUG("  Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
00601 }
00602 
00603 
00604 /**
00605  * @brief Dump ICMPv6 Destination Unreachable message
00606  * @param[in] message Pointer to the ICMPv6 message
00607  **/
00608 
00609 void icmpv6DumpDestUnreachableMessage(const Icmpv6DestUnreachableMessage *message)
00610 {
00611    //Dump ICMPv6 message
00612    TRACE_DEBUG("  Type = %" PRIu8 "\r\n", message->type);
00613    TRACE_DEBUG("  Code = %" PRIu8 "\r\n", message->code);
00614    TRACE_DEBUG("  Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
00615 }
00616 
00617 
00618 /**
00619  * @brief Dump ICMPv6 Packet Too Big message
00620  * @param[in] message Pointer to the ICMPv6 message
00621  **/
00622 
00623 void icmpv6DumpPacketTooBigMessage(const Icmpv6PacketTooBigMessage *message)
00624 {
00625    //Dump ICMPv6 message
00626    TRACE_DEBUG("  Type = %" PRIu8 "\r\n", message->type);
00627    TRACE_DEBUG("  Code = %" PRIu8 "\r\n", message->code);
00628    TRACE_DEBUG("  Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
00629    TRACE_DEBUG("  MTU = %" PRIu32 "\r\n", ntohl(message->mtu));
00630 }
00631 
00632 
00633 /**
00634  * @brief Dump ICMPv6 Echo Request or Echo Reply message
00635  * @param[in] message Pointer to the ICMPv6 message
00636  **/
00637 
00638 void icmpv6DumpEchoMessage(const Icmpv6EchoMessage *message)
00639 {
00640    //Dump ICMPv6 message
00641    TRACE_DEBUG("  Type = %" PRIu8 "\r\n", message->type);
00642    TRACE_DEBUG("  Code = %" PRIu8 "\r\n", message->code);
00643    TRACE_DEBUG("  Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
00644    TRACE_DEBUG("  Identifier = 0x%04" PRIX16 "\r\n", ntohs(message->identifier));
00645    TRACE_DEBUG("  Sequence Number = 0x%04" PRIX16 "\r\n", ntohs(message->sequenceNumber));
00646 }
00647 
00648 
00649 /**
00650  * @brief Dump generic ICMPv6 Error message
00651  * @param[in] message Pointer to the ICMPv6 message
00652  **/
00653 
00654 void icmpv6DumpErrorMessage(const Icmpv6ErrorMessage *message)
00655 {
00656    //Dump ICMP message
00657    TRACE_DEBUG("  Type = %" PRIu8 "\r\n", message->type);
00658    TRACE_DEBUG("  Code = %" PRIu8 "\r\n", message->code);
00659    TRACE_DEBUG("  Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
00660    TRACE_DEBUG("  Parameter = %" PRIu32 "\r\n", ntohl(message->parameter));
00661 }
00662 
00663 #endif
00664