Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dhcpv6_debug.c Source File

dhcpv6_debug.c

Go to the documentation of this file.
00001 /**
00002  * @file dhcpv6_debug.c
00003  * @brief Data logging functions for debugging purpose (DHCPv6)
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  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL DHCPV6_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "core/net.h"
00034 #include "dhcpv6/dhcpv6_debug.h"
00035 #include "debug.h"
00036 
00037 //Check TCP/IP stack configuration
00038 #if (IPV6_SUPPORT == ENABLED && DHCPV6_TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
00039 
00040 //DHCPv6 message types
00041 static const char_t *messageLabel[] =
00042 {
00043    "",
00044    "SOLICIT",
00045    "ADVERTISE",
00046    "REQUEST",
00047    "CONFIRM",
00048    "RENEW",
00049    "REBIND",
00050    "REPLY",
00051    "RELEASE",
00052    "DECLINE",
00053    "RECONFIGURE",
00054    "INFO-REQUEST",
00055    "RELAY-FORW",
00056    "RELAY-REPL"
00057 };
00058 
00059 //DHCPv6 options
00060 static const char_t *optionLabel[] =
00061 {
00062    "",
00063    "Client Identifier",
00064    "Server Identifier",
00065    "IA_NA",
00066    "IA_TA",
00067    "IA Address",
00068    "Option Request",
00069    "Preference",
00070    "Elapsed time",
00071    "Relay Message",
00072    "",
00073    "Authentication",
00074    "Server Unicast",
00075    "Status Code",
00076    "Rapid Commit",
00077    "User Class",
00078    "Vendor Class",
00079    "Vendor Specific Information",
00080    "Interface ID",
00081    "Reconfigure Message",
00082    "Reconfigure Accept",
00083    "",
00084    "",
00085    "DNS Recursive Name Server",
00086    "Domain Search List"
00087 };
00088 
00089 //DHCPv6 status codes
00090 static const char_t *statusLabel[] =
00091 {
00092    "Success",
00093    "Unspecified Failure",
00094    "No Address Available",
00095    "No Binding",
00096    "Not On Link",
00097    "Use Multicast",
00098 };
00099 
00100 //Prefix used to format the structure
00101 static const char_t *prefix[8] =
00102 {
00103    "",
00104    "  ",
00105    "    ",
00106    "      ",
00107    "        ",
00108    "          ",
00109    "            ",
00110    "              "
00111 };
00112 
00113 
00114 /**
00115  * @brief Dump DHCPv6 message for debugging purpose
00116  * @param[in] message Pointer to the DHCPv6 message to dump
00117  * @param[in] length Length of the message
00118  * @return Error code
00119  **/
00120 
00121 error_t dhcpv6DumpMessage(const void *message, size_t length)
00122 {
00123    error_t error;
00124    uint8_t type;
00125    const char_t *label;
00126 
00127    //Empty message?
00128    if(!length)
00129       return ERROR_INVALID_LENGTH;
00130 
00131    //Retrieve the message type
00132    type = *((uint8_t *) message);
00133    //Get the corresponding label
00134    label = (type < arraysize(messageLabel)) ? messageLabel[type] : "Unknown";
00135 
00136    //Relay agent/server message?
00137    if(type == DHCPV6_MSG_TYPE_RELAY_FORW || type == DHCPV6_MSG_TYPE_RELAY_REPL)
00138    {
00139       //Ensure the length of the DHCPv6 message is acceptable
00140       if(length < sizeof(Dhcpv6RelayMessage))
00141       {
00142          //Report an error
00143          error = ERROR_INVALID_LENGTH;
00144       }
00145       else
00146       {
00147          //Point to the DHCPv6 message
00148          const Dhcpv6RelayMessage *relayMessage = message;
00149 
00150          //Dump message header
00151          TRACE_DEBUG("  Message Type = %" PRIu8 " (%s)\r\n", relayMessage->msgType, label);
00152          TRACE_DEBUG("  Hop Count = %" PRIu8 "\r\n", relayMessage->hopCount);
00153          TRACE_DEBUG("  Link Address = %s\r\n", ipv6AddrToString(&relayMessage->linkAddress, NULL));
00154          TRACE_DEBUG("  Peer Address = %s\r\n", ipv6AddrToString(&relayMessage->peerAddress, NULL));
00155 
00156          //Dump message options
00157          error = dhcpv6DumpOptions(relayMessage->options, length - sizeof(Dhcpv6RelayMessage), 1);
00158       }
00159 
00160    }
00161    //Client/server message?
00162    else
00163    {
00164       //Ensure the length of the DHCPv6 message is acceptable
00165       if(length < sizeof(Dhcpv6Message))
00166       {
00167          //Report an error
00168          error = ERROR_INVALID_LENGTH;
00169       }
00170       else
00171       {
00172          //Point to the DHCPv6 message
00173          const Dhcpv6Message *clientMessage = message;
00174 
00175          //Dump message header
00176          TRACE_DEBUG("  Message Type = %" PRIu8 " (%s)\r\n", clientMessage->msgType, label);
00177          TRACE_DEBUG("  Transaction ID = 0x%06" PRIX32 "\r\n", LOAD24BE(clientMessage->transactionId));
00178 
00179          //Dump message options
00180          error = dhcpv6DumpOptions(clientMessage->options, length - sizeof(Dhcpv6Message), 1);
00181       }
00182    }
00183 
00184    //Did we encounter an error?
00185    if(error)
00186    {
00187       //Debug message
00188       TRACE_WARNING("DHCPv6 message is not valid!\r\n");
00189       //Dump message contents for debugging purpose
00190       TRACE_DEBUG_ARRAY("  ", message, length);
00191    }
00192 
00193    //Return status code
00194    return error;
00195 }
00196 
00197 
00198 /**
00199  * @brief Dump DHCPv6 options for debugging purpose
00200  * @param[in] options Pointer to the DHCPv6 options to dump
00201  * @param[in] length Length of the options
00202  * @param[in] level Current level of recursion
00203  * @return Error code
00204  **/
00205 
00206 error_t dhcpv6DumpOptions(const uint8_t *options, size_t length, uint_t level)
00207 {
00208    error_t error;
00209    size_t i;
00210    Dhcpv6Option *option;
00211 
00212    //Check whether the maximum level of recursion is reached
00213    if(level >= 6)
00214    {
00215       //If the maximum level of recursion is reached, then dump contents
00216       TRACE_DEBUG("%sOptions (%" PRIuSIZE " bytes)\r\n", prefix[level], length);
00217       TRACE_DEBUG_ARRAY(prefix[level + 1], options, length);
00218       //Exit immediately
00219       return NO_ERROR;
00220    }
00221 
00222    //Parse DHCPv6 options
00223    for(i = 0; i < length; )
00224    {
00225       //Point to the current option
00226       option = (Dhcpv6Option *) (options + i);
00227 
00228       //Make sure the option is valid
00229       if((i + sizeof(Dhcpv6Option)) > length)
00230          return ERROR_INVALID_OPTION;
00231       //Check the length of the option data
00232       if((i + sizeof(Dhcpv6Option) + ntohs(option->length)) > length)
00233          return ERROR_INVALID_OPTION;
00234 
00235       //Check option code
00236       switch(ntohs(option->code))
00237       {
00238       //Client Identifier option
00239       case DHCPV6_OPTION_CLIENTID:
00240          error = dhcpv6DumpClientIdOption(option, level);
00241          break;
00242       //Server Identifier option
00243       case DHCPV6_OPTION_SERVERID:
00244          error = dhcpv6DumpServerIdOption(option, level);
00245          break;
00246       //IA_NA option
00247       case DHCPV6_OPTION_IA_NA:
00248          error = dhcpv6DumpIaNaOption(option, level);
00249          break;
00250       //IA_TA option
00251       case DHCPV6_OPTION_IA_TA:
00252          error = dhcpv6DumpIaTaOption(option, level);
00253          break;
00254       //IA Address option
00255       case DHCPV6_OPTION_IAADDR:
00256          error = dhcpv6DumpIaAddrOption(option, level);
00257          break;
00258       //Option Request option
00259       case DHCPV6_OPTION_ORO:
00260          error = dhcpv6DumpOroOption(option, level);
00261          break;
00262        //Preference option
00263       case DHCPV6_OPTION_PREFERENCE:
00264          error = dhcpv6DumpPreferenceOption(option, level);
00265          break;
00266       //Elapsed Time option
00267       case DHCPV6_OPTION_ELAPSED_TIME:
00268          error = dhcpv6DumpElapsedTimeOption(option, level);
00269          break;
00270       //Relay Message option
00271       case DHCPV6_OPTION_RELAY_MSG:
00272          error = dhcpv6DumpRelayMessageOption(option, level);
00273          break;
00274       //Authentication option
00275       case DHCPV6_OPTION_AUTH:
00276          error = dhcpv6DumpAuthOption(option, level);
00277          break;
00278       //Server Unicast option
00279       case DHCPV6_OPTION_UNICAST:
00280          error = dhcpv6DumpServerUnicastOption(option, level);
00281          break;
00282       //Status Code option
00283       case DHCPV6_OPTION_STATUS_CODE:
00284          error = dhcpv6DumpStatusCodeOption(option, level);
00285          break;
00286       //Rapid Commit option
00287       case DHCPV6_OPTION_RAPID_COMMIT:
00288          error = dhcpv6DumpRapidCommitOption(option, level);
00289          break;
00290       //User Class option
00291       case DHCPV6_OPTION_USER_CLASS:
00292          error = dhcpv6DumpUserClassOption(option, level);
00293          break;
00294       //Vendor Class option
00295       case DHCPV6_OPTION_VENDOR_CLASS:
00296          error = dhcpv6DumpVendorClassOption(option, level);
00297          break;
00298       //Vendor Specific Information option
00299       case DHCPV6_OPTION_VENDOR_OPTS:
00300          error = dhcpv6DumpVendorSpecificInfoOption(option, level);
00301          break;
00302       //Interface ID option
00303       case DHCPV6_OPTION_INTERFACE_ID:
00304          error = dhcpv6DumpInterfaceIdOption(option, level);
00305          break;
00306       //Reconfigure Message option
00307       case DHCPV6_OPTION_RECONF_MSG:
00308          error = dhcpv6DumpReconfMessageOption(option, level);
00309          break;
00310       //Reconfigure Accept option
00311       case DHCPV6_OPTION_RECONF_ACCEPT:
00312          error = dhcpv6DumpReconfAcceptOption(option, level);
00313          break;
00314       //DNS Recursive Name Server option
00315       case DHCPV6_OPTION_DNS_SERVERS:
00316          error = dhcpv6DumpDnsServersOption(option, level);
00317          break;
00318       //Domain Search List option
00319       case DHCPV6_OPTION_DOMAIN_LIST:
00320          error = dhcpv6DumpDomainListOption(option, level);
00321          break;
00322       //Unknown option...
00323       default:
00324          error = dhcpv6DumpGenericOption(option, level);
00325          break;
00326       }
00327 
00328       //Failed to parse current option?
00329       if(error)
00330          return error;
00331 
00332       //Jump to the next option
00333       i += sizeof(Dhcpv6Option) + ntohs(option->length);
00334    }
00335 
00336    //No error to report
00337    return NO_ERROR;
00338 
00339 }
00340 
00341 
00342 /**
00343  * @brief Dump generic DHCPv6 option
00344  * @param[in] option Pointer to the option to dump
00345  * @param[in] level Current level of recursion
00346  * @return Error code
00347  **/
00348 
00349 error_t dhcpv6DumpGenericOption(const Dhcpv6Option *option, uint_t level)
00350 {
00351    //Dump contents
00352    TRACE_DEBUG("%sOption %" PRIu16 " (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->code), ntohs(option->length));
00353    TRACE_DEBUG_ARRAY(prefix[level + 1], option->value, ntohs(option->length));
00354 
00355    //No error to report
00356    return NO_ERROR;
00357 }
00358 
00359 
00360 /**
00361  * @brief Dump Client Identifier option
00362  * @param[in] option Pointer to the option to dump
00363  * @param[in] level Current level of recursion
00364  * @return Error code
00365  **/
00366 
00367 error_t dhcpv6DumpClientIdOption(const Dhcpv6Option *option, uint_t level)
00368 {
00369    //Dump contents
00370    TRACE_DEBUG("%sClient Identifier option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00371    TRACE_DEBUG_ARRAY(prefix[level + 1], option->value, ntohs(option->length));
00372 
00373    //No error to report
00374    return NO_ERROR;
00375 }
00376 
00377 
00378 /**
00379  * @brief Dump Server Identifier option
00380  * @param[in] option Pointer to the option to dump
00381  * @param[in] level Current level of recursion
00382  * @return Error code
00383  **/
00384 
00385 error_t dhcpv6DumpServerIdOption(const Dhcpv6Option *option, uint_t level)
00386 {
00387    //Dump contents
00388    TRACE_DEBUG("%sServer Identifier option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00389    TRACE_DEBUG_ARRAY(prefix[level + 1], option->value, ntohs(option->length));
00390 
00391    //No error to report
00392    return NO_ERROR;
00393 }
00394 
00395 
00396 /**
00397  * @brief Dump IA_NA option
00398  * @param[in] option Pointer to the option to dump
00399  * @param[in] level Current level of recursion
00400  * @return Error code
00401  **/
00402 
00403 error_t dhcpv6DumpIaNaOption(const Dhcpv6Option *option, uint_t level)
00404 {
00405    Dhcpv6IaNaOption *iaNaOption;
00406 
00407    //Check the length of the option
00408    if(ntohs(option->length) < sizeof(Dhcpv6IaNaOption))
00409       return ERROR_INVALID_OPTION;
00410 
00411    //Point to the option contents
00412    iaNaOption = (Dhcpv6IaNaOption *) option->value;
00413 
00414    //Dump contents
00415    TRACE_DEBUG("%sIA_NA option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00416    TRACE_DEBUG("%sIA ID = 0x%08" PRIX32 "\r\n", prefix[level + 1], ntohl(iaNaOption->iaId));
00417    TRACE_DEBUG("%sT1 = %" PRIu32 "s\r\n", prefix[level + 1], ntohl(iaNaOption->t1));
00418    TRACE_DEBUG("%sT2 = %" PRIu32 "s\r\n", prefix[level + 1], ntohl(iaNaOption->t2));
00419 
00420    //Dump the options associated with this IA_NA
00421    dhcpv6DumpOptions(iaNaOption->options, ntohs(option->length) - sizeof(Dhcpv6IaNaOption), level + 1);
00422 
00423    //No error to report
00424    return NO_ERROR;
00425 }
00426 
00427 
00428 /**
00429  * @brief Dump IA_TA option
00430  * @param[in] option Pointer to the option to dump
00431  * @param[in] level Current level of recursion
00432  * @return Error code
00433  **/
00434 
00435 error_t dhcpv6DumpIaTaOption(const Dhcpv6Option *option, uint_t level)
00436 {
00437    Dhcpv6IaTaOption *iaTaOption;
00438 
00439    //Check the length of the option
00440    if(ntohs(option->length) < sizeof(Dhcpv6IaTaOption))
00441       return ERROR_INVALID_OPTION;
00442 
00443    //Point to the option contents
00444    iaTaOption = (Dhcpv6IaTaOption *) option->value;
00445 
00446    //Dump contents
00447    TRACE_DEBUG("%sIA_TA option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00448    TRACE_DEBUG("%sIA ID = 0x%08" PRIX32 "\r\n", prefix[level + 1], ntohl(iaTaOption->iaId));
00449 
00450    //Dump the options associated with this IA_TA
00451    dhcpv6DumpOptions(iaTaOption->options, ntohs(option->length) - sizeof(Dhcpv6IaTaOption), level + 1);
00452 
00453    //No error to report
00454    return NO_ERROR;
00455 }
00456 
00457 
00458 /**
00459  * @brief Dump IA Address option
00460  * @param[in] option Pointer to the option to dump
00461  * @param[in] level Current level of recursion
00462  * @return Error code
00463  **/
00464 
00465 error_t dhcpv6DumpIaAddrOption(const Dhcpv6Option *option, uint_t level)
00466 {
00467    Dhcpv6IaAddrOption *iaAddrOption;
00468 
00469    //Check the length of the option
00470    if(ntohs(option->length) < sizeof(Dhcpv6IaAddrOption))
00471       return ERROR_INVALID_OPTION;
00472 
00473    //Point to the option contents
00474    iaAddrOption = (Dhcpv6IaAddrOption *) option->value;
00475 
00476    //Dump contents
00477    TRACE_DEBUG("%sIA Address option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00478    TRACE_DEBUG("%sIPv6 Address = %s\r\n", prefix[level + 1], ipv6AddrToString(&iaAddrOption->address, NULL));
00479    TRACE_DEBUG("%sPreferred Lifetime = %" PRIu32 "s\r\n", prefix[level + 1], ntohl(iaAddrOption->preferredLifetime));
00480    TRACE_DEBUG("%sValid Lifetime = %" PRIu32 "s\r\n", prefix[level + 1], ntohl(iaAddrOption->validLifetime));
00481 
00482    //Dump the options associated with this IA address
00483    dhcpv6DumpOptions(iaAddrOption->options, ntohs(option->length) - sizeof(Dhcpv6IaAddrOption), level + 1);
00484 
00485    //No error to report
00486    return NO_ERROR;
00487 }
00488 
00489 
00490 /**
00491  * @brief Dump Option Request option
00492  * @param[in] option Pointer to the option to dump
00493  * @param[in] level Current level of recursion
00494  * @return Error code
00495  **/
00496 
00497 error_t dhcpv6DumpOroOption(const Dhcpv6Option *option, uint_t level)
00498 {
00499    uint_t i;
00500    uint_t n;
00501    uint16_t code;
00502    const char_t *label;
00503    Dhcpv6OroOption *oroOption;
00504 
00505    //Check the length of the option
00506    if(ntohs(option->length) % 2)
00507       return ERROR_INVALID_OPTION;
00508 
00509    //Point to the option contents
00510    oroOption = (Dhcpv6OroOption *) option->value;
00511    //Get the number of requested options
00512    n = ntohs(option->length) / 2;
00513 
00514    //Dump contents
00515    TRACE_DEBUG("%sOption Request option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00516 
00517    //Parse the list of requested options
00518    for(i = 0; i < n; i++)
00519    {
00520       //Get current option code
00521       code = ntohs(oroOption->requestedOption[i]);
00522       //Find the name associated with this option code
00523       label = (code < arraysize(optionLabel)) ? optionLabel[code] : "Unknown";
00524       //Display option code and option name
00525       TRACE_DEBUG("%s%" PRIu16 " (%s option)\r\n", prefix[level + 1], code, label);
00526    }
00527 
00528    //No error to report
00529    return NO_ERROR;
00530 }
00531 
00532 
00533 /**
00534  * @brief Dump Preference option
00535  * @param[in] option Pointer to the option to dump
00536  * @param[in] level Current level of recursion
00537  * @return Error code
00538  **/
00539 
00540 error_t dhcpv6DumpPreferenceOption(const Dhcpv6Option *option, uint_t level)
00541 {
00542    Dhcpv6PreferenceOption *preferenceOption;
00543 
00544    //Check the length of the option
00545    if(ntohs(option->length) != sizeof(Dhcpv6PreferenceOption))
00546       return ERROR_INVALID_OPTION;
00547 
00548    //Point to the option contents
00549    preferenceOption = (Dhcpv6PreferenceOption *) option->value;
00550 
00551    //Dump contents
00552    TRACE_DEBUG("%sPreference option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00553    TRACE_DEBUG("%s%" PRIu8 "\r\n", prefix[level + 1], preferenceOption->value);
00554 
00555    //No error to report
00556    return NO_ERROR;
00557 }
00558 
00559 
00560 /**
00561  * @brief Dump Elapsed Time option
00562  * @param[in] option Pointer to the option to dump
00563  * @param[in] level Current level of recursion
00564  * @return Error code
00565  **/
00566 
00567 error_t dhcpv6DumpElapsedTimeOption(const Dhcpv6Option *option, uint_t level)
00568 {
00569    uint32_t value;
00570    Dhcpv6ElapsedTimeOption *elapsedTimeOption;
00571 
00572    //Check the length of the option
00573    if(ntohs(option->length) != sizeof(Dhcpv6ElapsedTimeOption))
00574       return ERROR_INVALID_OPTION;
00575 
00576    //Point to the option contents
00577    elapsedTimeOption = (Dhcpv6ElapsedTimeOption *) option->value;
00578    //Convert the value to milliseconds
00579    value = ntohs(elapsedTimeOption->value) * 10;
00580 
00581    //Dump contents
00582    TRACE_DEBUG("%sElapsed Time option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00583    TRACE_DEBUG("%s%" PRIu32 "ms\r\n", prefix[level + 1], value);
00584 
00585    //No error to report
00586    return NO_ERROR;
00587 }
00588 
00589 
00590 /**
00591  * @brief Dump Relay Message option
00592  * @param[in] option Pointer to the option to dump
00593  * @param[in] level Current level of recursion
00594  * @return Error code
00595  **/
00596 
00597 error_t dhcpv6DumpRelayMessageOption(const Dhcpv6Option *option, uint_t level)
00598 {
00599    uint8_t type;
00600    const char_t *label;
00601 
00602    //Check the length of the option
00603    if(!ntohs(option->length))
00604       return ERROR_INVALID_OPTION;
00605 
00606    //Retrieve the message type
00607    type = option->value[0];
00608    //Get the corresponding label
00609    label = (type < arraysize(messageLabel)) ? messageLabel[type] : "Unknown";
00610 
00611    //Relay agent/server message?
00612    if(type == DHCPV6_MSG_TYPE_RELAY_FORW || type == DHCPV6_MSG_TYPE_RELAY_REPL)
00613    {
00614       //Get the inner message
00615       const Dhcpv6RelayMessage *message = (Dhcpv6RelayMessage *) option->value;
00616 
00617       //Ensure the length of the DHCPv6 message is acceptable
00618       if(ntohs(option->length) < sizeof(Dhcpv6RelayMessage))
00619          return ERROR_INVALID_OPTION;
00620 
00621       //Dump message header
00622       TRACE_DEBUG("%sRelay Message option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00623       TRACE_DEBUG("%sMessage Type = %" PRIu8 " (%s)\r\n", prefix[level + 1], message->msgType, label);
00624       TRACE_DEBUG("%sHop Count = %" PRIu8 "\r\n", prefix[level + 1], message->hopCount);
00625       TRACE_DEBUG("%sLink Address = %s\r\n", prefix[level + 1], ipv6AddrToString(&message->linkAddress, NULL));
00626       TRACE_DEBUG("%sPeer Address = %s\r\n", prefix[level + 1], ipv6AddrToString(&message->peerAddress, NULL));
00627 
00628       //Dump message options
00629       return dhcpv6DumpOptions(message->options, ntohs(option->length) - sizeof(Dhcpv6RelayMessage), level + 1);
00630    }
00631    //Client/server message?
00632    else
00633    {
00634       //Get the inner message
00635       const Dhcpv6Message *message = (Dhcpv6Message *) option->value;
00636 
00637       //Ensure the length of the DHCPv6 message is acceptable
00638       if(ntohs(option->length) < sizeof(Dhcpv6Message))
00639          return ERROR_INVALID_OPTION;
00640 
00641       //Dump message header
00642       TRACE_DEBUG("%sRelay Message option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00643       TRACE_DEBUG("%sMessage Type = %" PRIu8 " (%s)\r\n", prefix[level + 1], message->msgType, label);
00644       TRACE_DEBUG("%sTransaction ID = 0x%06" PRIX32 "\r\n", prefix[level + 1], LOAD24BE(message->transactionId));
00645 
00646       //Dump message options
00647       return dhcpv6DumpOptions(message->options, ntohs(option->length) - sizeof(Dhcpv6Message), level + 1);
00648    }
00649 }
00650 
00651 
00652 /**
00653  * @brief Dump Authentication option
00654  * @param[in] option Pointer to the option to dump
00655  * @param[in] level Current level of recursion
00656  * @return Error code
00657  **/
00658 
00659 error_t dhcpv6DumpAuthOption(const Dhcpv6Option *option, uint_t level)
00660 {
00661    size_t n;
00662    Dhcpv6AuthOption *authOption;
00663 
00664    //Check the length of the option
00665    if(ntohs(option->length) < sizeof(Dhcpv6AuthOption))
00666       return ERROR_INVALID_OPTION;
00667 
00668    //Point to the option contents
00669    authOption = (Dhcpv6AuthOption *) option->value;
00670    //Get the length of the authentication information
00671    n = ntohs(option->length) - sizeof(Dhcpv6AuthOption);
00672 
00673    //Dump contents
00674    TRACE_DEBUG("%sAuthentication option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00675    TRACE_DEBUG("%sProtocol = %" PRIu8 "\r\n", prefix[level + 1], authOption->protocol);
00676    TRACE_DEBUG("%sAlgorithm = %" PRIu8 "\r\n", prefix[level + 1], authOption->algorithm);
00677    TRACE_DEBUG("%sRDM = %" PRIu8 "\r\n", prefix[level + 1], authOption->rdm);
00678    TRACE_DEBUG("%sReplay Detection\r\n", prefix[level + 1]);
00679    TRACE_DEBUG_ARRAY(prefix[level + 2], authOption->replayDetection, 8);
00680    TRACE_DEBUG("%sAuthentication Information (%" PRIuSIZE " bytes)\r\n", prefix[level + 1], n);
00681    TRACE_DEBUG_ARRAY(prefix[level + 2], authOption->authInfo, n);
00682 
00683    //No error to report
00684    return NO_ERROR;
00685 }
00686 
00687 
00688 /**
00689  * @brief Dump Server Unicast option
00690  * @param[in] option Pointer to the option to dump
00691  * @param[in] level Current level of recursion
00692  * @return Error code
00693  **/
00694 
00695 error_t dhcpv6DumpServerUnicastOption(const Dhcpv6Option *option, uint_t level)
00696 {
00697    Dhcpv6ServerUnicastOption *serverUnicastOption;
00698 
00699    //Check the length of the option
00700    if(ntohs(option->length) != sizeof(Dhcpv6ServerUnicastOption))
00701       return ERROR_INVALID_OPTION;
00702 
00703    //Point to the option contents
00704    serverUnicastOption = (Dhcpv6ServerUnicastOption *) option->value;
00705 
00706    //Dump contents
00707    TRACE_DEBUG("%sServer Unicast option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00708    TRACE_DEBUG("%s%s\r\n", prefix[level + 1], ipv6AddrToString(&serverUnicastOption->serverAddr, NULL));
00709 
00710    //No error to report
00711    return NO_ERROR;
00712 }
00713 
00714 
00715 /**
00716  * @brief Dump Status Code option
00717  * @param[in] option Pointer to the option to dump
00718  * @param[in] level Current level of recursion
00719  * @return Error code
00720  **/
00721 
00722 error_t dhcpv6DumpStatusCodeOption(const Dhcpv6Option *option, uint_t level)
00723 {
00724    uint16_t code;
00725    const char_t *label;
00726    Dhcpv6StatusCodeOption *statusCodeOption;
00727 
00728    //Check the length of the option
00729    if(ntohs(option->length) < sizeof(Dhcpv6StatusCodeOption))
00730       return ERROR_INVALID_OPTION;
00731 
00732    //Point to the option contents
00733    statusCodeOption = (Dhcpv6StatusCodeOption *) option->value;
00734    //Get the status code
00735    code = ntohs(statusCodeOption->statusCode);
00736    //Get the label associated with the status code
00737    label = (code < arraysize(statusLabel)) ? statusLabel[code] : "Unknown";
00738 
00739    //Dump contents
00740    TRACE_DEBUG("%sStatus Code option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00741    TRACE_DEBUG("%sCode = %" PRIu16 " (%s)\r\n", prefix[level + 1], code, label);
00742    TRACE_DEBUG("%sMessage = %s\r\n", prefix[level + 1], statusCodeOption->statusMessage);
00743 
00744    //No error to report
00745    return NO_ERROR;
00746 }
00747 
00748 
00749 /**
00750  * @brief Dump Rapid Commit option
00751  * @param[in] option Pointer to the option to dump
00752  * @param[in] level Current level of recursion
00753  * @return Error code
00754  **/
00755 
00756 error_t dhcpv6DumpRapidCommitOption(const Dhcpv6Option *option, uint_t level)
00757 {
00758    //Check the length of the option
00759    if(ntohs(option->length) != 0)
00760       return ERROR_INVALID_OPTION;
00761 
00762    //Dump contents
00763    TRACE_DEBUG("%sRapid Commit option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00764 
00765    //No error to report
00766    return NO_ERROR;
00767 }
00768 
00769 
00770 /**
00771  * @brief Dump User Class option
00772  * @param[in] option Pointer to the option to dump
00773  * @param[in] level Current level of recursion
00774  * @return Error code
00775  **/
00776 
00777 error_t dhcpv6DumpUserClassOption(const Dhcpv6Option *option, uint_t level)
00778 {
00779    //Dump contents
00780    TRACE_DEBUG("%sUser Class option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00781    TRACE_DEBUG_ARRAY(prefix[level + 1], option->value, ntohs(option->length));
00782 
00783    //No error to report
00784    return NO_ERROR;
00785 }
00786 
00787 
00788 /**
00789  * @brief Dump Vendor Class option
00790  * @param[in] option Pointer to the option to dump
00791  * @param[in] level Current level of recursion
00792  * @return Error code
00793  **/
00794 
00795 error_t dhcpv6DumpVendorClassOption(const Dhcpv6Option *option, uint_t level)
00796 {
00797    //Dump contents
00798    TRACE_DEBUG("%sVendor Class option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00799    TRACE_DEBUG_ARRAY(prefix[level + 1], option->value, ntohs(option->length));
00800 
00801    //No error to report
00802    return NO_ERROR;
00803 }
00804 
00805 
00806 /**
00807  * @brief Dump Vendor Specific Information option
00808  * @param[in] option Pointer to the option to dump
00809  * @param[in] level Current level of recursion
00810  * @return Error code
00811  **/
00812 
00813 error_t dhcpv6DumpVendorSpecificInfoOption(const Dhcpv6Option *option, uint_t level)
00814 {
00815    //Dump contents
00816    TRACE_DEBUG("%sVendor Specific Information option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00817    TRACE_DEBUG_ARRAY(prefix[level + 1], option->value, ntohs(option->length));
00818 
00819    //No error to report
00820    return NO_ERROR;
00821 }
00822 
00823 
00824 /**
00825  * @brief Dump Interface ID option
00826  * @param[in] option Pointer to the option to dump
00827  * @param[in] level Current level of recursion
00828  * @return Error code
00829  **/
00830 
00831 error_t dhcpv6DumpInterfaceIdOption(const Dhcpv6Option *option, uint_t level)
00832 {
00833    //Dump contents
00834    TRACE_DEBUG("%sInterface ID option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00835    TRACE_DEBUG_ARRAY(prefix[level + 1], option->value, ntohs(option->length));
00836 
00837    //No error to report
00838    return NO_ERROR;
00839 }
00840 
00841 
00842 /**
00843  * @brief Dump Reconfigure Message option
00844  * @param[in] option Pointer to the option to dump
00845  * @param[in] level Current level of recursion
00846  * @return Error code
00847  **/
00848 
00849 error_t dhcpv6DumpReconfMessageOption(const Dhcpv6Option *option, uint_t level)
00850 {
00851    Dhcpv6ReconfMessageOption *reconfMessageOption;
00852 
00853    //Check the length of the option
00854    if(ntohs(option->length) != sizeof(Dhcpv6ReconfMessageOption))
00855       return ERROR_INVALID_OPTION;
00856 
00857    //Point to the option contents
00858    reconfMessageOption = (Dhcpv6ReconfMessageOption *) option->value;
00859 
00860    //Dump contents
00861    TRACE_DEBUG("%sReconfigure Message option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00862    TRACE_DEBUG("%sMessage Type = %" PRIu8 "\r\n", prefix[level + 1], reconfMessageOption->msgType);
00863 
00864    //No error to report
00865    return NO_ERROR;
00866 }
00867 
00868 
00869 /**
00870  * @brief Dump Reconfigure Accept option
00871  * @param[in] option Pointer to the option to dump
00872  * @param[in] level Current level of recursion
00873  * @return Error code
00874  **/
00875 
00876 error_t dhcpv6DumpReconfAcceptOption(const Dhcpv6Option *option, uint_t level)
00877 {
00878    //Check the length of the option
00879    if(ntohs(option->length) != 0)
00880       return ERROR_INVALID_OPTION;
00881 
00882    //Dump contents
00883    TRACE_DEBUG("%sReconfigure Accept option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00884 
00885    //No error to report
00886    return NO_ERROR;
00887 }
00888 
00889 
00890 /**
00891  * @brief Dump DNS Recursive Name Server option
00892  * @param[in] option Pointer to the option to dump
00893  * @param[in] level Current level of recursion
00894  * @return Error code
00895  **/
00896 
00897 error_t dhcpv6DumpDnsServersOption(const Dhcpv6Option *option, uint_t level)
00898 {
00899    uint_t i;
00900    uint_t n;
00901    Dhcpv6DnsServersOption *dnsServersOption;
00902 
00903    //Check the length of the option
00904    if(ntohs(option->length) % sizeof(Ipv6Addr))
00905       return ERROR_INVALID_OPTION;
00906 
00907    //Point to the option contents
00908    dnsServersOption = (Dhcpv6DnsServersOption *) option->value;
00909    //Calculate the number of IPv6 addresses in the list
00910    n = ntohs(option->length) / sizeof(Ipv6Addr);
00911 
00912    //Dump contents
00913    TRACE_DEBUG("%sDNS Recursive Name Server option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00914 
00915    //Diplay the DNS servers
00916    for(i = 0; i < n; i++)
00917       TRACE_DEBUG("%s%s\r\n", prefix[level + 1], ipv6AddrToString(dnsServersOption->address + i, NULL));
00918 
00919    //No error to report
00920    return NO_ERROR;
00921 }
00922 
00923 
00924 /**
00925  * @brief Dump Domain Search List option
00926  * @param[in] option Pointer to the option to dump
00927  * @param[in] level Current level of recursion
00928  * @return Error code
00929  **/
00930 
00931 error_t dhcpv6DumpDomainListOption(const Dhcpv6Option *option, uint_t level)
00932 {
00933    //Dump contents
00934    TRACE_DEBUG("%sDomain Search List option (%" PRIu16 " bytes)\r\n", prefix[level], ntohs(option->length));
00935    TRACE_DEBUG_ARRAY(prefix[level + 1], option->value, ntohs(option->length));
00936 
00937    //No error to report
00938    return NO_ERROR;
00939 }
00940 
00941 #endif
00942