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 auto_ip.c
Sergunb 0:8918a71cdbe9 3 * @brief Auto-IP (Dynamic Configuration of IPv4 Link-Local Addresses)
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 * Auto-IP describes a method by which a host may automatically configure an
Sergunb 0:8918a71cdbe9 28 * interface with an IPv4 address in the 169.254/16 prefix that is valid for
Sergunb 0:8918a71cdbe9 29 * Link-Local communication on that interface. This is especially valuable in
Sergunb 0:8918a71cdbe9 30 * environments where no other configuration mechanism is available. Refer to
Sergunb 0:8918a71cdbe9 31 * the following RFCs for complete details:
Sergunb 0:8918a71cdbe9 32 * - RFC 3927: Dynamic Configuration of IPv4 Link-Local Addresses
Sergunb 0:8918a71cdbe9 33 * - RFC 5227: IPv4 Address Conflict Detection
Sergunb 0:8918a71cdbe9 34 *
Sergunb 0:8918a71cdbe9 35 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 36 * @version 1.7.6
Sergunb 0:8918a71cdbe9 37 **/
Sergunb 0:8918a71cdbe9 38
Sergunb 0:8918a71cdbe9 39 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 40 #define TRACE_LEVEL AUTO_IP_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 41
Sergunb 0:8918a71cdbe9 42 //Dependencies
Sergunb 0:8918a71cdbe9 43 #include "core/net.h"
Sergunb 0:8918a71cdbe9 44 #include "core/ethernet.h"
Sergunb 0:8918a71cdbe9 45 #include "ipv4/arp.h"
Sergunb 0:8918a71cdbe9 46 #include "ipv4/auto_ip.h"
Sergunb 0:8918a71cdbe9 47 #include "mdns/mdns_responder.h"
Sergunb 0:8918a71cdbe9 48 #include "debug.h"
Sergunb 0:8918a71cdbe9 49
Sergunb 0:8918a71cdbe9 50 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 51 #if (IPV4_SUPPORT == ENABLED && AUTO_IP_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 52
Sergunb 0:8918a71cdbe9 53 //Tick counter to handle periodic operations
Sergunb 0:8918a71cdbe9 54 systime_t autoIpTickCounter;
Sergunb 0:8918a71cdbe9 55
Sergunb 0:8918a71cdbe9 56
Sergunb 0:8918a71cdbe9 57 /**
Sergunb 0:8918a71cdbe9 58 * @brief Initialize settings with default values
Sergunb 0:8918a71cdbe9 59 * @param[out] settings Structure that contains Auto-IP settings
Sergunb 0:8918a71cdbe9 60 **/
Sergunb 0:8918a71cdbe9 61
Sergunb 0:8918a71cdbe9 62 void autoIpGetDefaultSettings(AutoIpSettings *settings)
Sergunb 0:8918a71cdbe9 63 {
Sergunb 0:8918a71cdbe9 64 //Use default interface
Sergunb 0:8918a71cdbe9 65 settings->interface = netGetDefaultInterface();
Sergunb 0:8918a71cdbe9 66
Sergunb 0:8918a71cdbe9 67 //Initial link-local address to be used
Sergunb 0:8918a71cdbe9 68 settings->linkLocalAddr = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 69 //Link state change event
Sergunb 0:8918a71cdbe9 70 settings->linkChangeEvent = NULL;
Sergunb 0:8918a71cdbe9 71 //FSM state change event
Sergunb 0:8918a71cdbe9 72 settings->stateChangeEvent = NULL;
Sergunb 0:8918a71cdbe9 73 }
Sergunb 0:8918a71cdbe9 74
Sergunb 0:8918a71cdbe9 75
Sergunb 0:8918a71cdbe9 76 /**
Sergunb 0:8918a71cdbe9 77 * @brief Auto-IP initialization
Sergunb 0:8918a71cdbe9 78 * @param[in] context Pointer to the Auto-IP context
Sergunb 0:8918a71cdbe9 79 * @param[in] settings Auto-IP specific settings
Sergunb 0:8918a71cdbe9 80 * @return Error code
Sergunb 0:8918a71cdbe9 81 **/
Sergunb 0:8918a71cdbe9 82
Sergunb 0:8918a71cdbe9 83 error_t autoIpInit(AutoIpContext *context, const AutoIpSettings *settings)
Sergunb 0:8918a71cdbe9 84 {
Sergunb 0:8918a71cdbe9 85 NetInterface *interface;
Sergunb 0:8918a71cdbe9 86
Sergunb 0:8918a71cdbe9 87 //Debug message
Sergunb 0:8918a71cdbe9 88 TRACE_INFO("Initializing Auto-IP...\r\n");
Sergunb 0:8918a71cdbe9 89
Sergunb 0:8918a71cdbe9 90 //Ensure the parameters are valid
Sergunb 0:8918a71cdbe9 91 if(context == NULL || settings == NULL)
Sergunb 0:8918a71cdbe9 92 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 93
Sergunb 0:8918a71cdbe9 94 //A valid pointer to the interface being configured is required
Sergunb 0:8918a71cdbe9 95 if(settings->interface == NULL)
Sergunb 0:8918a71cdbe9 96 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 97
Sergunb 0:8918a71cdbe9 98 //Point to the underlying network interface
Sergunb 0:8918a71cdbe9 99 interface = settings->interface;
Sergunb 0:8918a71cdbe9 100
Sergunb 0:8918a71cdbe9 101 //Clear the Auto-IP context
Sergunb 0:8918a71cdbe9 102 memset(context, 0, sizeof(AutoIpContext));
Sergunb 0:8918a71cdbe9 103 //Save user settings
Sergunb 0:8918a71cdbe9 104 context->settings = *settings;
Sergunb 0:8918a71cdbe9 105
Sergunb 0:8918a71cdbe9 106 //Use default link-local address
Sergunb 0:8918a71cdbe9 107 context->linkLocalAddr = settings->linkLocalAddr;
Sergunb 0:8918a71cdbe9 108 //Reset conflict counter
Sergunb 0:8918a71cdbe9 109 context->conflictCount = 0;
Sergunb 0:8918a71cdbe9 110
Sergunb 0:8918a71cdbe9 111 //Auto-IP operation is currently suspended
Sergunb 0:8918a71cdbe9 112 context->running = FALSE;
Sergunb 0:8918a71cdbe9 113 //Initialize state machine
Sergunb 0:8918a71cdbe9 114 context->state = AUTO_IP_STATE_INIT;
Sergunb 0:8918a71cdbe9 115
Sergunb 0:8918a71cdbe9 116 //Attach the Auto-IP context to the network interface
Sergunb 0:8918a71cdbe9 117 interface->autoIpContext = context;
Sergunb 0:8918a71cdbe9 118
Sergunb 0:8918a71cdbe9 119 //Successful initialization
Sergunb 0:8918a71cdbe9 120 return NO_ERROR;
Sergunb 0:8918a71cdbe9 121 }
Sergunb 0:8918a71cdbe9 122
Sergunb 0:8918a71cdbe9 123
Sergunb 0:8918a71cdbe9 124 /**
Sergunb 0:8918a71cdbe9 125 * @brief Start Auto-IP process
Sergunb 0:8918a71cdbe9 126 * @param[in] context Pointer to the Auto-IP context
Sergunb 0:8918a71cdbe9 127 * @return Error code
Sergunb 0:8918a71cdbe9 128 **/
Sergunb 0:8918a71cdbe9 129
Sergunb 0:8918a71cdbe9 130 error_t autoIpStart(AutoIpContext *context)
Sergunb 0:8918a71cdbe9 131 {
Sergunb 0:8918a71cdbe9 132 //Check parameter
Sergunb 0:8918a71cdbe9 133 if(context == NULL)
Sergunb 0:8918a71cdbe9 134 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 135
Sergunb 0:8918a71cdbe9 136 //Debug message
Sergunb 0:8918a71cdbe9 137 TRACE_INFO("Starting Auto-IP...\r\n");
Sergunb 0:8918a71cdbe9 138
Sergunb 0:8918a71cdbe9 139 //Get exclusive access
Sergunb 0:8918a71cdbe9 140 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 141
Sergunb 0:8918a71cdbe9 142 //Start Auto-IP operation
Sergunb 0:8918a71cdbe9 143 context->running = TRUE;
Sergunb 0:8918a71cdbe9 144 //Initialize state machine
Sergunb 0:8918a71cdbe9 145 context->state = AUTO_IP_STATE_INIT;
Sergunb 0:8918a71cdbe9 146 //Reset conflict counter
Sergunb 0:8918a71cdbe9 147 context->conflictCount = 0;
Sergunb 0:8918a71cdbe9 148
Sergunb 0:8918a71cdbe9 149 //Release exclusive access
Sergunb 0:8918a71cdbe9 150 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 151
Sergunb 0:8918a71cdbe9 152 //Successful processing
Sergunb 0:8918a71cdbe9 153 return NO_ERROR;
Sergunb 0:8918a71cdbe9 154 }
Sergunb 0:8918a71cdbe9 155
Sergunb 0:8918a71cdbe9 156
Sergunb 0:8918a71cdbe9 157 /**
Sergunb 0:8918a71cdbe9 158 * @brief Stop Auto-IP process
Sergunb 0:8918a71cdbe9 159 * @param[in] context Pointer to the Auto-IP context
Sergunb 0:8918a71cdbe9 160 * @return Error code
Sergunb 0:8918a71cdbe9 161 **/
Sergunb 0:8918a71cdbe9 162
Sergunb 0:8918a71cdbe9 163 error_t autoIpStop(AutoIpContext *context)
Sergunb 0:8918a71cdbe9 164 {
Sergunb 0:8918a71cdbe9 165 //Check parameter
Sergunb 0:8918a71cdbe9 166 if(context == NULL)
Sergunb 0:8918a71cdbe9 167 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 168
Sergunb 0:8918a71cdbe9 169 //Debug message
Sergunb 0:8918a71cdbe9 170 TRACE_INFO("Stopping Auto-IP...\r\n");
Sergunb 0:8918a71cdbe9 171
Sergunb 0:8918a71cdbe9 172 //Get exclusive access
Sergunb 0:8918a71cdbe9 173 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 174
Sergunb 0:8918a71cdbe9 175 //Suspend Auto-IP operation
Sergunb 0:8918a71cdbe9 176 context->running = FALSE;
Sergunb 0:8918a71cdbe9 177 //Reinitialize state machine
Sergunb 0:8918a71cdbe9 178 context->state = AUTO_IP_STATE_INIT;
Sergunb 0:8918a71cdbe9 179
Sergunb 0:8918a71cdbe9 180 //Release exclusive access
Sergunb 0:8918a71cdbe9 181 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 182
Sergunb 0:8918a71cdbe9 183 //Successful processing
Sergunb 0:8918a71cdbe9 184 return NO_ERROR;
Sergunb 0:8918a71cdbe9 185 }
Sergunb 0:8918a71cdbe9 186
Sergunb 0:8918a71cdbe9 187
Sergunb 0:8918a71cdbe9 188 /**
Sergunb 0:8918a71cdbe9 189 * @brief Retrieve current state
Sergunb 0:8918a71cdbe9 190 * @param[in] context Pointer to the Auto-IP context
Sergunb 0:8918a71cdbe9 191 * @return Current Auto-IP state
Sergunb 0:8918a71cdbe9 192 **/
Sergunb 0:8918a71cdbe9 193
Sergunb 0:8918a71cdbe9 194 AutoIpState autoIpGetState(AutoIpContext *context)
Sergunb 0:8918a71cdbe9 195 {
Sergunb 0:8918a71cdbe9 196 AutoIpState state;
Sergunb 0:8918a71cdbe9 197
Sergunb 0:8918a71cdbe9 198 //Get exclusive access
Sergunb 0:8918a71cdbe9 199 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 200 //Get current state
Sergunb 0:8918a71cdbe9 201 state = context->state;
Sergunb 0:8918a71cdbe9 202 //Release exclusive access
Sergunb 0:8918a71cdbe9 203 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 204
Sergunb 0:8918a71cdbe9 205 //Return current state
Sergunb 0:8918a71cdbe9 206 return state;
Sergunb 0:8918a71cdbe9 207 }
Sergunb 0:8918a71cdbe9 208
Sergunb 0:8918a71cdbe9 209
Sergunb 0:8918a71cdbe9 210 /**
Sergunb 0:8918a71cdbe9 211 * @brief Auto-IP timer handler
Sergunb 0:8918a71cdbe9 212 *
Sergunb 0:8918a71cdbe9 213 * This routine must be periodically called by the TCP/IP stack to
Sergunb 0:8918a71cdbe9 214 * manage Auto-IP operation
Sergunb 0:8918a71cdbe9 215 *
Sergunb 0:8918a71cdbe9 216 * @param[in] context Pointer to the Auto-IP context
Sergunb 0:8918a71cdbe9 217 **/
Sergunb 0:8918a71cdbe9 218
Sergunb 0:8918a71cdbe9 219 void autoIpTick(AutoIpContext *context)
Sergunb 0:8918a71cdbe9 220 {
Sergunb 0:8918a71cdbe9 221 systime_t time;
Sergunb 0:8918a71cdbe9 222 systime_t delay;
Sergunb 0:8918a71cdbe9 223 NetInterface *interface;
Sergunb 0:8918a71cdbe9 224
Sergunb 0:8918a71cdbe9 225 //Make sure Auto-IP has been properly instantiated
Sergunb 0:8918a71cdbe9 226 if(context == NULL)
Sergunb 0:8918a71cdbe9 227 return;
Sergunb 0:8918a71cdbe9 228
Sergunb 0:8918a71cdbe9 229 //Point to the underlying network interface
Sergunb 0:8918a71cdbe9 230 interface = context->settings.interface;
Sergunb 0:8918a71cdbe9 231
Sergunb 0:8918a71cdbe9 232 //Get current time
Sergunb 0:8918a71cdbe9 233 time = osGetSystemTime();
Sergunb 0:8918a71cdbe9 234
Sergunb 0:8918a71cdbe9 235 //Check current state
Sergunb 0:8918a71cdbe9 236 if(context->state == AUTO_IP_STATE_INIT)
Sergunb 0:8918a71cdbe9 237 {
Sergunb 0:8918a71cdbe9 238 //Wait for the link to be up before starting Auto-IP
Sergunb 0:8918a71cdbe9 239 if(context->running && interface->linkState)
Sergunb 0:8918a71cdbe9 240 {
Sergunb 0:8918a71cdbe9 241 //Configure subnet mask
Sergunb 0:8918a71cdbe9 242 interface->ipv4Context.subnetMask = AUTO_IP_MASK;
Sergunb 0:8918a71cdbe9 243
Sergunb 0:8918a71cdbe9 244 //The address must be in the range from 169.54.1.0 to 169.254.254.255
Sergunb 0:8918a71cdbe9 245 if(ntohl(context->linkLocalAddr) < ntohl(AUTO_IP_ADDR_MIN) ||
Sergunb 0:8918a71cdbe9 246 ntohl(context->linkLocalAddr) > ntohl(AUTO_IP_ADDR_MAX))
Sergunb 0:8918a71cdbe9 247 {
Sergunb 0:8918a71cdbe9 248 //Generate a random link-local address
Sergunb 0:8918a71cdbe9 249 autoIpGenerateAddr(&context->linkLocalAddr);
Sergunb 0:8918a71cdbe9 250 }
Sergunb 0:8918a71cdbe9 251
Sergunb 0:8918a71cdbe9 252 //Use the link-local address as a tentative address
Sergunb 0:8918a71cdbe9 253 interface->ipv4Context.addr = context->linkLocalAddr;
Sergunb 0:8918a71cdbe9 254 interface->ipv4Context.addrState = IPV4_ADDR_STATE_TENTATIVE;
Sergunb 0:8918a71cdbe9 255
Sergunb 0:8918a71cdbe9 256 //Clear conflict flag
Sergunb 0:8918a71cdbe9 257 interface->ipv4Context.addrConflict = FALSE;
Sergunb 0:8918a71cdbe9 258
Sergunb 0:8918a71cdbe9 259 //Initial random delay
Sergunb 0:8918a71cdbe9 260 delay = netGetRandRange(0, AUTO_IP_PROBE_WAIT);
Sergunb 0:8918a71cdbe9 261
Sergunb 0:8918a71cdbe9 262 //The number of conflicts exceeds the maximum acceptable value?
Sergunb 0:8918a71cdbe9 263 if(context->conflictCount >= AUTO_IP_MAX_CONFLICTS)
Sergunb 0:8918a71cdbe9 264 {
Sergunb 0:8918a71cdbe9 265 //The host must limit the rate at which it probes for new addresses
Sergunb 0:8918a71cdbe9 266 delay += AUTO_IP_RATE_LIMIT_INTERVAL;
Sergunb 0:8918a71cdbe9 267 }
Sergunb 0:8918a71cdbe9 268
Sergunb 0:8918a71cdbe9 269 //Verify the uniqueness of the link-local address
Sergunb 0:8918a71cdbe9 270 autoIpChangeState(context, AUTO_IP_STATE_PROBING, delay);
Sergunb 0:8918a71cdbe9 271 }
Sergunb 0:8918a71cdbe9 272 }
Sergunb 0:8918a71cdbe9 273 else if(context->state == AUTO_IP_STATE_PROBING)
Sergunb 0:8918a71cdbe9 274 {
Sergunb 0:8918a71cdbe9 275 //Any conflict detected?
Sergunb 0:8918a71cdbe9 276 if(interface->ipv4Context.addrConflict)
Sergunb 0:8918a71cdbe9 277 {
Sergunb 0:8918a71cdbe9 278 //The address is already in use by some other host and
Sergunb 0:8918a71cdbe9 279 //must not be assigned to the interface
Sergunb 0:8918a71cdbe9 280 interface->ipv4Context.addr = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 281 interface->ipv4Context.addrState = IPV4_ADDR_STATE_INVALID;
Sergunb 0:8918a71cdbe9 282
Sergunb 0:8918a71cdbe9 283 //The host should maintain a counter of the number of address
Sergunb 0:8918a71cdbe9 284 //conflicts it has experienced
Sergunb 0:8918a71cdbe9 285 context->conflictCount++;
Sergunb 0:8918a71cdbe9 286
Sergunb 0:8918a71cdbe9 287 //The host must pick a new random address...
Sergunb 0:8918a71cdbe9 288 autoIpGenerateAddr(&context->linkLocalAddr);
Sergunb 0:8918a71cdbe9 289 //...and repeat the process
Sergunb 0:8918a71cdbe9 290 autoIpChangeState(context, AUTO_IP_STATE_INIT, 0);
Sergunb 0:8918a71cdbe9 291 }
Sergunb 0:8918a71cdbe9 292 else
Sergunb 0:8918a71cdbe9 293 {
Sergunb 0:8918a71cdbe9 294 //Check current time
Sergunb 0:8918a71cdbe9 295 if(timeCompare(time, context->timestamp + context->timeout) >= 0)
Sergunb 0:8918a71cdbe9 296 {
Sergunb 0:8918a71cdbe9 297 //Address Conflict Detection is on-going?
Sergunb 0:8918a71cdbe9 298 if(context->retransmitCount < AUTO_IP_PROBE_NUM)
Sergunb 0:8918a71cdbe9 299 {
Sergunb 0:8918a71cdbe9 300 //Conflict detection is done using ARP probes
Sergunb 0:8918a71cdbe9 301 arpSendProbe(interface, context->linkLocalAddr);
Sergunb 0:8918a71cdbe9 302
Sergunb 0:8918a71cdbe9 303 //Save the time at which the packet was sent
Sergunb 0:8918a71cdbe9 304 context->timestamp = time;
Sergunb 0:8918a71cdbe9 305 //Increment retransmission counter
Sergunb 0:8918a71cdbe9 306 context->retransmitCount++;
Sergunb 0:8918a71cdbe9 307
Sergunb 0:8918a71cdbe9 308 //Last probe packet sent?
Sergunb 0:8918a71cdbe9 309 if(context->retransmitCount == AUTO_IP_PROBE_NUM)
Sergunb 0:8918a71cdbe9 310 {
Sergunb 0:8918a71cdbe9 311 //Delay before announcing
Sergunb 0:8918a71cdbe9 312 context->timeout = AUTO_IP_ANNOUNCE_WAIT;
Sergunb 0:8918a71cdbe9 313 }
Sergunb 0:8918a71cdbe9 314 else
Sergunb 0:8918a71cdbe9 315 {
Sergunb 0:8918a71cdbe9 316 //Maximum delay till repeated probe
Sergunb 0:8918a71cdbe9 317 context->timeout = netGetRandRange(AUTO_IP_PROBE_MIN,
Sergunb 0:8918a71cdbe9 318 AUTO_IP_PROBE_MAX);
Sergunb 0:8918a71cdbe9 319 }
Sergunb 0:8918a71cdbe9 320 }
Sergunb 0:8918a71cdbe9 321 else
Sergunb 0:8918a71cdbe9 322 {
Sergunb 0:8918a71cdbe9 323 //The use of the IPv4 address is now unrestricted
Sergunb 0:8918a71cdbe9 324 interface->ipv4Context.addrState = IPV4_ADDR_STATE_VALID;
Sergunb 0:8918a71cdbe9 325
Sergunb 0:8918a71cdbe9 326 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 327 //Restart mDNS probing process
Sergunb 0:8918a71cdbe9 328 mdnsResponderStartProbing(interface->mdnsResponderContext);
Sergunb 0:8918a71cdbe9 329 #endif
Sergunb 0:8918a71cdbe9 330 //The host must then announce its claimed address
Sergunb 0:8918a71cdbe9 331 autoIpChangeState(context, AUTO_IP_STATE_ANNOUNCING, 0);
Sergunb 0:8918a71cdbe9 332 }
Sergunb 0:8918a71cdbe9 333 }
Sergunb 0:8918a71cdbe9 334 }
Sergunb 0:8918a71cdbe9 335 }
Sergunb 0:8918a71cdbe9 336 else if(context->state == AUTO_IP_STATE_ANNOUNCING)
Sergunb 0:8918a71cdbe9 337 {
Sergunb 0:8918a71cdbe9 338 //Check current time
Sergunb 0:8918a71cdbe9 339 if(timeCompare(time, context->timestamp + context->timeout) >= 0)
Sergunb 0:8918a71cdbe9 340 {
Sergunb 0:8918a71cdbe9 341 //An ARP announcement is identical to an ARP probe, except that
Sergunb 0:8918a71cdbe9 342 //now the sender and target IP addresses are both set to the
Sergunb 0:8918a71cdbe9 343 //host's newly selected IPv4 address
Sergunb 0:8918a71cdbe9 344 arpSendRequest(interface, context->linkLocalAddr, &MAC_BROADCAST_ADDR);
Sergunb 0:8918a71cdbe9 345
Sergunb 0:8918a71cdbe9 346 //Save the time at which the packet was sent
Sergunb 0:8918a71cdbe9 347 context->timestamp = time;
Sergunb 0:8918a71cdbe9 348 //Time interval between announcement packets
Sergunb 0:8918a71cdbe9 349 context->timeout = AUTO_IP_ANNOUNCE_INTERVAL;
Sergunb 0:8918a71cdbe9 350 //Increment retransmission counter
Sergunb 0:8918a71cdbe9 351 context->retransmitCount++;
Sergunb 0:8918a71cdbe9 352
Sergunb 0:8918a71cdbe9 353 //Announcing is complete?
Sergunb 0:8918a71cdbe9 354 if(context->retransmitCount >= AUTO_IP_ANNOUNCE_NUM)
Sergunb 0:8918a71cdbe9 355 {
Sergunb 0:8918a71cdbe9 356 //Successful address autoconfiguration
Sergunb 0:8918a71cdbe9 357 autoIpChangeState(context, AUTO_IP_STATE_CONFIGURED, 0);
Sergunb 0:8918a71cdbe9 358 //Reset conflict counter
Sergunb 0:8918a71cdbe9 359 context->conflictCount = 0;
Sergunb 0:8918a71cdbe9 360
Sergunb 0:8918a71cdbe9 361 //Dump current IPv4 configuration for debugging purpose
Sergunb 0:8918a71cdbe9 362 autoIpDumpConfig(context);
Sergunb 0:8918a71cdbe9 363 }
Sergunb 0:8918a71cdbe9 364 }
Sergunb 0:8918a71cdbe9 365 }
Sergunb 0:8918a71cdbe9 366 else if(context->state == AUTO_IP_STATE_CONFIGURED)
Sergunb 0:8918a71cdbe9 367 {
Sergunb 0:8918a71cdbe9 368 //Address Conflict Detection is an ongoing process that is in effect
Sergunb 0:8918a71cdbe9 369 //for as long as a host is using an IPv4 link-local address
Sergunb 0:8918a71cdbe9 370 if(interface->ipv4Context.addrConflict)
Sergunb 0:8918a71cdbe9 371 {
Sergunb 0:8918a71cdbe9 372 //The host may elect to attempt to defend its address by recording
Sergunb 0:8918a71cdbe9 373 //the time that the conflicting ARP packet was received, and then
Sergunb 0:8918a71cdbe9 374 //broadcasting one single ARP announcement, giving its own IP and
Sergunb 0:8918a71cdbe9 375 //hardware addresses as the sender addresses of the ARP
Sergunb 0:8918a71cdbe9 376 #if (AUTO_IP_BCT_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 377 arpSendProbe(interface, context->linkLocalAddr);
Sergunb 0:8918a71cdbe9 378 #else
Sergunb 0:8918a71cdbe9 379 arpSendRequest(interface, context->linkLocalAddr, &MAC_BROADCAST_ADDR);
Sergunb 0:8918a71cdbe9 380 #endif
Sergunb 0:8918a71cdbe9 381 //Clear conflict flag
Sergunb 0:8918a71cdbe9 382 interface->ipv4Context.addrConflict = FALSE;
Sergunb 0:8918a71cdbe9 383
Sergunb 0:8918a71cdbe9 384 //The host can then continue to use the address normally without
Sergunb 0:8918a71cdbe9 385 //any further special action
Sergunb 0:8918a71cdbe9 386 autoIpChangeState(context, AUTO_IP_STATE_DEFENDING, 0);
Sergunb 0:8918a71cdbe9 387 }
Sergunb 0:8918a71cdbe9 388 }
Sergunb 0:8918a71cdbe9 389 else if(context->state == AUTO_IP_STATE_DEFENDING)
Sergunb 0:8918a71cdbe9 390 {
Sergunb 0:8918a71cdbe9 391 //if this is not the first conflicting ARP packet the host has seen, and
Sergunb 0:8918a71cdbe9 392 //the time recorded for the previous conflicting ARP packet is recent,
Sergunb 0:8918a71cdbe9 393 //within DEFEND_INTERVAL seconds, then the host must immediately cease
Sergunb 0:8918a71cdbe9 394 //using this address
Sergunb 0:8918a71cdbe9 395 if(interface->ipv4Context.addrConflict)
Sergunb 0:8918a71cdbe9 396 {
Sergunb 0:8918a71cdbe9 397 //The link-local address cannot be used anymore
Sergunb 0:8918a71cdbe9 398 interface->ipv4Context.addr = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 399 interface->ipv4Context.addrState = IPV4_ADDR_STATE_INVALID;
Sergunb 0:8918a71cdbe9 400
Sergunb 0:8918a71cdbe9 401 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 402 //Restart mDNS probing process
Sergunb 0:8918a71cdbe9 403 mdnsResponderStartProbing(interface->mdnsResponderContext);
Sergunb 0:8918a71cdbe9 404 #endif
Sergunb 0:8918a71cdbe9 405 //The host must pick a new random address...
Sergunb 0:8918a71cdbe9 406 autoIpGenerateAddr(&context->linkLocalAddr);
Sergunb 0:8918a71cdbe9 407 //...and probes/announces again
Sergunb 0:8918a71cdbe9 408 autoIpChangeState(context, AUTO_IP_STATE_INIT, 0);
Sergunb 0:8918a71cdbe9 409 }
Sergunb 0:8918a71cdbe9 410 else
Sergunb 0:8918a71cdbe9 411 {
Sergunb 0:8918a71cdbe9 412 //Check whether the DEFEND_INTERVAL has elapsed
Sergunb 0:8918a71cdbe9 413 if(timeCompare(time, context->timestamp + AUTO_IP_DEFEND_INTERVAL) >= 0)
Sergunb 0:8918a71cdbe9 414 {
Sergunb 0:8918a71cdbe9 415 //The host can continue to use its link-local address
Sergunb 0:8918a71cdbe9 416 autoIpChangeState(context, AUTO_IP_STATE_CONFIGURED, 0);
Sergunb 0:8918a71cdbe9 417 }
Sergunb 0:8918a71cdbe9 418 }
Sergunb 0:8918a71cdbe9 419 }
Sergunb 0:8918a71cdbe9 420 }
Sergunb 0:8918a71cdbe9 421
Sergunb 0:8918a71cdbe9 422
Sergunb 0:8918a71cdbe9 423 /**
Sergunb 0:8918a71cdbe9 424 * @brief Callback function for link change event
Sergunb 0:8918a71cdbe9 425 * @param[in] context Pointer to the Auto-IP context
Sergunb 0:8918a71cdbe9 426 **/
Sergunb 0:8918a71cdbe9 427
Sergunb 0:8918a71cdbe9 428 void autoIpLinkChangeEvent(AutoIpContext *context)
Sergunb 0:8918a71cdbe9 429 {
Sergunb 0:8918a71cdbe9 430 NetInterface *interface;
Sergunb 0:8918a71cdbe9 431
Sergunb 0:8918a71cdbe9 432 //Make sure Auto-IP has been properly instantiated
Sergunb 0:8918a71cdbe9 433 if(context == NULL)
Sergunb 0:8918a71cdbe9 434 return;
Sergunb 0:8918a71cdbe9 435
Sergunb 0:8918a71cdbe9 436 //Point to the underlying network interface
Sergunb 0:8918a71cdbe9 437 interface = context->settings.interface;
Sergunb 0:8918a71cdbe9 438
Sergunb 0:8918a71cdbe9 439 //Check whether Auto-IP is enabled
Sergunb 0:8918a71cdbe9 440 if(context->running)
Sergunb 0:8918a71cdbe9 441 {
Sergunb 0:8918a71cdbe9 442 //The host address is not longer valid
Sergunb 0:8918a71cdbe9 443 interface->ipv4Context.addr = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 444 interface->ipv4Context.addrState = IPV4_ADDR_STATE_INVALID;
Sergunb 0:8918a71cdbe9 445
Sergunb 0:8918a71cdbe9 446 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 447 //Restart mDNS probing process
Sergunb 0:8918a71cdbe9 448 mdnsResponderStartProbing(interface->mdnsResponderContext);
Sergunb 0:8918a71cdbe9 449 #endif
Sergunb 0:8918a71cdbe9 450
Sergunb 0:8918a71cdbe9 451 //Clear subnet mask
Sergunb 0:8918a71cdbe9 452 interface->ipv4Context.subnetMask = IPV4_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 453 }
Sergunb 0:8918a71cdbe9 454
Sergunb 0:8918a71cdbe9 455 //Reinitialize state machine
Sergunb 0:8918a71cdbe9 456 context->state = AUTO_IP_STATE_INIT;
Sergunb 0:8918a71cdbe9 457 //Reset conflict counter
Sergunb 0:8918a71cdbe9 458 context->conflictCount = 0;
Sergunb 0:8918a71cdbe9 459
Sergunb 0:8918a71cdbe9 460 //Any registered callback?
Sergunb 0:8918a71cdbe9 461 if(context->settings.linkChangeEvent != NULL)
Sergunb 0:8918a71cdbe9 462 {
Sergunb 0:8918a71cdbe9 463 //Release exclusive access
Sergunb 0:8918a71cdbe9 464 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 465 //Invoke user callback function
Sergunb 0:8918a71cdbe9 466 context->settings.linkChangeEvent(context, interface, interface->linkState);
Sergunb 0:8918a71cdbe9 467 //Get exclusive access
Sergunb 0:8918a71cdbe9 468 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 469 }
Sergunb 0:8918a71cdbe9 470 }
Sergunb 0:8918a71cdbe9 471
Sergunb 0:8918a71cdbe9 472
Sergunb 0:8918a71cdbe9 473 /**
Sergunb 0:8918a71cdbe9 474 * @brief Update Auto-IP FSM state
Sergunb 0:8918a71cdbe9 475 * @param[in] context Pointer to the Auto-IP context
Sergunb 0:8918a71cdbe9 476 * @param[in] newState New Auto-IP state to switch to
Sergunb 0:8918a71cdbe9 477 * @param[in] delay Initial delay
Sergunb 0:8918a71cdbe9 478 **/
Sergunb 0:8918a71cdbe9 479
Sergunb 0:8918a71cdbe9 480 void autoIpChangeState(AutoIpContext *context,
Sergunb 0:8918a71cdbe9 481 AutoIpState newState, systime_t delay)
Sergunb 0:8918a71cdbe9 482 {
Sergunb 0:8918a71cdbe9 483 NetInterface *interface;
Sergunb 0:8918a71cdbe9 484
Sergunb 0:8918a71cdbe9 485 //Point to the underlying network interface
Sergunb 0:8918a71cdbe9 486 interface = context->settings.interface;
Sergunb 0:8918a71cdbe9 487
Sergunb 0:8918a71cdbe9 488 //Set time stamp
Sergunb 0:8918a71cdbe9 489 context->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 490 //Set initial delay
Sergunb 0:8918a71cdbe9 491 context->timeout = delay;
Sergunb 0:8918a71cdbe9 492 //Reset retransmission counter
Sergunb 0:8918a71cdbe9 493 context->retransmitCount = 0;
Sergunb 0:8918a71cdbe9 494 //Switch to the new state
Sergunb 0:8918a71cdbe9 495 context->state = newState;
Sergunb 0:8918a71cdbe9 496
Sergunb 0:8918a71cdbe9 497 //Any registered callback?
Sergunb 0:8918a71cdbe9 498 if(context->settings.stateChangeEvent != NULL)
Sergunb 0:8918a71cdbe9 499 {
Sergunb 0:8918a71cdbe9 500 //Release exclusive access
Sergunb 0:8918a71cdbe9 501 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 502 //Invoke user callback function
Sergunb 0:8918a71cdbe9 503 context->settings.stateChangeEvent(context, interface, newState);
Sergunb 0:8918a71cdbe9 504 //Get exclusive access
Sergunb 0:8918a71cdbe9 505 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 506 }
Sergunb 0:8918a71cdbe9 507 }
Sergunb 0:8918a71cdbe9 508
Sergunb 0:8918a71cdbe9 509
Sergunb 0:8918a71cdbe9 510 /**
Sergunb 0:8918a71cdbe9 511 * @brief Generate a random link-local address
Sergunb 0:8918a71cdbe9 512 * @param[out] ipAddr Random link-local address
Sergunb 0:8918a71cdbe9 513 **/
Sergunb 0:8918a71cdbe9 514
Sergunb 0:8918a71cdbe9 515 void autoIpGenerateAddr(Ipv4Addr *ipAddr)
Sergunb 0:8918a71cdbe9 516 {
Sergunb 0:8918a71cdbe9 517 uint32_t n;
Sergunb 0:8918a71cdbe9 518
Sergunb 0:8918a71cdbe9 519 //Generate a random address in the range from 169.254.1.0 to 169.254.254.255
Sergunb 0:8918a71cdbe9 520 n = netGetRand() % ntohl(AUTO_IP_ADDR_MAX - AUTO_IP_ADDR_MIN);
Sergunb 0:8918a71cdbe9 521 n += ntohl(AUTO_IP_ADDR_MIN);
Sergunb 0:8918a71cdbe9 522
Sergunb 0:8918a71cdbe9 523 //Convert the resulting address to network byte order
Sergunb 0:8918a71cdbe9 524 *ipAddr = htonl(n);
Sergunb 0:8918a71cdbe9 525 }
Sergunb 0:8918a71cdbe9 526
Sergunb 0:8918a71cdbe9 527
Sergunb 0:8918a71cdbe9 528 /**
Sergunb 0:8918a71cdbe9 529 * @brief Dump Auto-IP configuration for debugging purpose
Sergunb 0:8918a71cdbe9 530 * @param[in] context Pointer to the Auto-IP context
Sergunb 0:8918a71cdbe9 531 **/
Sergunb 0:8918a71cdbe9 532
Sergunb 0:8918a71cdbe9 533 void autoIpDumpConfig(AutoIpContext *context)
Sergunb 0:8918a71cdbe9 534 {
Sergunb 0:8918a71cdbe9 535 #if (AUTO_IP_TRACE_LEVEL >= TRACE_LEVEL_INFO)
Sergunb 0:8918a71cdbe9 536 NetInterface *interface;
Sergunb 0:8918a71cdbe9 537 Ipv4Context *ipv4Context;
Sergunb 0:8918a71cdbe9 538
Sergunb 0:8918a71cdbe9 539 //Point to the underlying network interface
Sergunb 0:8918a71cdbe9 540 interface = context->settings.interface;
Sergunb 0:8918a71cdbe9 541 //Point to the IPv4 context
Sergunb 0:8918a71cdbe9 542 ipv4Context = &interface->ipv4Context;
Sergunb 0:8918a71cdbe9 543
Sergunb 0:8918a71cdbe9 544 //Debug message
Sergunb 0:8918a71cdbe9 545 TRACE_INFO("\r\n");
Sergunb 0:8918a71cdbe9 546 TRACE_INFO("Auto-IP configuration:\r\n");
Sergunb 0:8918a71cdbe9 547
Sergunb 0:8918a71cdbe9 548 //Link-local address
Sergunb 0:8918a71cdbe9 549 TRACE_INFO(" Link-local Address = %s\r\n",
Sergunb 0:8918a71cdbe9 550 ipv4AddrToString(ipv4Context->addr, NULL));
Sergunb 0:8918a71cdbe9 551
Sergunb 0:8918a71cdbe9 552 //Subnet mask
Sergunb 0:8918a71cdbe9 553 TRACE_INFO(" Subnet Mask = %s\r\n",
Sergunb 0:8918a71cdbe9 554 ipv4AddrToString(ipv4Context->subnetMask, NULL));
Sergunb 0:8918a71cdbe9 555
Sergunb 0:8918a71cdbe9 556 //Debug message
Sergunb 0:8918a71cdbe9 557 TRACE_INFO("\r\n");
Sergunb 0:8918a71cdbe9 558 #endif
Sergunb 0:8918a71cdbe9 559 }
Sergunb 0:8918a71cdbe9 560
Sergunb 0:8918a71cdbe9 561 #endif
Sergunb 0:8918a71cdbe9 562