Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dhcpv6_common.c
00001 /** 00002 * @file dhcpv6_common.c 00003 * @brief Functions common to DHCPv6 client, server and relay agent 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 * The Dynamic Host Configuration Protocol for IPv6 enables DHCP servers to 00028 * pass configuration parameters such as IPv6 network addresses to IPv6 00029 * nodes. This protocol is a stateful counterpart to IPv6 Stateless Address 00030 * Autoconfiguration (RFC 2462), and can be used separately or concurrently 00031 * with the latter to obtain configuration parameters. Refer to RFC 3315 00032 * 00033 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00034 * @version 1.7.6 00035 **/ 00036 00037 //Switch to the appropriate trace level 00038 #define TRACE_LEVEL DHCPV6_TRACE_LEVEL 00039 00040 //Dependencies 00041 #include "core/net.h" 00042 #include "dhcpv6/dhcpv6_common.h" 00043 #include "debug.h" 00044 00045 //Check TCP/IP stack configuration 00046 #if (IPV6_SUPPORT == ENABLED) 00047 00048 //All DHCPv6 relay agents and servers (FF02::1:2) 00049 const Ipv6Addr DHCPV6_ALL_RELAY_AGENTS_AND_SERVERS_ADDR = 00050 IPV6_ADDR(0xFF02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002); 00051 00052 //All DHCPv6 servers (FF05::1:3) 00053 const Ipv6Addr DHCPV6_ALL_SERVERS_ADDR = 00054 IPV6_ADDR(0xFF05, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0003); 00055 00056 00057 /** 00058 * @brief Retrieve status code 00059 * 00060 * This function returns a status indication related to the DHCPv6 00061 * message or option in which it appears 00062 * 00063 * @param[in] options Pointer to the Options field 00064 * @param[in] length Length of the Options field 00065 * @return Status code 00066 **/ 00067 00068 Dhcpv6StatusCode dhcpv6GetStatusCode(const uint8_t *options, size_t length) 00069 { 00070 uint16_t statusCode; 00071 Dhcpv6Option *option; 00072 Dhcpv6StatusCodeOption *statusCodeOption; 00073 00074 //Search for the Status Code option 00075 option = dhcpv6GetOption(options, length, DHCPV6_OPTION_STATUS_CODE); 00076 00077 //Check whether the option has been found 00078 if(option != NULL && ntohs(option->length) >= sizeof(Dhcpv6StatusCodeOption)) 00079 { 00080 //The option contains a status code and a status message 00081 statusCodeOption = (Dhcpv6StatusCodeOption *) option->value; 00082 00083 //Convert the status code from network byte order 00084 statusCode = ntohs(statusCodeOption->statusCode); 00085 } 00086 else 00087 { 00088 //If the Status Code option does not appear in a message in which the option 00089 //could appear, the status of the message is assumed to be Success 00090 statusCode = DHCPV6_STATUS_SUCCESS; 00091 } 00092 00093 //Return status code 00094 return (Dhcpv6StatusCode) statusCode; 00095 } 00096 00097 00098 /** 00099 * @brief Add an option to a DHCPv6 message 00100 * @param[in] message Pointer to the DHCPv6 message 00101 * @param[in,out] messageLength Length of the overall DHCPv6 message 00102 * @param[in] optionCode Option code 00103 * @param[in] optionValue Option value 00104 * @param[in] optionLength Length of the option value 00105 * @return If the option was successfully added, a pointer to the freshly 00106 * created option is returned. Otherwise NULL pointer is returned 00107 **/ 00108 00109 Dhcpv6Option *dhcpv6AddOption(void *message, size_t *messageLength, 00110 uint16_t optionCode, const void *optionValue, size_t optionLength) 00111 { 00112 Dhcpv6Option *option; 00113 00114 //Check the length of the DHCPv6 message 00115 if(*messageLength < sizeof(Dhcpv6Message)) 00116 return NULL; 00117 //Check the length of the option 00118 if(optionLength > UINT16_MAX) 00119 return NULL; 00120 00121 //Make sure there is enough room to add the option 00122 if((*messageLength + sizeof(Dhcpv6Option) + optionLength) > DHCPV6_MAX_MSG_SIZE) 00123 return NULL; 00124 00125 //Point to the end of the DHCPv6 message 00126 option = (Dhcpv6Option *) ((uint8_t *) message + *messageLength); 00127 //Write specified option at current location 00128 option->code = htons(optionCode); 00129 option->length = htons(optionLength); 00130 //Copy option data 00131 memcpy(option->value, optionValue, optionLength); 00132 00133 //Update the length of the DHCPv6 message 00134 *messageLength += sizeof(Dhcpv6Option) + optionLength; 00135 //Return a pointer to the freshly created option 00136 return option; 00137 } 00138 00139 00140 /** 00141 * @brief Add a suboption under an existing base option 00142 * @param[in] baseOption Pointer to the base option 00143 * @param[in,out] messageLength Length of the overall DHCPv6 message 00144 * @param[in] optionCode Option code 00145 * @param[in] optionValue Option value 00146 * @param[in] optionLength Length of the option value 00147 * @return If the option was successfully added, a pointer to the freshly 00148 * created option is returned. Otherwise NULL pointer is returned 00149 **/ 00150 00151 Dhcpv6Option *dhcpv6AddSubOption(Dhcpv6Option *baseOption, size_t *messageLength, 00152 uint16_t optionCode, const void *optionValue, size_t optionLength) 00153 { 00154 uint_t n; 00155 Dhcpv6Option *option; 00156 00157 //The pointer to the base option must be valid 00158 if(baseOption == NULL) 00159 return NULL; 00160 //Check the length of the DHCPv6 message 00161 if(*messageLength < sizeof(Dhcpv6Message)) 00162 return NULL; 00163 //Check the length of the suboption 00164 if(optionLength > UINT16_MAX) 00165 return NULL; 00166 00167 //Make sure there is enough room to add the option 00168 if((*messageLength + sizeof(Dhcpv6Option) + optionLength) > DHCPV6_MAX_MSG_SIZE) 00169 return NULL; 00170 00171 //Get the actual length of the base option 00172 n = ntohs(baseOption->length); 00173 00174 //Point to the location that follows the base option 00175 option = (Dhcpv6Option *) (baseOption->value + n); 00176 00177 //Write specified option at current location 00178 option->code = htons(optionCode); 00179 option->length = htons(optionLength); 00180 //Copy option data 00181 memcpy(option->value, optionValue, optionLength); 00182 00183 //Update the length of the base option 00184 n += sizeof(Dhcpv6Option) + optionLength; 00185 //Convert the 16-bit value to network byte order 00186 baseOption->length = htons(n); 00187 00188 //Update the length of the DHCPv6 message 00189 *messageLength += sizeof(Dhcpv6Option) + optionLength; 00190 //Return a pointer to the freshly created option 00191 return option; 00192 } 00193 00194 00195 /** 00196 * @brief Find the specified option in a DHCPv6 message 00197 * @param[in] options Pointer to the Options field 00198 * @param[in] optionsLength Length of the Options field 00199 * @param[in] optionCode Code of the option to find 00200 * @return If the specified option was found, a pointer to the corresponding 00201 * option is returned. Otherwise NULL pointer is returned 00202 **/ 00203 00204 Dhcpv6Option *dhcpv6GetOption(const uint8_t *options, 00205 size_t optionsLength, uint16_t optionCode) 00206 { 00207 uint_t i; 00208 Dhcpv6Option *option; 00209 00210 //Parse DHCPv6 options 00211 for(i = 0; i < optionsLength; ) 00212 { 00213 //Point to the current option 00214 option = (Dhcpv6Option *) (options + i); 00215 00216 //Make sure the option is valid 00217 if((i + sizeof(Dhcpv6Option)) > optionsLength) 00218 break; 00219 //Check the length of the option data 00220 if((i + sizeof(Dhcpv6Option) + ntohs(option->length)) > optionsLength) 00221 break; 00222 00223 //Option code matches the specified one? 00224 if(ntohs(option->code) == optionCode) 00225 return option; 00226 00227 //Jump to the next option 00228 i += sizeof(Dhcpv6Option) + ntohs(option->length); 00229 } 00230 00231 //The specified option code was not found 00232 return NULL; 00233 } 00234 00235 00236 /** 00237 * @brief Multiplication by a randomization factor 00238 * 00239 * Each of the computations of a new RT include a randomization factor 00240 * RAND, which is a random number chosen with a uniform distribution 00241 * between -0.1 and +0.1. The randomization factor is included to 00242 * minimize synchronization of messages transmitted by DHCPv6 clients 00243 * 00244 * @param[in] value Input value 00245 * @return Value resulting from the randomization process 00246 **/ 00247 00248 int32_t dhcpv6Rand(int32_t value) 00249 { 00250 //Use a randomization factor chosen with a uniform 00251 //distribution between -0.1 and +0.1 00252 return value * dhcpv6RandRange(-100, 100) / 1000; 00253 } 00254 00255 00256 /** 00257 * @brief Get a random value in the specified range 00258 * @param[in] min Lower bound 00259 * @param[in] max Upper bound 00260 * @return Random value in the specified range 00261 **/ 00262 00263 int32_t dhcpv6RandRange(int32_t min, int32_t max) 00264 { 00265 //Return a random value in the given range 00266 return min + netGetRand() % (max - min + 1); 00267 } 00268 00269 #endif 00270
Generated on Tue Jul 12 2022 17:10:13 by
1.7.2