Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

Committer:
rrajan8
Date:
Wed Mar 06 19:07:23 2013 +0000
Revision:
8:92b57208ab99
Parent:
0:ac1725ba162c
This project utilizes mbed's networking features to display live traffic updates on the Nokia LCD using the MapQuest API's Traffic Web Service.

Who changed what in which revision?

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