My fork of the HTTPServer (working)

Dependents:   DGWWebServer LAN2

Committer:
screamer
Date:
Mon Aug 06 09:23:14 2012 +0000
Revision:
0:7a64fbb4069d
[mbed] converted /DGWWebServer/HTTPServer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:7a64fbb4069d 1 /**
screamer 0:7a64fbb4069d 2 * @file
screamer 0:7a64fbb4069d 3 * AutoIP Automatic LinkLocal IP Configuration
screamer 0:7a64fbb4069d 4 *
screamer 0:7a64fbb4069d 5 */
screamer 0:7a64fbb4069d 6
screamer 0:7a64fbb4069d 7 /*
screamer 0:7a64fbb4069d 8 *
screamer 0:7a64fbb4069d 9 * Copyright (c) 2007 Dominik Spies <kontakt@dspies.de>
screamer 0:7a64fbb4069d 10 * All rights reserved.
screamer 0:7a64fbb4069d 11 *
screamer 0:7a64fbb4069d 12 * Redistribution and use in source and binary forms, with or without modification,
screamer 0:7a64fbb4069d 13 * are permitted provided that the following conditions are met:
screamer 0:7a64fbb4069d 14 *
screamer 0:7a64fbb4069d 15 * 1. Redistributions of source code must retain the above copyright notice,
screamer 0:7a64fbb4069d 16 * this list of conditions and the following disclaimer.
screamer 0:7a64fbb4069d 17 * 2. Redistributions in binary form must reproduce the above copyright notice,
screamer 0:7a64fbb4069d 18 * this list of conditions and the following disclaimer in the documentation
screamer 0:7a64fbb4069d 19 * and/or other materials provided with the distribution.
screamer 0:7a64fbb4069d 20 * 3. The name of the author may not be used to endorse or promote products
screamer 0:7a64fbb4069d 21 * derived from this software without specific prior written permission.
screamer 0:7a64fbb4069d 22 *
screamer 0:7a64fbb4069d 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
screamer 0:7a64fbb4069d 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
screamer 0:7a64fbb4069d 25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
screamer 0:7a64fbb4069d 26 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
screamer 0:7a64fbb4069d 27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
screamer 0:7a64fbb4069d 28 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
screamer 0:7a64fbb4069d 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
screamer 0:7a64fbb4069d 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
screamer 0:7a64fbb4069d 31 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
screamer 0:7a64fbb4069d 32 * OF SUCH DAMAGE.
screamer 0:7a64fbb4069d 33 *
screamer 0:7a64fbb4069d 34 * Author: Dominik Spies <kontakt@dspies.de>
screamer 0:7a64fbb4069d 35 *
screamer 0:7a64fbb4069d 36 * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform
screamer 0:7a64fbb4069d 37 * with RFC 3927.
screamer 0:7a64fbb4069d 38 *
screamer 0:7a64fbb4069d 39 *
screamer 0:7a64fbb4069d 40 * Please coordinate changes and requests with Dominik Spies
screamer 0:7a64fbb4069d 41 * <kontakt@dspies.de>
screamer 0:7a64fbb4069d 42 */
screamer 0:7a64fbb4069d 43
screamer 0:7a64fbb4069d 44 /*******************************************************************************
screamer 0:7a64fbb4069d 45 * USAGE:
screamer 0:7a64fbb4069d 46 *
screamer 0:7a64fbb4069d 47 * define LWIP_AUTOIP 1 in your lwipopts.h
screamer 0:7a64fbb4069d 48 *
screamer 0:7a64fbb4069d 49 * If you don't use tcpip.c (so, don't call, you don't call tcpip_init):
screamer 0:7a64fbb4069d 50 * - First, call autoip_init().
screamer 0:7a64fbb4069d 51 * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces,
screamer 0:7a64fbb4069d 52 * that should be defined in autoip.h.
screamer 0:7a64fbb4069d 53 * I recommend a value of 100. The value must divide 1000 with a remainder almost 0.
screamer 0:7a64fbb4069d 54 * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 ....
screamer 0:7a64fbb4069d 55 *
screamer 0:7a64fbb4069d 56 * Without DHCP:
screamer 0:7a64fbb4069d 57 * - Call autoip_start() after netif_add().
screamer 0:7a64fbb4069d 58 *
screamer 0:7a64fbb4069d 59 * With DHCP:
screamer 0:7a64fbb4069d 60 * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h.
screamer 0:7a64fbb4069d 61 * - Configure your DHCP Client.
screamer 0:7a64fbb4069d 62 *
screamer 0:7a64fbb4069d 63 */
screamer 0:7a64fbb4069d 64
screamer 0:7a64fbb4069d 65 #include "lwip/opt.h"
screamer 0:7a64fbb4069d 66
screamer 0:7a64fbb4069d 67 #if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
screamer 0:7a64fbb4069d 68
screamer 0:7a64fbb4069d 69 #include "lwip/mem.h"
screamer 0:7a64fbb4069d 70 #include "lwip/udp.h"
screamer 0:7a64fbb4069d 71 #include "lwip/ip_addr.h"
screamer 0:7a64fbb4069d 72 #include "lwip/netif.h"
screamer 0:7a64fbb4069d 73 #include "lwip/autoip.h"
screamer 0:7a64fbb4069d 74 #include "netif/etharp.h"
screamer 0:7a64fbb4069d 75
screamer 0:7a64fbb4069d 76 #include <stdlib.h>
screamer 0:7a64fbb4069d 77 #include <string.h>
screamer 0:7a64fbb4069d 78
screamer 0:7a64fbb4069d 79 /* 169.254.0.0 */
screamer 0:7a64fbb4069d 80 #define AUTOIP_NET 0xA9FE0000
screamer 0:7a64fbb4069d 81 /* 169.254.1.0 */
screamer 0:7a64fbb4069d 82 #define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100)
screamer 0:7a64fbb4069d 83 /* 169.254.254.255 */
screamer 0:7a64fbb4069d 84 #define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF)
screamer 0:7a64fbb4069d 85
screamer 0:7a64fbb4069d 86
screamer 0:7a64fbb4069d 87 /** Pseudo random macro based on netif informations.
screamer 0:7a64fbb4069d 88 * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */
screamer 0:7a64fbb4069d 89 #ifndef LWIP_AUTOIP_RAND
screamer 0:7a64fbb4069d 90 #define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
screamer 0:7a64fbb4069d 91 ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
screamer 0:7a64fbb4069d 92 ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
screamer 0:7a64fbb4069d 93 ((u32_t)((netif->hwaddr[4]) & 0xff))) + \
screamer 0:7a64fbb4069d 94 (netif->autoip?netif->autoip->tried_llipaddr:0))
screamer 0:7a64fbb4069d 95 #endif /* LWIP_AUTOIP_RAND */
screamer 0:7a64fbb4069d 96
screamer 0:7a64fbb4069d 97 /**
screamer 0:7a64fbb4069d 98 * Macro that generates the initial IP address to be tried by AUTOIP.
screamer 0:7a64fbb4069d 99 * If you want to override this, define it to something else in lwipopts.h.
screamer 0:7a64fbb4069d 100 */
screamer 0:7a64fbb4069d 101 #ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
screamer 0:7a64fbb4069d 102 #define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
screamer 0:7a64fbb4069d 103 (AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
screamer 0:7a64fbb4069d 104 ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
screamer 0:7a64fbb4069d 105 #endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
screamer 0:7a64fbb4069d 106
screamer 0:7a64fbb4069d 107 /* static functions */
screamer 0:7a64fbb4069d 108 static void autoip_handle_arp_conflict(struct netif *netif);
screamer 0:7a64fbb4069d 109
screamer 0:7a64fbb4069d 110 /* creates a pseudo random LL IP-Address for a network interface */
screamer 0:7a64fbb4069d 111 static void autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr);
screamer 0:7a64fbb4069d 112
screamer 0:7a64fbb4069d 113 /* sends an ARP announce */
screamer 0:7a64fbb4069d 114 static err_t autoip_arp_announce(struct netif *netif);
screamer 0:7a64fbb4069d 115
screamer 0:7a64fbb4069d 116 /* configure interface for use with current LL IP-Address */
screamer 0:7a64fbb4069d 117 static err_t autoip_bind(struct netif *netif);
screamer 0:7a64fbb4069d 118
screamer 0:7a64fbb4069d 119 /**
screamer 0:7a64fbb4069d 120 * Initialize this module
screamer 0:7a64fbb4069d 121 */
screamer 0:7a64fbb4069d 122 void
screamer 0:7a64fbb4069d 123 autoip_init(void)
screamer 0:7a64fbb4069d 124 {
screamer 0:7a64fbb4069d 125 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_init()\n"));
screamer 0:7a64fbb4069d 126 }
screamer 0:7a64fbb4069d 127
screamer 0:7a64fbb4069d 128 /**
screamer 0:7a64fbb4069d 129 * Handle a IP address conflict after an ARP conflict detection
screamer 0:7a64fbb4069d 130 */
screamer 0:7a64fbb4069d 131 static void
screamer 0:7a64fbb4069d 132 autoip_handle_arp_conflict(struct netif *netif)
screamer 0:7a64fbb4069d 133 {
screamer 0:7a64fbb4069d 134 /* Somehow detect if we are defending or retreating */
screamer 0:7a64fbb4069d 135 unsigned char defend = 1; /* tbd */
screamer 0:7a64fbb4069d 136
screamer 0:7a64fbb4069d 137 if(defend) {
screamer 0:7a64fbb4069d 138 if(netif->autoip->lastconflict > 0) {
screamer 0:7a64fbb4069d 139 /* retreat, there was a conflicting ARP in the last
screamer 0:7a64fbb4069d 140 * DEFEND_INTERVAL seconds
screamer 0:7a64fbb4069d 141 */
screamer 0:7a64fbb4069d 142 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
screamer 0:7a64fbb4069d 143 ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
screamer 0:7a64fbb4069d 144
screamer 0:7a64fbb4069d 145 /* TODO: close all TCP sessions */
screamer 0:7a64fbb4069d 146 autoip_start(netif);
screamer 0:7a64fbb4069d 147 } else {
screamer 0:7a64fbb4069d 148 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
screamer 0:7a64fbb4069d 149 ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
screamer 0:7a64fbb4069d 150 autoip_arp_announce(netif);
screamer 0:7a64fbb4069d 151 netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
screamer 0:7a64fbb4069d 152 }
screamer 0:7a64fbb4069d 153 } else {
screamer 0:7a64fbb4069d 154 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
screamer 0:7a64fbb4069d 155 ("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
screamer 0:7a64fbb4069d 156 /* TODO: close all TCP sessions */
screamer 0:7a64fbb4069d 157 autoip_start(netif);
screamer 0:7a64fbb4069d 158 }
screamer 0:7a64fbb4069d 159 }
screamer 0:7a64fbb4069d 160
screamer 0:7a64fbb4069d 161 /**
screamer 0:7a64fbb4069d 162 * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255
screamer 0:7a64fbb4069d 163 *
screamer 0:7a64fbb4069d 164 * @param netif network interface on which create the IP-Address
screamer 0:7a64fbb4069d 165 * @param IPAddr ip address to initialize
screamer 0:7a64fbb4069d 166 */
screamer 0:7a64fbb4069d 167 static void
screamer 0:7a64fbb4069d 168 autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr)
screamer 0:7a64fbb4069d 169 {
screamer 0:7a64fbb4069d 170 /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
screamer 0:7a64fbb4069d 171 * compliant to RFC 3927 Section 2.1
screamer 0:7a64fbb4069d 172 * We have 254 * 256 possibilities */
screamer 0:7a64fbb4069d 173
screamer 0:7a64fbb4069d 174 u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
screamer 0:7a64fbb4069d 175 addr += netif->autoip->tried_llipaddr;
screamer 0:7a64fbb4069d 176 addr = AUTOIP_NET | (addr & 0xffff);
screamer 0:7a64fbb4069d 177 /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
screamer 0:7a64fbb4069d 178
screamer 0:7a64fbb4069d 179 if (addr < AUTOIP_RANGE_START) {
screamer 0:7a64fbb4069d 180 addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
screamer 0:7a64fbb4069d 181 }
screamer 0:7a64fbb4069d 182 if (addr > AUTOIP_RANGE_END) {
screamer 0:7a64fbb4069d 183 addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
screamer 0:7a64fbb4069d 184 }
screamer 0:7a64fbb4069d 185 LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
screamer 0:7a64fbb4069d 186 (addr <= AUTOIP_RANGE_END));
screamer 0:7a64fbb4069d 187 IPAddr->addr = htonl(addr);
screamer 0:7a64fbb4069d 188
screamer 0:7a64fbb4069d 189 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
screamer 0:7a64fbb4069d 190 ("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
screamer 0:7a64fbb4069d 191 (u16_t)(netif->autoip->tried_llipaddr), (u32_t)(IPAddr->addr)));
screamer 0:7a64fbb4069d 192 }
screamer 0:7a64fbb4069d 193
screamer 0:7a64fbb4069d 194 /**
screamer 0:7a64fbb4069d 195 * Sends an ARP announce from a network interface
screamer 0:7a64fbb4069d 196 *
screamer 0:7a64fbb4069d 197 * @param netif network interface used to send the announce
screamer 0:7a64fbb4069d 198 */
screamer 0:7a64fbb4069d 199 static err_t
screamer 0:7a64fbb4069d 200 autoip_arp_announce(struct netif *netif)
screamer 0:7a64fbb4069d 201 {
screamer 0:7a64fbb4069d 202 return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
screamer 0:7a64fbb4069d 203 (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, &ethzero,
screamer 0:7a64fbb4069d 204 &netif->autoip->llipaddr, ARP_REQUEST);
screamer 0:7a64fbb4069d 205 }
screamer 0:7a64fbb4069d 206
screamer 0:7a64fbb4069d 207 /**
screamer 0:7a64fbb4069d 208 * Configure interface for use with current LL IP-Address
screamer 0:7a64fbb4069d 209 *
screamer 0:7a64fbb4069d 210 * @param netif network interface to configure with current LL IP-Address
screamer 0:7a64fbb4069d 211 */
screamer 0:7a64fbb4069d 212 static err_t
screamer 0:7a64fbb4069d 213 autoip_bind(struct netif *netif)
screamer 0:7a64fbb4069d 214 {
screamer 0:7a64fbb4069d 215 struct autoip *autoip = netif->autoip;
screamer 0:7a64fbb4069d 216 struct ip_addr sn_mask, gw_addr;
screamer 0:7a64fbb4069d 217
screamer 0:7a64fbb4069d 218 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
screamer 0:7a64fbb4069d 219 ("autoip_bind(netif=%p) %c%c%"U16_F" 0x%08"X32_F"\n",
screamer 0:7a64fbb4069d 220 (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, autoip->llipaddr.addr));
screamer 0:7a64fbb4069d 221
screamer 0:7a64fbb4069d 222 IP4_ADDR(&sn_mask, 255, 255, 0, 0);
screamer 0:7a64fbb4069d 223 IP4_ADDR(&gw_addr, 0, 0, 0, 0);
screamer 0:7a64fbb4069d 224
screamer 0:7a64fbb4069d 225 netif_set_ipaddr(netif, &autoip->llipaddr);
screamer 0:7a64fbb4069d 226 netif_set_netmask(netif, &sn_mask);
screamer 0:7a64fbb4069d 227 netif_set_gw(netif, &gw_addr);
screamer 0:7a64fbb4069d 228
screamer 0:7a64fbb4069d 229 /* bring the interface up */
screamer 0:7a64fbb4069d 230 netif_set_up(netif);
screamer 0:7a64fbb4069d 231
screamer 0:7a64fbb4069d 232 return ERR_OK;
screamer 0:7a64fbb4069d 233 }
screamer 0:7a64fbb4069d 234
screamer 0:7a64fbb4069d 235 /**
screamer 0:7a64fbb4069d 236 * Start AutoIP client
screamer 0:7a64fbb4069d 237 *
screamer 0:7a64fbb4069d 238 * @param netif network interface on which start the AutoIP client
screamer 0:7a64fbb4069d 239 */
screamer 0:7a64fbb4069d 240 err_t
screamer 0:7a64fbb4069d 241 autoip_start(struct netif *netif)
screamer 0:7a64fbb4069d 242 {
screamer 0:7a64fbb4069d 243 struct autoip *autoip = netif->autoip;
screamer 0:7a64fbb4069d 244 err_t result = ERR_OK;
screamer 0:7a64fbb4069d 245
screamer 0:7a64fbb4069d 246 if(netif_is_up(netif)) {
screamer 0:7a64fbb4069d 247 netif_set_down(netif);
screamer 0:7a64fbb4069d 248 }
screamer 0:7a64fbb4069d 249
screamer 0:7a64fbb4069d 250 /* Set IP-Address, Netmask and Gateway to 0 to make sure that
screamer 0:7a64fbb4069d 251 * ARP Packets are formed correctly
screamer 0:7a64fbb4069d 252 */
screamer 0:7a64fbb4069d 253 netif->ip_addr.addr = 0;
screamer 0:7a64fbb4069d 254 netif->netmask.addr = 0;
screamer 0:7a64fbb4069d 255 netif->gw.addr = 0;
screamer 0:7a64fbb4069d 256
screamer 0:7a64fbb4069d 257 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
screamer 0:7a64fbb4069d 258 ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
screamer 0:7a64fbb4069d 259 netif->name[1], (u16_t)netif->num));
screamer 0:7a64fbb4069d 260 if(autoip == NULL) {
screamer 0:7a64fbb4069d 261 /* no AutoIP client attached yet? */
screamer 0:7a64fbb4069d 262 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
screamer 0:7a64fbb4069d 263 ("autoip_start(): starting new AUTOIP client\n"));
screamer 0:7a64fbb4069d 264 autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); // static_cast<struct autoip *>(x)
screamer 0:7a64fbb4069d 265 if(autoip == NULL) {
screamer 0:7a64fbb4069d 266 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
screamer 0:7a64fbb4069d 267 ("autoip_start(): could not allocate autoip\n"));
screamer 0:7a64fbb4069d 268 return ERR_MEM;
screamer 0:7a64fbb4069d 269 }
screamer 0:7a64fbb4069d 270 memset( autoip, 0, sizeof(struct autoip));
screamer 0:7a64fbb4069d 271 /* store this AutoIP client in the netif */
screamer 0:7a64fbb4069d 272 netif->autoip = autoip;
screamer 0:7a64fbb4069d 273 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
screamer 0:7a64fbb4069d 274 } else {
screamer 0:7a64fbb4069d 275 autoip->state = AUTOIP_STATE_OFF;
screamer 0:7a64fbb4069d 276 autoip->ttw = 0;
screamer 0:7a64fbb4069d 277 autoip->sent_num = 0;
screamer 0:7a64fbb4069d 278 memset(&autoip->llipaddr, 0, sizeof(struct ip_addr));
screamer 0:7a64fbb4069d 279 autoip->lastconflict = 0;
screamer 0:7a64fbb4069d 280 }
screamer 0:7a64fbb4069d 281
screamer 0:7a64fbb4069d 282 autoip_create_addr(netif, &(autoip->llipaddr));
screamer 0:7a64fbb4069d 283 autoip->tried_llipaddr++;
screamer 0:7a64fbb4069d 284 autoip->state = AUTOIP_STATE_PROBING;
screamer 0:7a64fbb4069d 285 autoip->sent_num = 0;
screamer 0:7a64fbb4069d 286
screamer 0:7a64fbb4069d 287 /* time to wait to first probe, this is randomly
screamer 0:7a64fbb4069d 288 * choosen out of 0 to PROBE_WAIT seconds.
screamer 0:7a64fbb4069d 289 * compliant to RFC 3927 Section 2.2.1
screamer 0:7a64fbb4069d 290 */
screamer 0:7a64fbb4069d 291 autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND));
screamer 0:7a64fbb4069d 292
screamer 0:7a64fbb4069d 293 /*
screamer 0:7a64fbb4069d 294 * if we tried more then MAX_CONFLICTS we must limit our rate for
screamer 0:7a64fbb4069d 295 * accquiring and probing address
screamer 0:7a64fbb4069d 296 * compliant to RFC 3927 Section 2.2.1
screamer 0:7a64fbb4069d 297 */
screamer 0:7a64fbb4069d 298
screamer 0:7a64fbb4069d 299 if(autoip->tried_llipaddr > MAX_CONFLICTS) {
screamer 0:7a64fbb4069d 300 autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
screamer 0:7a64fbb4069d 301 }
screamer 0:7a64fbb4069d 302
screamer 0:7a64fbb4069d 303 return result;
screamer 0:7a64fbb4069d 304 }
screamer 0:7a64fbb4069d 305
screamer 0:7a64fbb4069d 306 /**
screamer 0:7a64fbb4069d 307 * Stop AutoIP client
screamer 0:7a64fbb4069d 308 *
screamer 0:7a64fbb4069d 309 * @param netif network interface on which stop the AutoIP client
screamer 0:7a64fbb4069d 310 */
screamer 0:7a64fbb4069d 311 err_t
screamer 0:7a64fbb4069d 312 autoip_stop(struct netif *netif)
screamer 0:7a64fbb4069d 313 {
screamer 0:7a64fbb4069d 314 netif->autoip->state = AUTOIP_STATE_OFF;
screamer 0:7a64fbb4069d 315 netif_set_down(netif);
screamer 0:7a64fbb4069d 316 return ERR_OK;
screamer 0:7a64fbb4069d 317 }
screamer 0:7a64fbb4069d 318
screamer 0:7a64fbb4069d 319 /**
screamer 0:7a64fbb4069d 320 * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds
screamer 0:7a64fbb4069d 321 */
screamer 0:7a64fbb4069d 322 void
screamer 0:7a64fbb4069d 323 autoip_tmr()
screamer 0:7a64fbb4069d 324 {
screamer 0:7a64fbb4069d 325 struct netif *netif = netif_list;
screamer 0:7a64fbb4069d 326 /* loop through netif's */
screamer 0:7a64fbb4069d 327 while (netif != NULL) {
screamer 0:7a64fbb4069d 328 /* only act on AutoIP configured interfaces */
screamer 0:7a64fbb4069d 329 if (netif->autoip != NULL) {
screamer 0:7a64fbb4069d 330 if(netif->autoip->lastconflict > 0) {
screamer 0:7a64fbb4069d 331 netif->autoip->lastconflict--;
screamer 0:7a64fbb4069d 332 }
screamer 0:7a64fbb4069d 333
screamer 0:7a64fbb4069d 334 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
screamer 0:7a64fbb4069d 335 ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n",
screamer 0:7a64fbb4069d 336 (u16_t)(netif->autoip->state), netif->autoip->ttw));
screamer 0:7a64fbb4069d 337
screamer 0:7a64fbb4069d 338 switch(netif->autoip->state) {
screamer 0:7a64fbb4069d 339 case AUTOIP_STATE_PROBING:
screamer 0:7a64fbb4069d 340 if(netif->autoip->ttw > 0) {
screamer 0:7a64fbb4069d 341 netif->autoip->ttw--;
screamer 0:7a64fbb4069d 342 } else {
screamer 0:7a64fbb4069d 343 if(netif->autoip->sent_num == PROBE_NUM) {
screamer 0:7a64fbb4069d 344 netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
screamer 0:7a64fbb4069d 345 netif->autoip->sent_num = 0;
screamer 0:7a64fbb4069d 346 netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
screamer 0:7a64fbb4069d 347 } else {
screamer 0:7a64fbb4069d 348 etharp_request(netif, &(netif->autoip->llipaddr));
screamer 0:7a64fbb4069d 349 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
screamer 0:7a64fbb4069d 350 ("autoip_tmr() PROBING Sent Probe\n"));
screamer 0:7a64fbb4069d 351 netif->autoip->sent_num++;
screamer 0:7a64fbb4069d 352 /* calculate time to wait to next probe */
screamer 0:7a64fbb4069d 353 netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
screamer 0:7a64fbb4069d 354 ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) +
screamer 0:7a64fbb4069d 355 PROBE_MIN * AUTOIP_TICKS_PER_SECOND);
screamer 0:7a64fbb4069d 356 }
screamer 0:7a64fbb4069d 357 }
screamer 0:7a64fbb4069d 358 break;
screamer 0:7a64fbb4069d 359
screamer 0:7a64fbb4069d 360 case AUTOIP_STATE_ANNOUNCING:
screamer 0:7a64fbb4069d 361 if(netif->autoip->ttw > 0) {
screamer 0:7a64fbb4069d 362 netif->autoip->ttw--;
screamer 0:7a64fbb4069d 363 } else {
screamer 0:7a64fbb4069d 364 if(netif->autoip->sent_num == 0) {
screamer 0:7a64fbb4069d 365 /* We are here the first time, so we waited ANNOUNCE_WAIT seconds
screamer 0:7a64fbb4069d 366 * Now we can bind to an IP address and use it
screamer 0:7a64fbb4069d 367 */
screamer 0:7a64fbb4069d 368 autoip_bind(netif);
screamer 0:7a64fbb4069d 369 }
screamer 0:7a64fbb4069d 370
screamer 0:7a64fbb4069d 371 if(netif->autoip->sent_num == ANNOUNCE_NUM) {
screamer 0:7a64fbb4069d 372 netif->autoip->state = AUTOIP_STATE_BOUND;
screamer 0:7a64fbb4069d 373 netif->autoip->sent_num = 0;
screamer 0:7a64fbb4069d 374 netif->autoip->ttw = 0;
screamer 0:7a64fbb4069d 375 } else {
screamer 0:7a64fbb4069d 376 autoip_arp_announce(netif);
screamer 0:7a64fbb4069d 377 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
screamer 0:7a64fbb4069d 378 ("autoip_tmr() ANNOUNCING Sent Announce\n"));
screamer 0:7a64fbb4069d 379 netif->autoip->sent_num++;
screamer 0:7a64fbb4069d 380 netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
screamer 0:7a64fbb4069d 381 }
screamer 0:7a64fbb4069d 382 }
screamer 0:7a64fbb4069d 383 break;
screamer 0:7a64fbb4069d 384 }
screamer 0:7a64fbb4069d 385 }
screamer 0:7a64fbb4069d 386 /* proceed to next network interface */
screamer 0:7a64fbb4069d 387 netif = netif->next;
screamer 0:7a64fbb4069d 388 }
screamer 0:7a64fbb4069d 389 }
screamer 0:7a64fbb4069d 390
screamer 0:7a64fbb4069d 391 /**
screamer 0:7a64fbb4069d 392 * Handles every incoming ARP Packet, called by etharp_arp_input.
screamer 0:7a64fbb4069d 393 *
screamer 0:7a64fbb4069d 394 * @param netif network interface to use for autoip processing
screamer 0:7a64fbb4069d 395 * @param hdr Incoming ARP packet
screamer 0:7a64fbb4069d 396 */
screamer 0:7a64fbb4069d 397 void
screamer 0:7a64fbb4069d 398 autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
screamer 0:7a64fbb4069d 399 {
screamer 0:7a64fbb4069d 400 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_arp_reply()\n"));
screamer 0:7a64fbb4069d 401 if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) {
screamer 0:7a64fbb4069d 402 /* when ip.src == llipaddr && hw.src != netif->hwaddr
screamer 0:7a64fbb4069d 403 *
screamer 0:7a64fbb4069d 404 * when probing ip.dst == llipaddr && hw.src != netif->hwaddr
screamer 0:7a64fbb4069d 405 * we have a conflict and must solve it
screamer 0:7a64fbb4069d 406 */
screamer 0:7a64fbb4069d 407 struct ip_addr sipaddr, dipaddr;
screamer 0:7a64fbb4069d 408 struct eth_addr netifaddr;
screamer 0:7a64fbb4069d 409 netifaddr.addr[0] = netif->hwaddr[0];
screamer 0:7a64fbb4069d 410 netifaddr.addr[1] = netif->hwaddr[1];
screamer 0:7a64fbb4069d 411 netifaddr.addr[2] = netif->hwaddr[2];
screamer 0:7a64fbb4069d 412 netifaddr.addr[3] = netif->hwaddr[3];
screamer 0:7a64fbb4069d 413 netifaddr.addr[4] = netif->hwaddr[4];
screamer 0:7a64fbb4069d 414 netifaddr.addr[5] = netif->hwaddr[5];
screamer 0:7a64fbb4069d 415
screamer 0:7a64fbb4069d 416 /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
screamer 0:7a64fbb4069d 417 * structure packing (not using structure copy which breaks strict-aliasing rules).
screamer 0:7a64fbb4069d 418 */
screamer 0:7a64fbb4069d 419 SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
screamer 0:7a64fbb4069d 420 SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
screamer 0:7a64fbb4069d 421
screamer 0:7a64fbb4069d 422 if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
screamer 0:7a64fbb4069d 423 ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
screamer 0:7a64fbb4069d 424 (netif->autoip->sent_num == 0))) {
screamer 0:7a64fbb4069d 425 /* RFC 3927 Section 2.2.1:
screamer 0:7a64fbb4069d 426 * from beginning to after ANNOUNCE_WAIT
screamer 0:7a64fbb4069d 427 * seconds we have a conflict if
screamer 0:7a64fbb4069d 428 * ip.src == llipaddr OR
screamer 0:7a64fbb4069d 429 * ip.dst == llipaddr && hw.src != own hwaddr
screamer 0:7a64fbb4069d 430 */
screamer 0:7a64fbb4069d 431 if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) ||
screamer 0:7a64fbb4069d 432 (ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) &&
screamer 0:7a64fbb4069d 433 !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
screamer 0:7a64fbb4069d 434 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
screamer 0:7a64fbb4069d 435 ("autoip_arp_reply(): Probe Conflict detected\n"));
screamer 0:7a64fbb4069d 436 autoip_start(netif);
screamer 0:7a64fbb4069d 437 }
screamer 0:7a64fbb4069d 438 } else {
screamer 0:7a64fbb4069d 439 /* RFC 3927 Section 2.5:
screamer 0:7a64fbb4069d 440 * in any state we have a conflict if
screamer 0:7a64fbb4069d 441 * ip.src == llipaddr && hw.src != own hwaddr
screamer 0:7a64fbb4069d 442 */
screamer 0:7a64fbb4069d 443 if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) &&
screamer 0:7a64fbb4069d 444 !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
screamer 0:7a64fbb4069d 445 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
screamer 0:7a64fbb4069d 446 ("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
screamer 0:7a64fbb4069d 447 autoip_handle_arp_conflict(netif);
screamer 0:7a64fbb4069d 448 }
screamer 0:7a64fbb4069d 449 }
screamer 0:7a64fbb4069d 450 }
screamer 0:7a64fbb4069d 451 }
screamer 0:7a64fbb4069d 452
screamer 0:7a64fbb4069d 453 #endif /* LWIP_AUTOIP */