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 dhcp_server.c
Sergunb 0:8918a71cdbe9 3 * @brief DHCP server (Dynamic Host Configuration Protocol)
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 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL DHCP_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //Dependencies
Sergunb 0:8918a71cdbe9 33 #include "core/net.h"
Sergunb 0:8918a71cdbe9 34 #include "dhcp/dhcp_server.h"
Sergunb 0:8918a71cdbe9 35 #include "dhcp/dhcp_common.h"
Sergunb 0:8918a71cdbe9 36 #include "dhcp/dhcp_debug.h"
Sergunb 0:8918a71cdbe9 37 #include "date_time.h"
Sergunb 0:8918a71cdbe9 38 #include "debug.h"
Sergunb 0:8918a71cdbe9 39
Sergunb 0:8918a71cdbe9 40 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 41 #if (IPV4_SUPPORT == ENABLED && DHCP_SERVER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 42
Sergunb 0:8918a71cdbe9 43 //Tick counter to handle periodic operations
Sergunb 0:8918a71cdbe9 44 systime_t dhcpServerTickCounter;
Sergunb 0:8918a71cdbe9 45
Sergunb 0:8918a71cdbe9 46
Sergunb 0:8918a71cdbe9 47 /**
Sergunb 0:8918a71cdbe9 48 * @brief Initialize settings with default values
Sergunb 0:8918a71cdbe9 49 * @param[out] settings Structure that contains DHCP server settings
Sergunb 0:8918a71cdbe9 50 **/
Sergunb 0:8918a71cdbe9 51
Sergunb 0:8918a71cdbe9 52 void dhcpServerGetDefaultSettings(DhcpServerSettings *settings)
Sergunb 0:8918a71cdbe9 53 {
Sergunb 0:8918a71cdbe9 54 uint_t i;
Sergunb 0:8918a71cdbe9 55
Sergunb 0:8918a71cdbe9 56 //Use default interface
Sergunb 0:8918a71cdbe9 57 settings->interface = netGetDefaultInterface();
Sergunb 0:8918a71cdbe9 58
Sergunb 0:8918a71cdbe9 59 //Support for quick configuration using rapid commit
Sergunb 0:8918a71cdbe9 60 settings->rapidCommit = FALSE;
Sergunb 0:8918a71cdbe9 61 //Lease time, in seconds, assigned to the DHCP clients
Sergunb 0:8918a71cdbe9 62 settings->leaseTime = DHCP_SERVER_DEFAULT_LEASE_TIME;
Sergunb 0:8918a71cdbe9 63
Sergunb 0:8918a71cdbe9 64 //Lowest and highest IP addresses in the pool that are available
Sergunb 0:8918a71cdbe9 65 //for dynamic address assignment
Sergunb 0:8918a71cdbe9 66 settings->ipAddrRangeMin = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 67 settings->ipAddrRangeMax = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 68
Sergunb 0:8918a71cdbe9 69 //Subnet mask
Sergunb 0:8918a71cdbe9 70 settings->subnetMask = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 71 //Default gateway
Sergunb 0:8918a71cdbe9 72 settings->defaultGateway = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 73
Sergunb 0:8918a71cdbe9 74 //DNS servers
Sergunb 0:8918a71cdbe9 75 for(i = 0; i < DHCP_SERVER_MAX_DNS_SERVERS; i++)
Sergunb 0:8918a71cdbe9 76 settings->dnsServer[i] = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 77 }
Sergunb 0:8918a71cdbe9 78
Sergunb 0:8918a71cdbe9 79
Sergunb 0:8918a71cdbe9 80 /**
Sergunb 0:8918a71cdbe9 81 * @brief DHCP server initialization
Sergunb 0:8918a71cdbe9 82 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 83 * @param[in] settings DHCP server specific settings
Sergunb 0:8918a71cdbe9 84 * @return Error code
Sergunb 0:8918a71cdbe9 85 **/
Sergunb 0:8918a71cdbe9 86
Sergunb 0:8918a71cdbe9 87 error_t dhcpServerInit(DhcpServerContext *context, const DhcpServerSettings *settings)
Sergunb 0:8918a71cdbe9 88 {
Sergunb 0:8918a71cdbe9 89 error_t error;
Sergunb 0:8918a71cdbe9 90 NetInterface *interface;
Sergunb 0:8918a71cdbe9 91
Sergunb 0:8918a71cdbe9 92 //Debug message
Sergunb 0:8918a71cdbe9 93 TRACE_INFO("Initializing DHCP server...\r\n");
Sergunb 0:8918a71cdbe9 94
Sergunb 0:8918a71cdbe9 95 //Ensure the parameters are valid
Sergunb 0:8918a71cdbe9 96 if(context == NULL || settings == NULL)
Sergunb 0:8918a71cdbe9 97 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 98
Sergunb 0:8918a71cdbe9 99 //Valid network interface?
Sergunb 0:8918a71cdbe9 100 if(settings->interface == NULL)
Sergunb 0:8918a71cdbe9 101 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 102
Sergunb 0:8918a71cdbe9 103 //Get exclusive access
Sergunb 0:8918a71cdbe9 104 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 105
Sergunb 0:8918a71cdbe9 106 //Point to the underlying network interface
Sergunb 0:8918a71cdbe9 107 interface = settings->interface;
Sergunb 0:8918a71cdbe9 108
Sergunb 0:8918a71cdbe9 109 //Clear the DHCP server context
Sergunb 0:8918a71cdbe9 110 memset(context, 0, sizeof(DhcpServerContext));
Sergunb 0:8918a71cdbe9 111 //Save user settings
Sergunb 0:8918a71cdbe9 112 context->settings = *settings;
Sergunb 0:8918a71cdbe9 113
Sergunb 0:8918a71cdbe9 114 //Next IP address that will be assigned by the DHCP server
Sergunb 0:8918a71cdbe9 115 context->nextIpAddr = settings->ipAddrRangeMin;
Sergunb 0:8918a71cdbe9 116 //DHCP server is currently suspended
Sergunb 0:8918a71cdbe9 117 context->running = FALSE;
Sergunb 0:8918a71cdbe9 118
Sergunb 0:8918a71cdbe9 119 //Callback function to be called when a DHCP message is received
Sergunb 0:8918a71cdbe9 120 error = udpAttachRxCallback(interface, DHCP_SERVER_PORT,
Sergunb 0:8918a71cdbe9 121 dhcpServerProcessMessage, context);
Sergunb 0:8918a71cdbe9 122
Sergunb 0:8918a71cdbe9 123 //Check status code
Sergunb 0:8918a71cdbe9 124 if(!error)
Sergunb 0:8918a71cdbe9 125 {
Sergunb 0:8918a71cdbe9 126 //Attach the DHCP server context to the network interface
Sergunb 0:8918a71cdbe9 127 interface->dhcpServerContext = context;
Sergunb 0:8918a71cdbe9 128 }
Sergunb 0:8918a71cdbe9 129
Sergunb 0:8918a71cdbe9 130 //Release exclusive access
Sergunb 0:8918a71cdbe9 131 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 132
Sergunb 0:8918a71cdbe9 133 //Return status code
Sergunb 0:8918a71cdbe9 134 return error;
Sergunb 0:8918a71cdbe9 135 }
Sergunb 0:8918a71cdbe9 136
Sergunb 0:8918a71cdbe9 137
Sergunb 0:8918a71cdbe9 138 /**
Sergunb 0:8918a71cdbe9 139 * @brief Start DHCP server
Sergunb 0:8918a71cdbe9 140 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 141 * @return Error code
Sergunb 0:8918a71cdbe9 142 **/
Sergunb 0:8918a71cdbe9 143
Sergunb 0:8918a71cdbe9 144 error_t dhcpServerStart(DhcpServerContext *context)
Sergunb 0:8918a71cdbe9 145 {
Sergunb 0:8918a71cdbe9 146 //Check parameter
Sergunb 0:8918a71cdbe9 147 if(context == NULL)
Sergunb 0:8918a71cdbe9 148 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 149
Sergunb 0:8918a71cdbe9 150 //Debug message
Sergunb 0:8918a71cdbe9 151 TRACE_INFO("Starting DHCP server...\r\n");
Sergunb 0:8918a71cdbe9 152
Sergunb 0:8918a71cdbe9 153 //Get exclusive access
Sergunb 0:8918a71cdbe9 154 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 155 //Start DHCP server
Sergunb 0:8918a71cdbe9 156 context->running = TRUE;
Sergunb 0:8918a71cdbe9 157 //Release exclusive access
Sergunb 0:8918a71cdbe9 158 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 159
Sergunb 0:8918a71cdbe9 160 //Successful processing
Sergunb 0:8918a71cdbe9 161 return NO_ERROR;
Sergunb 0:8918a71cdbe9 162 }
Sergunb 0:8918a71cdbe9 163
Sergunb 0:8918a71cdbe9 164
Sergunb 0:8918a71cdbe9 165 /**
Sergunb 0:8918a71cdbe9 166 * @brief Stop DHCP server
Sergunb 0:8918a71cdbe9 167 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 168 * @return Error code
Sergunb 0:8918a71cdbe9 169 **/
Sergunb 0:8918a71cdbe9 170
Sergunb 0:8918a71cdbe9 171 error_t dhcpServerStop(DhcpServerContext *context)
Sergunb 0:8918a71cdbe9 172 {
Sergunb 0:8918a71cdbe9 173 //Check parameter
Sergunb 0:8918a71cdbe9 174 if(context == NULL)
Sergunb 0:8918a71cdbe9 175 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 176
Sergunb 0:8918a71cdbe9 177 //Debug message
Sergunb 0:8918a71cdbe9 178 TRACE_INFO("Stopping DHCP server...\r\n");
Sergunb 0:8918a71cdbe9 179
Sergunb 0:8918a71cdbe9 180 //Get exclusive access
Sergunb 0:8918a71cdbe9 181 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 182 //Stop DHCP server
Sergunb 0:8918a71cdbe9 183 context->running = FALSE;
Sergunb 0:8918a71cdbe9 184 //Release exclusive access
Sergunb 0:8918a71cdbe9 185 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 186
Sergunb 0:8918a71cdbe9 187 //Successful processing
Sergunb 0:8918a71cdbe9 188 return NO_ERROR;
Sergunb 0:8918a71cdbe9 189 }
Sergunb 0:8918a71cdbe9 190
Sergunb 0:8918a71cdbe9 191
Sergunb 0:8918a71cdbe9 192 /**
Sergunb 0:8918a71cdbe9 193 * @brief DHCP server timer handler
Sergunb 0:8918a71cdbe9 194 *
Sergunb 0:8918a71cdbe9 195 * This routine must be periodically called by the TCP/IP stack to
Sergunb 0:8918a71cdbe9 196 * manage DHCP server operation
Sergunb 0:8918a71cdbe9 197 *
Sergunb 0:8918a71cdbe9 198 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 199 **/
Sergunb 0:8918a71cdbe9 200
Sergunb 0:8918a71cdbe9 201 void dhcpServerTick(DhcpServerContext *context)
Sergunb 0:8918a71cdbe9 202 {
Sergunb 0:8918a71cdbe9 203 uint_t i;
Sergunb 0:8918a71cdbe9 204 systime_t time;
Sergunb 0:8918a71cdbe9 205 systime_t leaseTime;
Sergunb 0:8918a71cdbe9 206 DhcpServerBinding *binding;
Sergunb 0:8918a71cdbe9 207
Sergunb 0:8918a71cdbe9 208 //Make sure the DHCP server has been properly instantiated
Sergunb 0:8918a71cdbe9 209 if(context == NULL)
Sergunb 0:8918a71cdbe9 210 return;
Sergunb 0:8918a71cdbe9 211
Sergunb 0:8918a71cdbe9 212 //Get current time
Sergunb 0:8918a71cdbe9 213 time = osGetSystemTime();
Sergunb 0:8918a71cdbe9 214
Sergunb 0:8918a71cdbe9 215 //Convert the lease time to milliseconds
Sergunb 0:8918a71cdbe9 216 if(context->settings.leaseTime < (MAX_DELAY / 1000))
Sergunb 0:8918a71cdbe9 217 leaseTime = context->settings.leaseTime * 1000;
Sergunb 0:8918a71cdbe9 218 else
Sergunb 0:8918a71cdbe9 219 leaseTime = MAX_DELAY;
Sergunb 0:8918a71cdbe9 220
Sergunb 0:8918a71cdbe9 221 //Loop through the list of bindings
Sergunb 0:8918a71cdbe9 222 for(i = 0; i < DHCP_SERVER_MAX_CLIENTS; i++)
Sergunb 0:8918a71cdbe9 223 {
Sergunb 0:8918a71cdbe9 224 //Point to the current binding
Sergunb 0:8918a71cdbe9 225 binding = &context->clientBinding[i];
Sergunb 0:8918a71cdbe9 226
Sergunb 0:8918a71cdbe9 227 //Valid binding?
Sergunb 0:8918a71cdbe9 228 if(!macCompAddr(&binding->macAddr, &MAC_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 229 {
Sergunb 0:8918a71cdbe9 230 //Check whether the network address has been committed
Sergunb 0:8918a71cdbe9 231 if(binding->validLease)
Sergunb 0:8918a71cdbe9 232 {
Sergunb 0:8918a71cdbe9 233 //Check whether the lease has expired
Sergunb 0:8918a71cdbe9 234 if(timeCompare(time, binding->timestamp + leaseTime) >= 0)
Sergunb 0:8918a71cdbe9 235 {
Sergunb 0:8918a71cdbe9 236 //The address lease is not more valid
Sergunb 0:8918a71cdbe9 237 binding->validLease = FALSE;
Sergunb 0:8918a71cdbe9 238 }
Sergunb 0:8918a71cdbe9 239 }
Sergunb 0:8918a71cdbe9 240 }
Sergunb 0:8918a71cdbe9 241 }
Sergunb 0:8918a71cdbe9 242 }
Sergunb 0:8918a71cdbe9 243
Sergunb 0:8918a71cdbe9 244
Sergunb 0:8918a71cdbe9 245 /**
Sergunb 0:8918a71cdbe9 246 * @brief Process incoming DHCP message
Sergunb 0:8918a71cdbe9 247 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 248 * @param[in] pseudoHeader UDP pseudo header
Sergunb 0:8918a71cdbe9 249 * @param[in] udpHeader UDP header
Sergunb 0:8918a71cdbe9 250 * @param[in] buffer Multi-part buffer containing the incoming DHCP message
Sergunb 0:8918a71cdbe9 251 * @param[in] offset Offset to the first byte of the DHCP message
Sergunb 0:8918a71cdbe9 252 * @param[in] params Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 253 **/
Sergunb 0:8918a71cdbe9 254
Sergunb 0:8918a71cdbe9 255 void dhcpServerProcessMessage(NetInterface *interface,
Sergunb 0:8918a71cdbe9 256 const IpPseudoHeader *pseudoHeader, const UdpHeader *udpHeader,
Sergunb 0:8918a71cdbe9 257 const NetBuffer *buffer, size_t offset, void *params)
Sergunb 0:8918a71cdbe9 258 {
Sergunb 0:8918a71cdbe9 259 size_t length;
Sergunb 0:8918a71cdbe9 260 DhcpServerContext *context;
Sergunb 0:8918a71cdbe9 261 DhcpMessage *message;
Sergunb 0:8918a71cdbe9 262 DhcpOption *option;
Sergunb 0:8918a71cdbe9 263
Sergunb 0:8918a71cdbe9 264 //Point to the DHCP server context
Sergunb 0:8918a71cdbe9 265 context = (DhcpServerContext *) params;
Sergunb 0:8918a71cdbe9 266
Sergunb 0:8918a71cdbe9 267 //Retrieve the length of the DHCP message
Sergunb 0:8918a71cdbe9 268 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 269
Sergunb 0:8918a71cdbe9 270 //Make sure the DHCP message is valid
Sergunb 0:8918a71cdbe9 271 if(length < sizeof(DhcpMessage))
Sergunb 0:8918a71cdbe9 272 return;
Sergunb 0:8918a71cdbe9 273 if(length > DHCP_MAX_MSG_SIZE)
Sergunb 0:8918a71cdbe9 274 return;
Sergunb 0:8918a71cdbe9 275
Sergunb 0:8918a71cdbe9 276 //Point to the beginning of the DHCP message
Sergunb 0:8918a71cdbe9 277 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 278 //Sanity check
Sergunb 0:8918a71cdbe9 279 if(message == NULL)
Sergunb 0:8918a71cdbe9 280 return;
Sergunb 0:8918a71cdbe9 281
Sergunb 0:8918a71cdbe9 282 //Debug message
Sergunb 0:8918a71cdbe9 283 TRACE_DEBUG("\r\n%s: DHCP message received (%" PRIuSIZE " bytes)...\r\n",
Sergunb 0:8918a71cdbe9 284 formatSystemTime(osGetSystemTime(), NULL), length);
Sergunb 0:8918a71cdbe9 285
Sergunb 0:8918a71cdbe9 286 //Dump the contents of the message for debugging purpose
Sergunb 0:8918a71cdbe9 287 dhcpDumpMessage(message, length);
Sergunb 0:8918a71cdbe9 288
Sergunb 0:8918a71cdbe9 289 //Check opcode
Sergunb 0:8918a71cdbe9 290 if(message->op != DHCP_OPCODE_BOOTREQUEST)
Sergunb 0:8918a71cdbe9 291 return;
Sergunb 0:8918a71cdbe9 292 //Enforce hardware type
Sergunb 0:8918a71cdbe9 293 if(message->htype != DHCP_HARDWARE_TYPE_ETH)
Sergunb 0:8918a71cdbe9 294 return;
Sergunb 0:8918a71cdbe9 295 //Check the length of the hardware address
Sergunb 0:8918a71cdbe9 296 if(message->hlen != sizeof(MacAddr))
Sergunb 0:8918a71cdbe9 297 return;
Sergunb 0:8918a71cdbe9 298 //Check magic cookie
Sergunb 0:8918a71cdbe9 299 if(message->magicCookie != HTONL(DHCP_MAGIC_COOKIE))
Sergunb 0:8918a71cdbe9 300 return;
Sergunb 0:8918a71cdbe9 301
Sergunb 0:8918a71cdbe9 302 //Retrieve DHCP Message Type option
Sergunb 0:8918a71cdbe9 303 option = dhcpGetOption(message, length, DHCP_OPT_DHCP_MESSAGE_TYPE);
Sergunb 0:8918a71cdbe9 304
Sergunb 0:8918a71cdbe9 305 //Failed to retrieve specified option?
Sergunb 0:8918a71cdbe9 306 if(option == NULL || option->length != 1)
Sergunb 0:8918a71cdbe9 307 return;
Sergunb 0:8918a71cdbe9 308
Sergunb 0:8918a71cdbe9 309 //Check message type
Sergunb 0:8918a71cdbe9 310 switch(option->value[0])
Sergunb 0:8918a71cdbe9 311 {
Sergunb 0:8918a71cdbe9 312 case DHCP_MESSAGE_TYPE_DISCOVER:
Sergunb 0:8918a71cdbe9 313 //Parse DHCPDISCOVER message
Sergunb 0:8918a71cdbe9 314 dhcpServerParseDiscover(context, message, length);
Sergunb 0:8918a71cdbe9 315 break;
Sergunb 0:8918a71cdbe9 316 case DHCP_MESSAGE_TYPE_REQUEST:
Sergunb 0:8918a71cdbe9 317 //Parse DHCPREQUEST message
Sergunb 0:8918a71cdbe9 318 dhcpServerParseRequest(context, message, length);
Sergunb 0:8918a71cdbe9 319 break;
Sergunb 0:8918a71cdbe9 320 case DHCP_MESSAGE_TYPE_DECLINE:
Sergunb 0:8918a71cdbe9 321 //Parse DHCPDECLINE message
Sergunb 0:8918a71cdbe9 322 dhcpServerParseDecline(context, message, length);
Sergunb 0:8918a71cdbe9 323 break;
Sergunb 0:8918a71cdbe9 324 case DHCP_MESSAGE_TYPE_RELEASE:
Sergunb 0:8918a71cdbe9 325 //Parse DHCPRELEASE message
Sergunb 0:8918a71cdbe9 326 dhcpServerParseRelease(context, message, length);
Sergunb 0:8918a71cdbe9 327 break;
Sergunb 0:8918a71cdbe9 328 case DHCP_MESSAGE_TYPE_INFORM:
Sergunb 0:8918a71cdbe9 329 //Parse DHCPINFORM message
Sergunb 0:8918a71cdbe9 330 dhcpServerParseInform(context, message, length);
Sergunb 0:8918a71cdbe9 331 break;
Sergunb 0:8918a71cdbe9 332 default:
Sergunb 0:8918a71cdbe9 333 //Silently drop incoming message
Sergunb 0:8918a71cdbe9 334 break;
Sergunb 0:8918a71cdbe9 335 }
Sergunb 0:8918a71cdbe9 336 }
Sergunb 0:8918a71cdbe9 337
Sergunb 0:8918a71cdbe9 338
Sergunb 0:8918a71cdbe9 339 /**
Sergunb 0:8918a71cdbe9 340 * @brief Parse DHCPDISCOVER message
Sergunb 0:8918a71cdbe9 341 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 342 * @param[in] message Pointer to the incoming DHCP message
Sergunb 0:8918a71cdbe9 343 * @param[in] length Length of the incoming message to parse
Sergunb 0:8918a71cdbe9 344 **/
Sergunb 0:8918a71cdbe9 345
Sergunb 0:8918a71cdbe9 346 void dhcpServerParseDiscover(DhcpServerContext *context,
Sergunb 0:8918a71cdbe9 347 const DhcpMessage *message, size_t length)
Sergunb 0:8918a71cdbe9 348 {
Sergunb 0:8918a71cdbe9 349 error_t error;
Sergunb 0:8918a71cdbe9 350 NetInterface *interface;
Sergunb 0:8918a71cdbe9 351 Ipv4Addr requestedIpAddr;
Sergunb 0:8918a71cdbe9 352 DhcpOption *option;
Sergunb 0:8918a71cdbe9 353 DhcpServerBinding *binding;
Sergunb 0:8918a71cdbe9 354
Sergunb 0:8918a71cdbe9 355 //Point to the underlying network interface
Sergunb 0:8918a71cdbe9 356 interface = context->settings.interface;
Sergunb 0:8918a71cdbe9 357
Sergunb 0:8918a71cdbe9 358 //Retrieve Server Identifier option
Sergunb 0:8918a71cdbe9 359 option = dhcpGetOption(message, length, DHCP_OPT_SERVER_IDENTIFIER);
Sergunb 0:8918a71cdbe9 360
Sergunb 0:8918a71cdbe9 361 //Option found?
Sergunb 0:8918a71cdbe9 362 if(option != NULL && option->length == 4)
Sergunb 0:8918a71cdbe9 363 {
Sergunb 0:8918a71cdbe9 364 //Unexpected server identifier?
Sergunb 0:8918a71cdbe9 365 if(!ipv4CompAddr(option->value, &interface->ipv4Context.addr))
Sergunb 0:8918a71cdbe9 366 return;
Sergunb 0:8918a71cdbe9 367 }
Sergunb 0:8918a71cdbe9 368
Sergunb 0:8918a71cdbe9 369 //Retrieve Requested IP Address option
Sergunb 0:8918a71cdbe9 370 option = dhcpGetOption(message, length, DHCP_OPT_REQUESTED_IP_ADDRESS);
Sergunb 0:8918a71cdbe9 371
Sergunb 0:8918a71cdbe9 372 //The client may include the 'requested IP address' option to suggest
Sergunb 0:8918a71cdbe9 373 //that a particular IP address be assigned
Sergunb 0:8918a71cdbe9 374 if(option != NULL && option->length == 4)
Sergunb 0:8918a71cdbe9 375 ipv4CopyAddr(&requestedIpAddr, option->value);
Sergunb 0:8918a71cdbe9 376 else
Sergunb 0:8918a71cdbe9 377 requestedIpAddr = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 378
Sergunb 0:8918a71cdbe9 379 //Search the list for a matching binding
Sergunb 0:8918a71cdbe9 380 binding = dhcpServerFindBindingByMacAddr(context, &message->chaddr);
Sergunb 0:8918a71cdbe9 381
Sergunb 0:8918a71cdbe9 382 //Matching binding found?
Sergunb 0:8918a71cdbe9 383 if(binding != NULL)
Sergunb 0:8918a71cdbe9 384 {
Sergunb 0:8918a71cdbe9 385 //Different IP address than cached?
Sergunb 0:8918a71cdbe9 386 if(requestedIpAddr != binding->ipAddr)
Sergunb 0:8918a71cdbe9 387 {
Sergunb 0:8918a71cdbe9 388 //Ensure the IP address is in the server's pool of available addresses
Sergunb 0:8918a71cdbe9 389 if(ntohl(requestedIpAddr) >= ntohl(context->settings.ipAddrRangeMin) &&
Sergunb 0:8918a71cdbe9 390 ntohl(requestedIpAddr) <= ntohl(context->settings.ipAddrRangeMax))
Sergunb 0:8918a71cdbe9 391 {
Sergunb 0:8918a71cdbe9 392 //Make sure the IP address is not already allocated
Sergunb 0:8918a71cdbe9 393 if(!dhcpServerFindBindingByIpAddr(context, requestedIpAddr))
Sergunb 0:8918a71cdbe9 394 {
Sergunb 0:8918a71cdbe9 395 //Record IP address
Sergunb 0:8918a71cdbe9 396 binding->ipAddr = requestedIpAddr;
Sergunb 0:8918a71cdbe9 397 //Get current time
Sergunb 0:8918a71cdbe9 398 binding->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 399 }
Sergunb 0:8918a71cdbe9 400 }
Sergunb 0:8918a71cdbe9 401 }
Sergunb 0:8918a71cdbe9 402
Sergunb 0:8918a71cdbe9 403 //Sucessful processing
Sergunb 0:8918a71cdbe9 404 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 405 }
Sergunb 0:8918a71cdbe9 406 else
Sergunb 0:8918a71cdbe9 407 {
Sergunb 0:8918a71cdbe9 408 //Create a new binding
Sergunb 0:8918a71cdbe9 409 binding = dhcpServerCreateBinding(context);
Sergunb 0:8918a71cdbe9 410
Sergunb 0:8918a71cdbe9 411 //Binding successfully created
Sergunb 0:8918a71cdbe9 412 if(binding != NULL)
Sergunb 0:8918a71cdbe9 413 {
Sergunb 0:8918a71cdbe9 414 //Ensure the IP address is in the server's pool of available addresses
Sergunb 0:8918a71cdbe9 415 if(ntohl(requestedIpAddr) >= ntohl(context->settings.ipAddrRangeMin) &&
Sergunb 0:8918a71cdbe9 416 ntohl(requestedIpAddr) <= ntohl(context->settings.ipAddrRangeMax))
Sergunb 0:8918a71cdbe9 417 {
Sergunb 0:8918a71cdbe9 418 //Make sure the IP address is not already allocated
Sergunb 0:8918a71cdbe9 419 if(!dhcpServerFindBindingByIpAddr(context, requestedIpAddr))
Sergunb 0:8918a71cdbe9 420 {
Sergunb 0:8918a71cdbe9 421 //Record IP address
Sergunb 0:8918a71cdbe9 422 binding->ipAddr = requestedIpAddr;
Sergunb 0:8918a71cdbe9 423 //Sucessful processing
Sergunb 0:8918a71cdbe9 424 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 425 }
Sergunb 0:8918a71cdbe9 426 else
Sergunb 0:8918a71cdbe9 427 {
Sergunb 0:8918a71cdbe9 428 //Retrieve the next available IP address from the pool of addresses
Sergunb 0:8918a71cdbe9 429 error = dhcpServerGetNextIpAddr(context, &binding->ipAddr);
Sergunb 0:8918a71cdbe9 430 }
Sergunb 0:8918a71cdbe9 431 }
Sergunb 0:8918a71cdbe9 432 else
Sergunb 0:8918a71cdbe9 433 {
Sergunb 0:8918a71cdbe9 434 //Retrieve the next available IP address from the pool of addresses
Sergunb 0:8918a71cdbe9 435 error = dhcpServerGetNextIpAddr(context, &binding->ipAddr);
Sergunb 0:8918a71cdbe9 436 }
Sergunb 0:8918a71cdbe9 437
Sergunb 0:8918a71cdbe9 438 //Check status code
Sergunb 0:8918a71cdbe9 439 if(!error)
Sergunb 0:8918a71cdbe9 440 {
Sergunb 0:8918a71cdbe9 441 //Record MAC address
Sergunb 0:8918a71cdbe9 442 binding->macAddr = message->chaddr;
Sergunb 0:8918a71cdbe9 443 //Get current time
Sergunb 0:8918a71cdbe9 444 binding->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 445 }
Sergunb 0:8918a71cdbe9 446 }
Sergunb 0:8918a71cdbe9 447 else
Sergunb 0:8918a71cdbe9 448 {
Sergunb 0:8918a71cdbe9 449 //Failed to create a new binding
Sergunb 0:8918a71cdbe9 450 error = ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 451 }
Sergunb 0:8918a71cdbe9 452 }
Sergunb 0:8918a71cdbe9 453
Sergunb 0:8918a71cdbe9 454 //Check status code
Sergunb 0:8918a71cdbe9 455 if(!error)
Sergunb 0:8918a71cdbe9 456 {
Sergunb 0:8918a71cdbe9 457 //The server responds with a DHCPOFFER message that includes an
Sergunb 0:8918a71cdbe9 458 //available network address in the 'yiaddr' field (and other
Sergunb 0:8918a71cdbe9 459 //configuration parameters in DHCP options)
Sergunb 0:8918a71cdbe9 460 dhcpServerSendReply(context, DHCP_MESSAGE_TYPE_OFFER,
Sergunb 0:8918a71cdbe9 461 binding->ipAddr, message, length);
Sergunb 0:8918a71cdbe9 462 }
Sergunb 0:8918a71cdbe9 463 }
Sergunb 0:8918a71cdbe9 464
Sergunb 0:8918a71cdbe9 465
Sergunb 0:8918a71cdbe9 466 /**
Sergunb 0:8918a71cdbe9 467 * @brief Parse DHCPREQUEST message
Sergunb 0:8918a71cdbe9 468 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 469 * @param[in] message Pointer to the incoming DHCP message
Sergunb 0:8918a71cdbe9 470 * @param[in] length Length of the incoming message to parse
Sergunb 0:8918a71cdbe9 471 **/
Sergunb 0:8918a71cdbe9 472
Sergunb 0:8918a71cdbe9 473 void dhcpServerParseRequest(DhcpServerContext *context,
Sergunb 0:8918a71cdbe9 474 const DhcpMessage *message, size_t length)
Sergunb 0:8918a71cdbe9 475 {
Sergunb 0:8918a71cdbe9 476 NetInterface *interface;
Sergunb 0:8918a71cdbe9 477 Ipv4Addr clientIpAddr;
Sergunb 0:8918a71cdbe9 478 DhcpOption *option;
Sergunb 0:8918a71cdbe9 479 DhcpServerBinding *binding;
Sergunb 0:8918a71cdbe9 480
Sergunb 0:8918a71cdbe9 481 //Point to the underlying network interface
Sergunb 0:8918a71cdbe9 482 interface = context->settings.interface;
Sergunb 0:8918a71cdbe9 483
Sergunb 0:8918a71cdbe9 484 //Retrieve Server Identifier option
Sergunb 0:8918a71cdbe9 485 option = dhcpGetOption(message, length, DHCP_OPT_SERVER_IDENTIFIER);
Sergunb 0:8918a71cdbe9 486
Sergunb 0:8918a71cdbe9 487 //Option found?
Sergunb 0:8918a71cdbe9 488 if(option != NULL && option->length == 4)
Sergunb 0:8918a71cdbe9 489 {
Sergunb 0:8918a71cdbe9 490 //Unexpected server identifier?
Sergunb 0:8918a71cdbe9 491 if(!ipv4CompAddr(option->value, &interface->ipv4Context.addr))
Sergunb 0:8918a71cdbe9 492 return;
Sergunb 0:8918a71cdbe9 493 }
Sergunb 0:8918a71cdbe9 494
Sergunb 0:8918a71cdbe9 495 //Check the 'ciaddr' field
Sergunb 0:8918a71cdbe9 496 if(message->ciaddr != IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 497 {
Sergunb 0:8918a71cdbe9 498 //Save client's network address
Sergunb 0:8918a71cdbe9 499 clientIpAddr = message->ciaddr;
Sergunb 0:8918a71cdbe9 500 }
Sergunb 0:8918a71cdbe9 501 else
Sergunb 0:8918a71cdbe9 502 {
Sergunb 0:8918a71cdbe9 503 //Retrieve Requested IP Address option
Sergunb 0:8918a71cdbe9 504 option = dhcpGetOption(message, length, DHCP_OPT_REQUESTED_IP_ADDRESS);
Sergunb 0:8918a71cdbe9 505
Sergunb 0:8918a71cdbe9 506 //Option found?
Sergunb 0:8918a71cdbe9 507 if(option != NULL && option->length == 4)
Sergunb 0:8918a71cdbe9 508 ipv4CopyAddr(&clientIpAddr, option->value);
Sergunb 0:8918a71cdbe9 509 else
Sergunb 0:8918a71cdbe9 510 clientIpAddr = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 511 }
Sergunb 0:8918a71cdbe9 512
Sergunb 0:8918a71cdbe9 513 //Valid client IP address?
Sergunb 0:8918a71cdbe9 514 if(clientIpAddr != IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 515 {
Sergunb 0:8918a71cdbe9 516 //Search the list for a matching binding
Sergunb 0:8918a71cdbe9 517 binding = dhcpServerFindBindingByMacAddr(context, &message->chaddr);
Sergunb 0:8918a71cdbe9 518
Sergunb 0:8918a71cdbe9 519 //Matching binding found?
Sergunb 0:8918a71cdbe9 520 if(binding != NULL)
Sergunb 0:8918a71cdbe9 521 {
Sergunb 0:8918a71cdbe9 522 //Make sure the client's IP address is valid
Sergunb 0:8918a71cdbe9 523 if(clientIpAddr == binding->ipAddr)
Sergunb 0:8918a71cdbe9 524 {
Sergunb 0:8918a71cdbe9 525 //Commit network address
Sergunb 0:8918a71cdbe9 526 binding->validLease = TRUE;
Sergunb 0:8918a71cdbe9 527 //Save lease start time
Sergunb 0:8918a71cdbe9 528 binding->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 529
Sergunb 0:8918a71cdbe9 530 //The server responds with a DHCPACK message containing the
Sergunb 0:8918a71cdbe9 531 //configuration parameters for the requesting client
Sergunb 0:8918a71cdbe9 532 dhcpServerSendReply(context, DHCP_MESSAGE_TYPE_ACK,
Sergunb 0:8918a71cdbe9 533 binding->ipAddr, message, length);
Sergunb 0:8918a71cdbe9 534
Sergunb 0:8918a71cdbe9 535 //Exit immediately
Sergunb 0:8918a71cdbe9 536 return;
Sergunb 0:8918a71cdbe9 537 }
Sergunb 0:8918a71cdbe9 538 }
Sergunb 0:8918a71cdbe9 539 else
Sergunb 0:8918a71cdbe9 540 {
Sergunb 0:8918a71cdbe9 541 //Ensure the IP address is in the server's pool of available addresses
Sergunb 0:8918a71cdbe9 542 if(ntohl(clientIpAddr) >= ntohl(context->settings.ipAddrRangeMin) &&
Sergunb 0:8918a71cdbe9 543 ntohl(clientIpAddr) <= ntohl(context->settings.ipAddrRangeMax))
Sergunb 0:8918a71cdbe9 544 {
Sergunb 0:8918a71cdbe9 545 //Make sure the IP address is not already allocated
Sergunb 0:8918a71cdbe9 546 if(!dhcpServerFindBindingByIpAddr(context, clientIpAddr))
Sergunb 0:8918a71cdbe9 547 {
Sergunb 0:8918a71cdbe9 548 //Create a new binding
Sergunb 0:8918a71cdbe9 549 binding = dhcpServerCreateBinding(context);
Sergunb 0:8918a71cdbe9 550
Sergunb 0:8918a71cdbe9 551 //Binding successfully created
Sergunb 0:8918a71cdbe9 552 if(binding != NULL)
Sergunb 0:8918a71cdbe9 553 {
Sergunb 0:8918a71cdbe9 554 //Record MAC address
Sergunb 0:8918a71cdbe9 555 binding->macAddr = message->chaddr;
Sergunb 0:8918a71cdbe9 556 //Record IP address
Sergunb 0:8918a71cdbe9 557 binding->ipAddr = clientIpAddr;
Sergunb 0:8918a71cdbe9 558 //Commit network address
Sergunb 0:8918a71cdbe9 559 binding->validLease = TRUE;
Sergunb 0:8918a71cdbe9 560 //Get current time
Sergunb 0:8918a71cdbe9 561 binding->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 562
Sergunb 0:8918a71cdbe9 563 //The server responds with a DHCPACK message containing the
Sergunb 0:8918a71cdbe9 564 //configuration parameters for the requesting client
Sergunb 0:8918a71cdbe9 565 dhcpServerSendReply(context, DHCP_MESSAGE_TYPE_ACK,
Sergunb 0:8918a71cdbe9 566 binding->ipAddr, message, length);
Sergunb 0:8918a71cdbe9 567
Sergunb 0:8918a71cdbe9 568 //Exit immediately
Sergunb 0:8918a71cdbe9 569 return;
Sergunb 0:8918a71cdbe9 570 }
Sergunb 0:8918a71cdbe9 571 }
Sergunb 0:8918a71cdbe9 572 }
Sergunb 0:8918a71cdbe9 573 }
Sergunb 0:8918a71cdbe9 574 }
Sergunb 0:8918a71cdbe9 575
Sergunb 0:8918a71cdbe9 576 //If the server is unable to satisfy the DHCPREQUEST message, the
Sergunb 0:8918a71cdbe9 577 //server should respond with a DHCPNAK message
Sergunb 0:8918a71cdbe9 578 dhcpServerSendReply(context, DHCP_MESSAGE_TYPE_NAK,
Sergunb 0:8918a71cdbe9 579 IPV4_UNSPECIFIED_ADDR, message, length);
Sergunb 0:8918a71cdbe9 580 }
Sergunb 0:8918a71cdbe9 581
Sergunb 0:8918a71cdbe9 582
Sergunb 0:8918a71cdbe9 583 /**
Sergunb 0:8918a71cdbe9 584 * @brief Parse DHCPDECLINE message
Sergunb 0:8918a71cdbe9 585 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 586 * @param[in] message Pointer to the incoming DHCP message
Sergunb 0:8918a71cdbe9 587 * @param[in] length Length of the incoming message to parse
Sergunb 0:8918a71cdbe9 588 **/
Sergunb 0:8918a71cdbe9 589
Sergunb 0:8918a71cdbe9 590 void dhcpServerParseDecline(DhcpServerContext *context,
Sergunb 0:8918a71cdbe9 591 const DhcpMessage *message, size_t length)
Sergunb 0:8918a71cdbe9 592 {
Sergunb 0:8918a71cdbe9 593 DhcpOption *option;
Sergunb 0:8918a71cdbe9 594 DhcpServerBinding *binding;
Sergunb 0:8918a71cdbe9 595 Ipv4Addr requestedIpAddr;
Sergunb 0:8918a71cdbe9 596
Sergunb 0:8918a71cdbe9 597 //Retrieve Requested IP Address option
Sergunb 0:8918a71cdbe9 598 option = dhcpGetOption(message, length, DHCP_OPT_REQUESTED_IP_ADDRESS);
Sergunb 0:8918a71cdbe9 599
Sergunb 0:8918a71cdbe9 600 //Option found?
Sergunb 0:8918a71cdbe9 601 if(option != NULL && option->length == 4)
Sergunb 0:8918a71cdbe9 602 {
Sergunb 0:8918a71cdbe9 603 //Copy the requested IP address
Sergunb 0:8918a71cdbe9 604 ipv4CopyAddr(&requestedIpAddr, option->value);
Sergunb 0:8918a71cdbe9 605
Sergunb 0:8918a71cdbe9 606 //Search the list for a matching binding
Sergunb 0:8918a71cdbe9 607 binding = dhcpServerFindBindingByMacAddr(context, &message->chaddr);
Sergunb 0:8918a71cdbe9 608
Sergunb 0:8918a71cdbe9 609 //Matching binding found?
Sergunb 0:8918a71cdbe9 610 if(binding != NULL)
Sergunb 0:8918a71cdbe9 611 {
Sergunb 0:8918a71cdbe9 612 //Check the IP address against the requested IP address
Sergunb 0:8918a71cdbe9 613 if(binding->ipAddr == requestedIpAddr)
Sergunb 0:8918a71cdbe9 614 {
Sergunb 0:8918a71cdbe9 615 //Remote the binding from the list
Sergunb 0:8918a71cdbe9 616 memset(binding, 0, sizeof(DhcpServerBinding));
Sergunb 0:8918a71cdbe9 617 }
Sergunb 0:8918a71cdbe9 618 }
Sergunb 0:8918a71cdbe9 619 }
Sergunb 0:8918a71cdbe9 620 }
Sergunb 0:8918a71cdbe9 621
Sergunb 0:8918a71cdbe9 622
Sergunb 0:8918a71cdbe9 623 /**
Sergunb 0:8918a71cdbe9 624 * @brief Parse DHCPRELEASE message
Sergunb 0:8918a71cdbe9 625 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 626 * @param[in] message Pointer to the incoming DHCP message
Sergunb 0:8918a71cdbe9 627 * @param[in] length Length of the incoming message to parse
Sergunb 0:8918a71cdbe9 628 **/
Sergunb 0:8918a71cdbe9 629
Sergunb 0:8918a71cdbe9 630 void dhcpServerParseRelease(DhcpServerContext *context,
Sergunb 0:8918a71cdbe9 631 const DhcpMessage *message, size_t length)
Sergunb 0:8918a71cdbe9 632 {
Sergunb 0:8918a71cdbe9 633 DhcpServerBinding *binding;
Sergunb 0:8918a71cdbe9 634
Sergunb 0:8918a71cdbe9 635 //Search the list for a matching binding
Sergunb 0:8918a71cdbe9 636 binding = dhcpServerFindBindingByMacAddr(context, &message->chaddr);
Sergunb 0:8918a71cdbe9 637
Sergunb 0:8918a71cdbe9 638 //Matching binding found?
Sergunb 0:8918a71cdbe9 639 if(binding != NULL)
Sergunb 0:8918a71cdbe9 640 {
Sergunb 0:8918a71cdbe9 641 //Check the IP address against the client IP address
Sergunb 0:8918a71cdbe9 642 if(binding->ipAddr == message->ciaddr)
Sergunb 0:8918a71cdbe9 643 {
Sergunb 0:8918a71cdbe9 644 //Release the network address and cancel remaining lease
Sergunb 0:8918a71cdbe9 645 binding->validLease = FALSE;
Sergunb 0:8918a71cdbe9 646 }
Sergunb 0:8918a71cdbe9 647 }
Sergunb 0:8918a71cdbe9 648 }
Sergunb 0:8918a71cdbe9 649
Sergunb 0:8918a71cdbe9 650
Sergunb 0:8918a71cdbe9 651 /**
Sergunb 0:8918a71cdbe9 652 * @brief Parse DHCPINFORM message
Sergunb 0:8918a71cdbe9 653 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 654 * @param[in] message Pointer to the incoming DHCP message
Sergunb 0:8918a71cdbe9 655 * @param[in] length Length of the incoming message to parse
Sergunb 0:8918a71cdbe9 656 **/
Sergunb 0:8918a71cdbe9 657
Sergunb 0:8918a71cdbe9 658 void dhcpServerParseInform(DhcpServerContext *context,
Sergunb 0:8918a71cdbe9 659 const DhcpMessage *message, size_t length)
Sergunb 0:8918a71cdbe9 660 {
Sergunb 0:8918a71cdbe9 661 //Make sure the client IP address is valid
Sergunb 0:8918a71cdbe9 662 if(message->ciaddr != IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 663 {
Sergunb 0:8918a71cdbe9 664 //Servers receiving a DHCPINFORM message construct a DHCPACK message
Sergunb 0:8918a71cdbe9 665 //with any local configuration parameters appropriate for the client
Sergunb 0:8918a71cdbe9 666 dhcpServerSendReply(context, DHCP_MESSAGE_TYPE_ACK,
Sergunb 0:8918a71cdbe9 667 IPV4_UNSPECIFIED_ADDR, message, length);
Sergunb 0:8918a71cdbe9 668 }
Sergunb 0:8918a71cdbe9 669 }
Sergunb 0:8918a71cdbe9 670
Sergunb 0:8918a71cdbe9 671
Sergunb 0:8918a71cdbe9 672 /**
Sergunb 0:8918a71cdbe9 673 * @brief Send DHCP reply message
Sergunb 0:8918a71cdbe9 674 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 675 * @param[in] type DHCP message type (DHCPOFFER, DHCPACK or DHCPNAK)
Sergunb 0:8918a71cdbe9 676 * @param[in] yourIpAddr The IP address to be placed in the 'yiaddr' field
Sergunb 0:8918a71cdbe9 677 * @param[in] request Pointer to DHCP message received from the client
Sergunb 0:8918a71cdbe9 678 * @param[in] length Length of the DHCP message received from the client
Sergunb 0:8918a71cdbe9 679 * @return Error code
Sergunb 0:8918a71cdbe9 680 **/
Sergunb 0:8918a71cdbe9 681
Sergunb 0:8918a71cdbe9 682 error_t dhcpServerSendReply(DhcpServerContext *context, uint8_t type,
Sergunb 0:8918a71cdbe9 683 Ipv4Addr yourIpAddr, const DhcpMessage *request, size_t length)
Sergunb 0:8918a71cdbe9 684 {
Sergunb 0:8918a71cdbe9 685 error_t error;
Sergunb 0:8918a71cdbe9 686 uint_t n;
Sergunb 0:8918a71cdbe9 687 uint32_t value;
Sergunb 0:8918a71cdbe9 688 size_t offset;
Sergunb 0:8918a71cdbe9 689 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 690 NetInterface *interface;
Sergunb 0:8918a71cdbe9 691 DhcpMessage *reply;
Sergunb 0:8918a71cdbe9 692 IpAddr destIpAddr;
Sergunb 0:8918a71cdbe9 693 uint16_t destPort;
Sergunb 0:8918a71cdbe9 694
Sergunb 0:8918a71cdbe9 695 //Point to the underlying network interface
Sergunb 0:8918a71cdbe9 696 interface = context->settings.interface;
Sergunb 0:8918a71cdbe9 697
Sergunb 0:8918a71cdbe9 698 //Allocate a memory buffer to hold the DHCP message
Sergunb 0:8918a71cdbe9 699 buffer = udpAllocBuffer(DHCP_MIN_MSG_SIZE, &offset);
Sergunb 0:8918a71cdbe9 700 //Failed to allocate buffer?
Sergunb 0:8918a71cdbe9 701 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 702 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 703
Sergunb 0:8918a71cdbe9 704 //Point to the beginning of the DHCP message
Sergunb 0:8918a71cdbe9 705 reply = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 706 //Clear memory buffer contents
Sergunb 0:8918a71cdbe9 707 memset(reply, 0, DHCP_MIN_MSG_SIZE);
Sergunb 0:8918a71cdbe9 708
Sergunb 0:8918a71cdbe9 709 //Format DHCP reply message
Sergunb 0:8918a71cdbe9 710 reply->op = DHCP_OPCODE_BOOTREPLY;
Sergunb 0:8918a71cdbe9 711 reply->htype = DHCP_HARDWARE_TYPE_ETH;
Sergunb 0:8918a71cdbe9 712 reply->hlen = sizeof(MacAddr);
Sergunb 0:8918a71cdbe9 713 reply->xid = request->xid;
Sergunb 0:8918a71cdbe9 714 reply->secs = 0;
Sergunb 0:8918a71cdbe9 715 reply->flags = request->flags;
Sergunb 0:8918a71cdbe9 716 reply->ciaddr = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 717 reply->yiaddr = yourIpAddr;
Sergunb 0:8918a71cdbe9 718 reply->siaddr = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 719 reply->giaddr = request->giaddr;
Sergunb 0:8918a71cdbe9 720 reply->chaddr = request->chaddr;
Sergunb 0:8918a71cdbe9 721
Sergunb 0:8918a71cdbe9 722 //Write magic cookie before setting any option
Sergunb 0:8918a71cdbe9 723 reply->magicCookie = HTONL(DHCP_MAGIC_COOKIE);
Sergunb 0:8918a71cdbe9 724 //Properly terminate options field
Sergunb 0:8918a71cdbe9 725 reply->options[0] = DHCP_OPT_END;
Sergunb 0:8918a71cdbe9 726
Sergunb 0:8918a71cdbe9 727 //Add DHCP Message Type option
Sergunb 0:8918a71cdbe9 728 dhcpAddOption(reply, DHCP_OPT_DHCP_MESSAGE_TYPE,
Sergunb 0:8918a71cdbe9 729 &type, sizeof(type));
Sergunb 0:8918a71cdbe9 730
Sergunb 0:8918a71cdbe9 731 //Add Server Identifier option
Sergunb 0:8918a71cdbe9 732 dhcpAddOption(reply, DHCP_OPT_SERVER_IDENTIFIER,
Sergunb 0:8918a71cdbe9 733 &interface->ipv4Context.addr, sizeof(Ipv4Addr));
Sergunb 0:8918a71cdbe9 734
Sergunb 0:8918a71cdbe9 735 //DHCPOFFER or DHCPACK message?
Sergunb 0:8918a71cdbe9 736 if(type == DHCP_MESSAGE_TYPE_OFFER || type == DHCP_MESSAGE_TYPE_ACK)
Sergunb 0:8918a71cdbe9 737 {
Sergunb 0:8918a71cdbe9 738 //Convert the lease time to network byte order
Sergunb 0:8918a71cdbe9 739 value = htonl(context->settings.leaseTime);
Sergunb 0:8918a71cdbe9 740
Sergunb 0:8918a71cdbe9 741 //When responding to a DHCPINFORM message, the server must not
Sergunb 0:8918a71cdbe9 742 //send a lease expiration time to the client
Sergunb 0:8918a71cdbe9 743 if(yourIpAddr != IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 744 {
Sergunb 0:8918a71cdbe9 745 //Add IP Address Lease Time option
Sergunb 0:8918a71cdbe9 746 dhcpAddOption(reply, DHCP_OPT_IP_ADDRESS_LEASE_TIME,
Sergunb 0:8918a71cdbe9 747 &value, sizeof(value));
Sergunb 0:8918a71cdbe9 748 }
Sergunb 0:8918a71cdbe9 749
Sergunb 0:8918a71cdbe9 750 //Add Subnet Mask option
Sergunb 0:8918a71cdbe9 751 if(context->settings.subnetMask != IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 752 {
Sergunb 0:8918a71cdbe9 753 dhcpAddOption(reply, DHCP_OPT_SUBNET_MASK,
Sergunb 0:8918a71cdbe9 754 &context->settings.subnetMask, sizeof(Ipv4Addr));
Sergunb 0:8918a71cdbe9 755 }
Sergunb 0:8918a71cdbe9 756
Sergunb 0:8918a71cdbe9 757 //Add Router option
Sergunb 0:8918a71cdbe9 758 if(context->settings.defaultGateway != IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 759 {
Sergunb 0:8918a71cdbe9 760 dhcpAddOption(reply, DHCP_OPT_ROUTER,
Sergunb 0:8918a71cdbe9 761 &context->settings.defaultGateway, sizeof(Ipv4Addr));
Sergunb 0:8918a71cdbe9 762 }
Sergunb 0:8918a71cdbe9 763
Sergunb 0:8918a71cdbe9 764 //Retrieve the number of DNS servers
Sergunb 0:8918a71cdbe9 765 for(n = 0; n < DHCP_SERVER_MAX_DNS_SERVERS; n++)
Sergunb 0:8918a71cdbe9 766 {
Sergunb 0:8918a71cdbe9 767 //Check whether the current DNS server is valid
Sergunb 0:8918a71cdbe9 768 if(context->settings.dnsServer[n] == IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 769 break;
Sergunb 0:8918a71cdbe9 770 }
Sergunb 0:8918a71cdbe9 771
Sergunb 0:8918a71cdbe9 772 //Add DNS Server option
Sergunb 0:8918a71cdbe9 773 if(n > 0)
Sergunb 0:8918a71cdbe9 774 {
Sergunb 0:8918a71cdbe9 775 dhcpAddOption(reply, DHCP_OPT_DNS_SERVER,
Sergunb 0:8918a71cdbe9 776 context->settings.dnsServer, n * sizeof(Ipv4Addr));
Sergunb 0:8918a71cdbe9 777 }
Sergunb 0:8918a71cdbe9 778 }
Sergunb 0:8918a71cdbe9 779
Sergunb 0:8918a71cdbe9 780 //Check whether the 'giaddr' field is non-zero
Sergunb 0:8918a71cdbe9 781 if(request->giaddr != IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 782 {
Sergunb 0:8918a71cdbe9 783 //If the 'giaddr' field in a DHCP message from a client is non-zero,
Sergunb 0:8918a71cdbe9 784 //the server sends any return messages to the 'DHCP server' port
Sergunb 0:8918a71cdbe9 785 destPort = DHCP_SERVER_PORT;
Sergunb 0:8918a71cdbe9 786
Sergunb 0:8918a71cdbe9 787 //The DHCP message is sent to the BOOTP relay agent whose address
Sergunb 0:8918a71cdbe9 788 //appears in 'giaddr'
Sergunb 0:8918a71cdbe9 789 destIpAddr.length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 790 destIpAddr.ipv4Addr = request->giaddr;
Sergunb 0:8918a71cdbe9 791 }
Sergunb 0:8918a71cdbe9 792 else
Sergunb 0:8918a71cdbe9 793 {
Sergunb 0:8918a71cdbe9 794 //If the 'giaddr' field in a DHCP message from a client is zero,
Sergunb 0:8918a71cdbe9 795 //the server sends any return messages to the 'DHCP client'
Sergunb 0:8918a71cdbe9 796 destPort = DHCP_CLIENT_PORT;
Sergunb 0:8918a71cdbe9 797
Sergunb 0:8918a71cdbe9 798 //DHCPOFFER or DHCPACK message?
Sergunb 0:8918a71cdbe9 799 if(type == DHCP_MESSAGE_TYPE_OFFER || type == DHCP_MESSAGE_TYPE_ACK)
Sergunb 0:8918a71cdbe9 800 {
Sergunb 0:8918a71cdbe9 801 //Check whether the 'giaddr' field is non-zero
Sergunb 0:8918a71cdbe9 802 if(request->ciaddr != IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 803 {
Sergunb 0:8918a71cdbe9 804 //If the 'giaddr' field is zero and the 'ciaddr' field is nonzero,
Sergunb 0:8918a71cdbe9 805 //then the server unicasts DHCPOFFER and DHCPACK messages to the
Sergunb 0:8918a71cdbe9 806 //address in 'ciaddr'
Sergunb 0:8918a71cdbe9 807 destIpAddr.length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 808 destIpAddr.ipv4Addr = request->ciaddr;
Sergunb 0:8918a71cdbe9 809 }
Sergunb 0:8918a71cdbe9 810 else
Sergunb 0:8918a71cdbe9 811 {
Sergunb 0:8918a71cdbe9 812 //Check whether the broadcast bit is set
Sergunb 0:8918a71cdbe9 813 if(ntohs(request->flags) & DHCP_FLAG_BROADCAST)
Sergunb 0:8918a71cdbe9 814 {
Sergunb 0:8918a71cdbe9 815 //If 'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is
Sergunb 0:8918a71cdbe9 816 //set, then the server broadcasts DHCPOFFER and DHCPACK messages
Sergunb 0:8918a71cdbe9 817 destIpAddr.length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 818 destIpAddr.ipv4Addr = IPV4_BROADCAST_ADDR;
Sergunb 0:8918a71cdbe9 819 }
Sergunb 0:8918a71cdbe9 820 else
Sergunb 0:8918a71cdbe9 821 {
Sergunb 0:8918a71cdbe9 822 //If 'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is
Sergunb 0:8918a71cdbe9 823 //not set, then the server unicasts DHCPOFFER and DHCPACK messages
Sergunb 0:8918a71cdbe9 824 //to the client's hardware address and 'yiaddr' address
Sergunb 0:8918a71cdbe9 825 destIpAddr.length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 826 destIpAddr.ipv4Addr = IPV4_BROADCAST_ADDR;
Sergunb 0:8918a71cdbe9 827 }
Sergunb 0:8918a71cdbe9 828 }
Sergunb 0:8918a71cdbe9 829 }
Sergunb 0:8918a71cdbe9 830 //DHCPNAK message?
Sergunb 0:8918a71cdbe9 831 else
Sergunb 0:8918a71cdbe9 832 {
Sergunb 0:8918a71cdbe9 833 //In all cases, when 'giaddr' is zero, the server broadcasts any
Sergunb 0:8918a71cdbe9 834 //DHCPNAK messages
Sergunb 0:8918a71cdbe9 835 destIpAddr.length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 836 destIpAddr.ipv4Addr = IPV4_BROADCAST_ADDR;
Sergunb 0:8918a71cdbe9 837 }
Sergunb 0:8918a71cdbe9 838 }
Sergunb 0:8918a71cdbe9 839
Sergunb 0:8918a71cdbe9 840 //Debug message
Sergunb 0:8918a71cdbe9 841 TRACE_DEBUG("\r\n%s: Sending DHCP message (%" PRIuSIZE " bytes)...\r\n",
Sergunb 0:8918a71cdbe9 842 formatSystemTime(osGetSystemTime(), NULL), DHCP_MIN_MSG_SIZE);
Sergunb 0:8918a71cdbe9 843
Sergunb 0:8918a71cdbe9 844 //Dump the contents of the message for debugging purpose
Sergunb 0:8918a71cdbe9 845 dhcpDumpMessage(reply, DHCP_MIN_MSG_SIZE);
Sergunb 0:8918a71cdbe9 846
Sergunb 0:8918a71cdbe9 847 //Broadcast DHCPDECLINE message
Sergunb 0:8918a71cdbe9 848 error = udpSendDatagramEx(interface, DHCP_SERVER_PORT, &destIpAddr,
Sergunb 0:8918a71cdbe9 849 destPort, buffer, offset, IPV4_DEFAULT_TTL);
Sergunb 0:8918a71cdbe9 850
Sergunb 0:8918a71cdbe9 851 //Free previously allocated memory
Sergunb 0:8918a71cdbe9 852 netBufferFree(buffer);
Sergunb 0:8918a71cdbe9 853 //Return status code
Sergunb 0:8918a71cdbe9 854 return error;
Sergunb 0:8918a71cdbe9 855 }
Sergunb 0:8918a71cdbe9 856
Sergunb 0:8918a71cdbe9 857
Sergunb 0:8918a71cdbe9 858 /**
Sergunb 0:8918a71cdbe9 859 * @brief Create a new binding
Sergunb 0:8918a71cdbe9 860 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 861 * @return Pointer to the newly created binding
Sergunb 0:8918a71cdbe9 862 **/
Sergunb 0:8918a71cdbe9 863
Sergunb 0:8918a71cdbe9 864 DhcpServerBinding *dhcpServerCreateBinding(DhcpServerContext *context)
Sergunb 0:8918a71cdbe9 865 {
Sergunb 0:8918a71cdbe9 866 uint_t i;
Sergunb 0:8918a71cdbe9 867 DhcpServerBinding *binding;
Sergunb 0:8918a71cdbe9 868 DhcpServerBinding *oldestBinding;
Sergunb 0:8918a71cdbe9 869
Sergunb 0:8918a71cdbe9 870 //Keep track of the oldest binding
Sergunb 0:8918a71cdbe9 871 oldestBinding = NULL;
Sergunb 0:8918a71cdbe9 872
Sergunb 0:8918a71cdbe9 873 //Loop through the list of bindings
Sergunb 0:8918a71cdbe9 874 for(i = 0; i < DHCP_SERVER_MAX_CLIENTS; i++)
Sergunb 0:8918a71cdbe9 875 {
Sergunb 0:8918a71cdbe9 876 //Point to the current binding
Sergunb 0:8918a71cdbe9 877 binding = &context->clientBinding[i];
Sergunb 0:8918a71cdbe9 878
Sergunb 0:8918a71cdbe9 879 //Check whether the binding is available
Sergunb 0:8918a71cdbe9 880 if(macCompAddr(&binding->macAddr, &MAC_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 881 {
Sergunb 0:8918a71cdbe9 882 //Erase contents
Sergunb 0:8918a71cdbe9 883 memset(binding, 0, sizeof(DhcpServerBinding));
Sergunb 0:8918a71cdbe9 884 //Return a pointer to the newly created binding
Sergunb 0:8918a71cdbe9 885 return binding;
Sergunb 0:8918a71cdbe9 886 }
Sergunb 0:8918a71cdbe9 887 else
Sergunb 0:8918a71cdbe9 888 {
Sergunb 0:8918a71cdbe9 889 //Bindings that have been committed cannot be removed
Sergunb 0:8918a71cdbe9 890 if(!binding->validLease)
Sergunb 0:8918a71cdbe9 891 {
Sergunb 0:8918a71cdbe9 892 //Keep track of the oldest binding in the list
Sergunb 0:8918a71cdbe9 893 if(oldestBinding != NULL)
Sergunb 0:8918a71cdbe9 894 {
Sergunb 0:8918a71cdbe9 895 if(timeCompare(binding->timestamp, oldestBinding->timestamp) < 0)
Sergunb 0:8918a71cdbe9 896 oldestBinding = binding;
Sergunb 0:8918a71cdbe9 897 }
Sergunb 0:8918a71cdbe9 898 else
Sergunb 0:8918a71cdbe9 899 {
Sergunb 0:8918a71cdbe9 900 oldestBinding = binding;
Sergunb 0:8918a71cdbe9 901 }
Sergunb 0:8918a71cdbe9 902 }
Sergunb 0:8918a71cdbe9 903 }
Sergunb 0:8918a71cdbe9 904 }
Sergunb 0:8918a71cdbe9 905
Sergunb 0:8918a71cdbe9 906 //Any binding available in the list?
Sergunb 0:8918a71cdbe9 907 if(oldestBinding != NULL)
Sergunb 0:8918a71cdbe9 908 {
Sergunb 0:8918a71cdbe9 909 //Erase contents
Sergunb 0:8918a71cdbe9 910 memset(oldestBinding, 0, sizeof(DhcpServerBinding));
Sergunb 0:8918a71cdbe9 911 }
Sergunb 0:8918a71cdbe9 912
Sergunb 0:8918a71cdbe9 913 //Return a pointer to the oldest binding
Sergunb 0:8918a71cdbe9 914 return oldestBinding;
Sergunb 0:8918a71cdbe9 915 }
Sergunb 0:8918a71cdbe9 916
Sergunb 0:8918a71cdbe9 917
Sergunb 0:8918a71cdbe9 918 /**
Sergunb 0:8918a71cdbe9 919 * @brief Search the list of bindings for a given MAC address
Sergunb 0:8918a71cdbe9 920 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 921 * @param[in] macAddr MAC address
Sergunb 0:8918a71cdbe9 922 * @return Pointer to the corresponding DHCP binding
Sergunb 0:8918a71cdbe9 923 **/
Sergunb 0:8918a71cdbe9 924
Sergunb 0:8918a71cdbe9 925 DhcpServerBinding *dhcpServerFindBindingByMacAddr(DhcpServerContext *context,
Sergunb 0:8918a71cdbe9 926 const MacAddr* macAddr)
Sergunb 0:8918a71cdbe9 927 {
Sergunb 0:8918a71cdbe9 928 uint_t i;
Sergunb 0:8918a71cdbe9 929 DhcpServerBinding *binding;
Sergunb 0:8918a71cdbe9 930
Sergunb 0:8918a71cdbe9 931 //Loop through the list of bindings
Sergunb 0:8918a71cdbe9 932 for(i = 0; i < DHCP_SERVER_MAX_CLIENTS; i++)
Sergunb 0:8918a71cdbe9 933 {
Sergunb 0:8918a71cdbe9 934 //Point to the current binding
Sergunb 0:8918a71cdbe9 935 binding = &context->clientBinding[i];
Sergunb 0:8918a71cdbe9 936
Sergunb 0:8918a71cdbe9 937 //Valid binding?
Sergunb 0:8918a71cdbe9 938 if(!macCompAddr(&binding->macAddr, &MAC_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 939 {
Sergunb 0:8918a71cdbe9 940 //Check whether the current binding matches the specified MAC address
Sergunb 0:8918a71cdbe9 941 if(macCompAddr(&binding->macAddr, macAddr))
Sergunb 0:8918a71cdbe9 942 {
Sergunb 0:8918a71cdbe9 943 //Return the pointer to the corresponding binding
Sergunb 0:8918a71cdbe9 944 return binding;
Sergunb 0:8918a71cdbe9 945 }
Sergunb 0:8918a71cdbe9 946 }
Sergunb 0:8918a71cdbe9 947 }
Sergunb 0:8918a71cdbe9 948
Sergunb 0:8918a71cdbe9 949 //No matching binding...
Sergunb 0:8918a71cdbe9 950 return NULL;
Sergunb 0:8918a71cdbe9 951 }
Sergunb 0:8918a71cdbe9 952
Sergunb 0:8918a71cdbe9 953
Sergunb 0:8918a71cdbe9 954 /**
Sergunb 0:8918a71cdbe9 955 * @brief Search the list of bindings for a given IP address
Sergunb 0:8918a71cdbe9 956 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 957 * @param[in] ipAddr IP address
Sergunb 0:8918a71cdbe9 958 * @return Pointer to the corresponding DHCP binding
Sergunb 0:8918a71cdbe9 959 **/
Sergunb 0:8918a71cdbe9 960
Sergunb 0:8918a71cdbe9 961 DhcpServerBinding *dhcpServerFindBindingByIpAddr(DhcpServerContext *context,
Sergunb 0:8918a71cdbe9 962 Ipv4Addr ipAddr)
Sergunb 0:8918a71cdbe9 963 {
Sergunb 0:8918a71cdbe9 964 uint_t i;
Sergunb 0:8918a71cdbe9 965 DhcpServerBinding *binding;
Sergunb 0:8918a71cdbe9 966
Sergunb 0:8918a71cdbe9 967 //Loop through the list of bindings
Sergunb 0:8918a71cdbe9 968 for(i = 0; i < DHCP_SERVER_MAX_CLIENTS; i++)
Sergunb 0:8918a71cdbe9 969 {
Sergunb 0:8918a71cdbe9 970 //Point to the current binding
Sergunb 0:8918a71cdbe9 971 binding = &context->clientBinding[i];
Sergunb 0:8918a71cdbe9 972
Sergunb 0:8918a71cdbe9 973 //Valid binding?
Sergunb 0:8918a71cdbe9 974 if(!macCompAddr(&binding->macAddr, &MAC_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 975 {
Sergunb 0:8918a71cdbe9 976 //Check whether the current binding matches the specified IP address
Sergunb 0:8918a71cdbe9 977 if(binding->ipAddr == ipAddr)
Sergunb 0:8918a71cdbe9 978 {
Sergunb 0:8918a71cdbe9 979 //Return the pointer to the corresponding binding
Sergunb 0:8918a71cdbe9 980 return binding;
Sergunb 0:8918a71cdbe9 981 }
Sergunb 0:8918a71cdbe9 982 }
Sergunb 0:8918a71cdbe9 983 }
Sergunb 0:8918a71cdbe9 984
Sergunb 0:8918a71cdbe9 985 //No matching binding...
Sergunb 0:8918a71cdbe9 986 return NULL;
Sergunb 0:8918a71cdbe9 987 }
Sergunb 0:8918a71cdbe9 988
Sergunb 0:8918a71cdbe9 989
Sergunb 0:8918a71cdbe9 990 /**
Sergunb 0:8918a71cdbe9 991 * @brief Retrieve the next IP address to be used
Sergunb 0:8918a71cdbe9 992 * @param[in] context Pointer to the DHCP server context
Sergunb 0:8918a71cdbe9 993 * @param[out] ipAddr Next IP address to be used
Sergunb 0:8918a71cdbe9 994 * @return Error code
Sergunb 0:8918a71cdbe9 995 **/
Sergunb 0:8918a71cdbe9 996
Sergunb 0:8918a71cdbe9 997 error_t dhcpServerGetNextIpAddr(DhcpServerContext *context, Ipv4Addr *ipAddr)
Sergunb 0:8918a71cdbe9 998 {
Sergunb 0:8918a71cdbe9 999 uint_t i;
Sergunb 0:8918a71cdbe9 1000 DhcpServerBinding *binding;
Sergunb 0:8918a71cdbe9 1001
Sergunb 0:8918a71cdbe9 1002 //Search the pool for any available IP address
Sergunb 0:8918a71cdbe9 1003 for(i = 0; i < DHCP_SERVER_MAX_CLIENTS; i++)
Sergunb 0:8918a71cdbe9 1004 {
Sergunb 0:8918a71cdbe9 1005 //Check whether the current IP address is already allocated
Sergunb 0:8918a71cdbe9 1006 binding = dhcpServerFindBindingByIpAddr(context, context->nextIpAddr);
Sergunb 0:8918a71cdbe9 1007
Sergunb 0:8918a71cdbe9 1008 //If the IP address is available, then it can be assigned to a new client
Sergunb 0:8918a71cdbe9 1009 if(binding == NULL)
Sergunb 0:8918a71cdbe9 1010 *ipAddr = context->nextIpAddr;
Sergunb 0:8918a71cdbe9 1011
Sergunb 0:8918a71cdbe9 1012 //Compute the next IP address that will be assigned by the DHCP server
Sergunb 0:8918a71cdbe9 1013 if(ntohl(context->nextIpAddr) >= ntohl(context->settings.ipAddrRangeMax))
Sergunb 0:8918a71cdbe9 1014 {
Sergunb 0:8918a71cdbe9 1015 //Wrap around to the beginning of the pool
Sergunb 0:8918a71cdbe9 1016 context->nextIpAddr = context->settings.ipAddrRangeMin;
Sergunb 0:8918a71cdbe9 1017 }
Sergunb 0:8918a71cdbe9 1018 else
Sergunb 0:8918a71cdbe9 1019 {
Sergunb 0:8918a71cdbe9 1020 //Increment IP address
Sergunb 0:8918a71cdbe9 1021 context->nextIpAddr = htonl(ntohl(context->nextIpAddr) + 1);
Sergunb 0:8918a71cdbe9 1022 }
Sergunb 0:8918a71cdbe9 1023
Sergunb 0:8918a71cdbe9 1024 //If the IP address is available, we are done
Sergunb 0:8918a71cdbe9 1025 if(binding == NULL)
Sergunb 0:8918a71cdbe9 1026 return NO_ERROR;
Sergunb 0:8918a71cdbe9 1027 }
Sergunb 0:8918a71cdbe9 1028
Sergunb 0:8918a71cdbe9 1029 //No available addresses in the pool...
Sergunb 0:8918a71cdbe9 1030 return ERROR_NO_ADDRESS;
Sergunb 0:8918a71cdbe9 1031 }
Sergunb 0:8918a71cdbe9 1032
Sergunb 0:8918a71cdbe9 1033 #endif
Sergunb 0:8918a71cdbe9 1034