Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file dhcpv6_common.c
Sergunb 0:8918a71cdbe9 3 * @brief Functions common to DHCPv6 client, server and relay agent
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @section Description
Sergunb 0:8918a71cdbe9 26 *
Sergunb 0:8918a71cdbe9 27 * The Dynamic Host Configuration Protocol for IPv6 enables DHCP servers to
Sergunb 0:8918a71cdbe9 28 * pass configuration parameters such as IPv6 network addresses to IPv6
Sergunb 0:8918a71cdbe9 29 * nodes. This protocol is a stateful counterpart to IPv6 Stateless Address
Sergunb 0:8918a71cdbe9 30 * Autoconfiguration (RFC 2462), and can be used separately or concurrently
Sergunb 0:8918a71cdbe9 31 * with the latter to obtain configuration parameters. Refer to RFC 3315
Sergunb 0:8918a71cdbe9 32 *
Sergunb 0:8918a71cdbe9 33 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 34 * @version 1.7.6
Sergunb 0:8918a71cdbe9 35 **/
Sergunb 0:8918a71cdbe9 36
Sergunb 0:8918a71cdbe9 37 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 38 #define TRACE_LEVEL DHCPV6_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 39
Sergunb 0:8918a71cdbe9 40 //Dependencies
Sergunb 0:8918a71cdbe9 41 #include "core/net.h"
Sergunb 0:8918a71cdbe9 42 #include "dhcpv6/dhcpv6_common.h"
Sergunb 0:8918a71cdbe9 43 #include "debug.h"
Sergunb 0:8918a71cdbe9 44
Sergunb 0:8918a71cdbe9 45 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 46 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 47
Sergunb 0:8918a71cdbe9 48 //All DHCPv6 relay agents and servers (FF02::1:2)
Sergunb 0:8918a71cdbe9 49 const Ipv6Addr DHCPV6_ALL_RELAY_AGENTS_AND_SERVERS_ADDR =
Sergunb 0:8918a71cdbe9 50 IPV6_ADDR(0xFF02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002);
Sergunb 0:8918a71cdbe9 51
Sergunb 0:8918a71cdbe9 52 //All DHCPv6 servers (FF05::1:3)
Sergunb 0:8918a71cdbe9 53 const Ipv6Addr DHCPV6_ALL_SERVERS_ADDR =
Sergunb 0:8918a71cdbe9 54 IPV6_ADDR(0xFF05, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0003);
Sergunb 0:8918a71cdbe9 55
Sergunb 0:8918a71cdbe9 56
Sergunb 0:8918a71cdbe9 57 /**
Sergunb 0:8918a71cdbe9 58 * @brief Retrieve status code
Sergunb 0:8918a71cdbe9 59 *
Sergunb 0:8918a71cdbe9 60 * This function returns a status indication related to the DHCPv6
Sergunb 0:8918a71cdbe9 61 * message or option in which it appears
Sergunb 0:8918a71cdbe9 62 *
Sergunb 0:8918a71cdbe9 63 * @param[in] options Pointer to the Options field
Sergunb 0:8918a71cdbe9 64 * @param[in] length Length of the Options field
Sergunb 0:8918a71cdbe9 65 * @return Status code
Sergunb 0:8918a71cdbe9 66 **/
Sergunb 0:8918a71cdbe9 67
Sergunb 0:8918a71cdbe9 68 Dhcpv6StatusCode dhcpv6GetStatusCode(const uint8_t *options, size_t length)
Sergunb 0:8918a71cdbe9 69 {
Sergunb 0:8918a71cdbe9 70 uint16_t statusCode;
Sergunb 0:8918a71cdbe9 71 Dhcpv6Option *option;
Sergunb 0:8918a71cdbe9 72 Dhcpv6StatusCodeOption *statusCodeOption;
Sergunb 0:8918a71cdbe9 73
Sergunb 0:8918a71cdbe9 74 //Search for the Status Code option
Sergunb 0:8918a71cdbe9 75 option = dhcpv6GetOption(options, length, DHCPV6_OPTION_STATUS_CODE);
Sergunb 0:8918a71cdbe9 76
Sergunb 0:8918a71cdbe9 77 //Check whether the option has been found
Sergunb 0:8918a71cdbe9 78 if(option != NULL && ntohs(option->length) >= sizeof(Dhcpv6StatusCodeOption))
Sergunb 0:8918a71cdbe9 79 {
Sergunb 0:8918a71cdbe9 80 //The option contains a status code and a status message
Sergunb 0:8918a71cdbe9 81 statusCodeOption = (Dhcpv6StatusCodeOption *) option->value;
Sergunb 0:8918a71cdbe9 82
Sergunb 0:8918a71cdbe9 83 //Convert the status code from network byte order
Sergunb 0:8918a71cdbe9 84 statusCode = ntohs(statusCodeOption->statusCode);
Sergunb 0:8918a71cdbe9 85 }
Sergunb 0:8918a71cdbe9 86 else
Sergunb 0:8918a71cdbe9 87 {
Sergunb 0:8918a71cdbe9 88 //If the Status Code option does not appear in a message in which the option
Sergunb 0:8918a71cdbe9 89 //could appear, the status of the message is assumed to be Success
Sergunb 0:8918a71cdbe9 90 statusCode = DHCPV6_STATUS_SUCCESS;
Sergunb 0:8918a71cdbe9 91 }
Sergunb 0:8918a71cdbe9 92
Sergunb 0:8918a71cdbe9 93 //Return status code
Sergunb 0:8918a71cdbe9 94 return (Dhcpv6StatusCode) statusCode;
Sergunb 0:8918a71cdbe9 95 }
Sergunb 0:8918a71cdbe9 96
Sergunb 0:8918a71cdbe9 97
Sergunb 0:8918a71cdbe9 98 /**
Sergunb 0:8918a71cdbe9 99 * @brief Add an option to a DHCPv6 message
Sergunb 0:8918a71cdbe9 100 * @param[in] message Pointer to the DHCPv6 message
Sergunb 0:8918a71cdbe9 101 * @param[in,out] messageLength Length of the overall DHCPv6 message
Sergunb 0:8918a71cdbe9 102 * @param[in] optionCode Option code
Sergunb 0:8918a71cdbe9 103 * @param[in] optionValue Option value
Sergunb 0:8918a71cdbe9 104 * @param[in] optionLength Length of the option value
Sergunb 0:8918a71cdbe9 105 * @return If the option was successfully added, a pointer to the freshly
Sergunb 0:8918a71cdbe9 106 * created option is returned. Otherwise NULL pointer is returned
Sergunb 0:8918a71cdbe9 107 **/
Sergunb 0:8918a71cdbe9 108
Sergunb 0:8918a71cdbe9 109 Dhcpv6Option *dhcpv6AddOption(void *message, size_t *messageLength,
Sergunb 0:8918a71cdbe9 110 uint16_t optionCode, const void *optionValue, size_t optionLength)
Sergunb 0:8918a71cdbe9 111 {
Sergunb 0:8918a71cdbe9 112 Dhcpv6Option *option;
Sergunb 0:8918a71cdbe9 113
Sergunb 0:8918a71cdbe9 114 //Check the length of the DHCPv6 message
Sergunb 0:8918a71cdbe9 115 if(*messageLength < sizeof(Dhcpv6Message))
Sergunb 0:8918a71cdbe9 116 return NULL;
Sergunb 0:8918a71cdbe9 117 //Check the length of the option
Sergunb 0:8918a71cdbe9 118 if(optionLength > UINT16_MAX)
Sergunb 0:8918a71cdbe9 119 return NULL;
Sergunb 0:8918a71cdbe9 120
Sergunb 0:8918a71cdbe9 121 //Make sure there is enough room to add the option
Sergunb 0:8918a71cdbe9 122 if((*messageLength + sizeof(Dhcpv6Option) + optionLength) > DHCPV6_MAX_MSG_SIZE)
Sergunb 0:8918a71cdbe9 123 return NULL;
Sergunb 0:8918a71cdbe9 124
Sergunb 0:8918a71cdbe9 125 //Point to the end of the DHCPv6 message
Sergunb 0:8918a71cdbe9 126 option = (Dhcpv6Option *) ((uint8_t *) message + *messageLength);
Sergunb 0:8918a71cdbe9 127 //Write specified option at current location
Sergunb 0:8918a71cdbe9 128 option->code = htons(optionCode);
Sergunb 0:8918a71cdbe9 129 option->length = htons(optionLength);
Sergunb 0:8918a71cdbe9 130 //Copy option data
Sergunb 0:8918a71cdbe9 131 memcpy(option->value, optionValue, optionLength);
Sergunb 0:8918a71cdbe9 132
Sergunb 0:8918a71cdbe9 133 //Update the length of the DHCPv6 message
Sergunb 0:8918a71cdbe9 134 *messageLength += sizeof(Dhcpv6Option) + optionLength;
Sergunb 0:8918a71cdbe9 135 //Return a pointer to the freshly created option
Sergunb 0:8918a71cdbe9 136 return option;
Sergunb 0:8918a71cdbe9 137 }
Sergunb 0:8918a71cdbe9 138
Sergunb 0:8918a71cdbe9 139
Sergunb 0:8918a71cdbe9 140 /**
Sergunb 0:8918a71cdbe9 141 * @brief Add a suboption under an existing base option
Sergunb 0:8918a71cdbe9 142 * @param[in] baseOption Pointer to the base option
Sergunb 0:8918a71cdbe9 143 * @param[in,out] messageLength Length of the overall DHCPv6 message
Sergunb 0:8918a71cdbe9 144 * @param[in] optionCode Option code
Sergunb 0:8918a71cdbe9 145 * @param[in] optionValue Option value
Sergunb 0:8918a71cdbe9 146 * @param[in] optionLength Length of the option value
Sergunb 0:8918a71cdbe9 147 * @return If the option was successfully added, a pointer to the freshly
Sergunb 0:8918a71cdbe9 148 * created option is returned. Otherwise NULL pointer is returned
Sergunb 0:8918a71cdbe9 149 **/
Sergunb 0:8918a71cdbe9 150
Sergunb 0:8918a71cdbe9 151 Dhcpv6Option *dhcpv6AddSubOption(Dhcpv6Option *baseOption, size_t *messageLength,
Sergunb 0:8918a71cdbe9 152 uint16_t optionCode, const void *optionValue, size_t optionLength)
Sergunb 0:8918a71cdbe9 153 {
Sergunb 0:8918a71cdbe9 154 uint_t n;
Sergunb 0:8918a71cdbe9 155 Dhcpv6Option *option;
Sergunb 0:8918a71cdbe9 156
Sergunb 0:8918a71cdbe9 157 //The pointer to the base option must be valid
Sergunb 0:8918a71cdbe9 158 if(baseOption == NULL)
Sergunb 0:8918a71cdbe9 159 return NULL;
Sergunb 0:8918a71cdbe9 160 //Check the length of the DHCPv6 message
Sergunb 0:8918a71cdbe9 161 if(*messageLength < sizeof(Dhcpv6Message))
Sergunb 0:8918a71cdbe9 162 return NULL;
Sergunb 0:8918a71cdbe9 163 //Check the length of the suboption
Sergunb 0:8918a71cdbe9 164 if(optionLength > UINT16_MAX)
Sergunb 0:8918a71cdbe9 165 return NULL;
Sergunb 0:8918a71cdbe9 166
Sergunb 0:8918a71cdbe9 167 //Make sure there is enough room to add the option
Sergunb 0:8918a71cdbe9 168 if((*messageLength + sizeof(Dhcpv6Option) + optionLength) > DHCPV6_MAX_MSG_SIZE)
Sergunb 0:8918a71cdbe9 169 return NULL;
Sergunb 0:8918a71cdbe9 170
Sergunb 0:8918a71cdbe9 171 //Get the actual length of the base option
Sergunb 0:8918a71cdbe9 172 n = ntohs(baseOption->length);
Sergunb 0:8918a71cdbe9 173
Sergunb 0:8918a71cdbe9 174 //Point to the location that follows the base option
Sergunb 0:8918a71cdbe9 175 option = (Dhcpv6Option *) (baseOption->value + n);
Sergunb 0:8918a71cdbe9 176
Sergunb 0:8918a71cdbe9 177 //Write specified option at current location
Sergunb 0:8918a71cdbe9 178 option->code = htons(optionCode);
Sergunb 0:8918a71cdbe9 179 option->length = htons(optionLength);
Sergunb 0:8918a71cdbe9 180 //Copy option data
Sergunb 0:8918a71cdbe9 181 memcpy(option->value, optionValue, optionLength);
Sergunb 0:8918a71cdbe9 182
Sergunb 0:8918a71cdbe9 183 //Update the length of the base option
Sergunb 0:8918a71cdbe9 184 n += sizeof(Dhcpv6Option) + optionLength;
Sergunb 0:8918a71cdbe9 185 //Convert the 16-bit value to network byte order
Sergunb 0:8918a71cdbe9 186 baseOption->length = htons(n);
Sergunb 0:8918a71cdbe9 187
Sergunb 0:8918a71cdbe9 188 //Update the length of the DHCPv6 message
Sergunb 0:8918a71cdbe9 189 *messageLength += sizeof(Dhcpv6Option) + optionLength;
Sergunb 0:8918a71cdbe9 190 //Return a pointer to the freshly created option
Sergunb 0:8918a71cdbe9 191 return option;
Sergunb 0:8918a71cdbe9 192 }
Sergunb 0:8918a71cdbe9 193
Sergunb 0:8918a71cdbe9 194
Sergunb 0:8918a71cdbe9 195 /**
Sergunb 0:8918a71cdbe9 196 * @brief Find the specified option in a DHCPv6 message
Sergunb 0:8918a71cdbe9 197 * @param[in] options Pointer to the Options field
Sergunb 0:8918a71cdbe9 198 * @param[in] optionsLength Length of the Options field
Sergunb 0:8918a71cdbe9 199 * @param[in] optionCode Code of the option to find
Sergunb 0:8918a71cdbe9 200 * @return If the specified option was found, a pointer to the corresponding
Sergunb 0:8918a71cdbe9 201 * option is returned. Otherwise NULL pointer is returned
Sergunb 0:8918a71cdbe9 202 **/
Sergunb 0:8918a71cdbe9 203
Sergunb 0:8918a71cdbe9 204 Dhcpv6Option *dhcpv6GetOption(const uint8_t *options,
Sergunb 0:8918a71cdbe9 205 size_t optionsLength, uint16_t optionCode)
Sergunb 0:8918a71cdbe9 206 {
Sergunb 0:8918a71cdbe9 207 uint_t i;
Sergunb 0:8918a71cdbe9 208 Dhcpv6Option *option;
Sergunb 0:8918a71cdbe9 209
Sergunb 0:8918a71cdbe9 210 //Parse DHCPv6 options
Sergunb 0:8918a71cdbe9 211 for(i = 0; i < optionsLength; )
Sergunb 0:8918a71cdbe9 212 {
Sergunb 0:8918a71cdbe9 213 //Point to the current option
Sergunb 0:8918a71cdbe9 214 option = (Dhcpv6Option *) (options + i);
Sergunb 0:8918a71cdbe9 215
Sergunb 0:8918a71cdbe9 216 //Make sure the option is valid
Sergunb 0:8918a71cdbe9 217 if((i + sizeof(Dhcpv6Option)) > optionsLength)
Sergunb 0:8918a71cdbe9 218 break;
Sergunb 0:8918a71cdbe9 219 //Check the length of the option data
Sergunb 0:8918a71cdbe9 220 if((i + sizeof(Dhcpv6Option) + ntohs(option->length)) > optionsLength)
Sergunb 0:8918a71cdbe9 221 break;
Sergunb 0:8918a71cdbe9 222
Sergunb 0:8918a71cdbe9 223 //Option code matches the specified one?
Sergunb 0:8918a71cdbe9 224 if(ntohs(option->code) == optionCode)
Sergunb 0:8918a71cdbe9 225 return option;
Sergunb 0:8918a71cdbe9 226
Sergunb 0:8918a71cdbe9 227 //Jump to the next option
Sergunb 0:8918a71cdbe9 228 i += sizeof(Dhcpv6Option) + ntohs(option->length);
Sergunb 0:8918a71cdbe9 229 }
Sergunb 0:8918a71cdbe9 230
Sergunb 0:8918a71cdbe9 231 //The specified option code was not found
Sergunb 0:8918a71cdbe9 232 return NULL;
Sergunb 0:8918a71cdbe9 233 }
Sergunb 0:8918a71cdbe9 234
Sergunb 0:8918a71cdbe9 235
Sergunb 0:8918a71cdbe9 236 /**
Sergunb 0:8918a71cdbe9 237 * @brief Multiplication by a randomization factor
Sergunb 0:8918a71cdbe9 238 *
Sergunb 0:8918a71cdbe9 239 * Each of the computations of a new RT include a randomization factor
Sergunb 0:8918a71cdbe9 240 * RAND, which is a random number chosen with a uniform distribution
Sergunb 0:8918a71cdbe9 241 * between -0.1 and +0.1. The randomization factor is included to
Sergunb 0:8918a71cdbe9 242 * minimize synchronization of messages transmitted by DHCPv6 clients
Sergunb 0:8918a71cdbe9 243 *
Sergunb 0:8918a71cdbe9 244 * @param[in] value Input value
Sergunb 0:8918a71cdbe9 245 * @return Value resulting from the randomization process
Sergunb 0:8918a71cdbe9 246 **/
Sergunb 0:8918a71cdbe9 247
Sergunb 0:8918a71cdbe9 248 int32_t dhcpv6Rand(int32_t value)
Sergunb 0:8918a71cdbe9 249 {
Sergunb 0:8918a71cdbe9 250 //Use a randomization factor chosen with a uniform
Sergunb 0:8918a71cdbe9 251 //distribution between -0.1 and +0.1
Sergunb 0:8918a71cdbe9 252 return value * dhcpv6RandRange(-100, 100) / 1000;
Sergunb 0:8918a71cdbe9 253 }
Sergunb 0:8918a71cdbe9 254
Sergunb 0:8918a71cdbe9 255
Sergunb 0:8918a71cdbe9 256 /**
Sergunb 0:8918a71cdbe9 257 * @brief Get a random value in the specified range
Sergunb 0:8918a71cdbe9 258 * @param[in] min Lower bound
Sergunb 0:8918a71cdbe9 259 * @param[in] max Upper bound
Sergunb 0:8918a71cdbe9 260 * @return Random value in the specified range
Sergunb 0:8918a71cdbe9 261 **/
Sergunb 0:8918a71cdbe9 262
Sergunb 0:8918a71cdbe9 263 int32_t dhcpv6RandRange(int32_t min, int32_t max)
Sergunb 0:8918a71cdbe9 264 {
Sergunb 0:8918a71cdbe9 265 //Return a random value in the given range
Sergunb 0:8918a71cdbe9 266 return min + netGetRand() % (max - min + 1);
Sergunb 0:8918a71cdbe9 267 }
Sergunb 0:8918a71cdbe9 268
Sergunb 0:8918a71cdbe9 269 #endif
Sergunb 0:8918a71cdbe9 270