1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * AutoIP Automatic LinkLocal IP Configuration 4195972f6Sopenharmony_ci * 5195972f6Sopenharmony_ci * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform 6195972f6Sopenharmony_ci * with RFC 3927. 7195972f6Sopenharmony_ci * 8195972f6Sopenharmony_ci * @defgroup autoip AUTOIP 9195972f6Sopenharmony_ci * @ingroup ip4 10195972f6Sopenharmony_ci * AUTOIP related functions 11195972f6Sopenharmony_ci * USAGE: 12195972f6Sopenharmony_ci * 13195972f6Sopenharmony_ci * define @ref LWIP_AUTOIP 1 in your lwipopts.h 14195972f6Sopenharmony_ci * Options: 15195972f6Sopenharmony_ci * AUTOIP_TMR_INTERVAL msecs, 16195972f6Sopenharmony_ci * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. 17195972f6Sopenharmony_ci * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... 18195972f6Sopenharmony_ci * 19195972f6Sopenharmony_ci * Without DHCP: 20195972f6Sopenharmony_ci * - Call autoip_start() after netif_add(). 21195972f6Sopenharmony_ci * 22195972f6Sopenharmony_ci * With DHCP: 23195972f6Sopenharmony_ci * - define @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. 24195972f6Sopenharmony_ci * - Configure your DHCP Client. 25195972f6Sopenharmony_ci * 26195972f6Sopenharmony_ci * @see netifapi_autoip 27195972f6Sopenharmony_ci */ 28195972f6Sopenharmony_ci 29195972f6Sopenharmony_ci/* 30195972f6Sopenharmony_ci * 31195972f6Sopenharmony_ci * Copyright (c) 2007 Dominik Spies <kontakt@dspies.de> 32195972f6Sopenharmony_ci * All rights reserved. 33195972f6Sopenharmony_ci * 34195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 35195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 36195972f6Sopenharmony_ci * 37195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 38195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 39195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 40195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 41195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 42195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 43195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 44195972f6Sopenharmony_ci * 45195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 46195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 47195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 48195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 49195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 50195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 51195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 52195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 53195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 54195972f6Sopenharmony_ci * OF SUCH DAMAGE. 55195972f6Sopenharmony_ci * 56195972f6Sopenharmony_ci * Author: Dominik Spies <kontakt@dspies.de> 57195972f6Sopenharmony_ci */ 58195972f6Sopenharmony_ci 59195972f6Sopenharmony_ci#include "lwip/opt.h" 60195972f6Sopenharmony_ci 61195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ 62195972f6Sopenharmony_ci 63195972f6Sopenharmony_ci#include "lwip/mem.h" 64195972f6Sopenharmony_ci/* #include "lwip/udp.h" */ 65195972f6Sopenharmony_ci#include "lwip/ip_addr.h" 66195972f6Sopenharmony_ci#include "lwip/netif.h" 67195972f6Sopenharmony_ci#include "lwip/autoip.h" 68195972f6Sopenharmony_ci#include "lwip/etharp.h" 69195972f6Sopenharmony_ci#include "lwip/prot/autoip.h" 70195972f6Sopenharmony_ci 71195972f6Sopenharmony_ci#include <string.h> 72195972f6Sopenharmony_ci 73195972f6Sopenharmony_ci/** Pseudo random macro based on netif informations. 74195972f6Sopenharmony_ci * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ 75195972f6Sopenharmony_ci#ifndef LWIP_AUTOIP_RAND 76195972f6Sopenharmony_ci#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ 77195972f6Sopenharmony_ci ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ 78195972f6Sopenharmony_ci ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ 79195972f6Sopenharmony_ci ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ 80195972f6Sopenharmony_ci (netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0)) 81195972f6Sopenharmony_ci#endif /* LWIP_AUTOIP_RAND */ 82195972f6Sopenharmony_ci 83195972f6Sopenharmony_ci/** 84195972f6Sopenharmony_ci * Macro that generates the initial IP address to be tried by AUTOIP. 85195972f6Sopenharmony_ci * If you want to override this, define it to something else in lwipopts.h. 86195972f6Sopenharmony_ci */ 87195972f6Sopenharmony_ci#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR 88195972f6Sopenharmony_ci#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ 89195972f6Sopenharmony_ci lwip_htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ 90195972f6Sopenharmony_ci ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) 91195972f6Sopenharmony_ci#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ 92195972f6Sopenharmony_ci 93195972f6Sopenharmony_ci/* static functions */ 94195972f6Sopenharmony_cistatic err_t autoip_arp_announce(struct netif *netif); 95195972f6Sopenharmony_cistatic void autoip_start_probing(struct netif *netif); 96195972f6Sopenharmony_ci 97195972f6Sopenharmony_ci/** 98195972f6Sopenharmony_ci * @ingroup autoip 99195972f6Sopenharmony_ci * Set a statically allocated struct autoip to work with. 100195972f6Sopenharmony_ci * Using this prevents autoip_start to allocate it using mem_malloc. 101195972f6Sopenharmony_ci * 102195972f6Sopenharmony_ci * @param netif the netif for which to set the struct autoip 103195972f6Sopenharmony_ci * @param autoip (uninitialised) autoip struct allocated by the application 104195972f6Sopenharmony_ci */ 105195972f6Sopenharmony_civoid 106195972f6Sopenharmony_ciautoip_set_struct(struct netif *netif, struct autoip *autoip) 107195972f6Sopenharmony_ci{ 108195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 109195972f6Sopenharmony_ci LWIP_ASSERT("netif != NULL", netif != NULL); 110195972f6Sopenharmony_ci LWIP_ASSERT("autoip != NULL", autoip != NULL); 111195972f6Sopenharmony_ci LWIP_ASSERT("netif already has a struct autoip set", 112195972f6Sopenharmony_ci netif_autoip_data(netif) == NULL); 113195972f6Sopenharmony_ci 114195972f6Sopenharmony_ci /* clear data structure */ 115195972f6Sopenharmony_ci memset(autoip, 0, sizeof(struct autoip)); 116195972f6Sopenharmony_ci /* autoip->state = AUTOIP_STATE_OFF; */ 117195972f6Sopenharmony_ci netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); 118195972f6Sopenharmony_ci} 119195972f6Sopenharmony_ci 120195972f6Sopenharmony_ci/** Restart AutoIP client and check the next address (conflict detected) 121195972f6Sopenharmony_ci * 122195972f6Sopenharmony_ci * @param netif The netif under AutoIP control 123195972f6Sopenharmony_ci */ 124195972f6Sopenharmony_cistatic void 125195972f6Sopenharmony_ciautoip_restart(struct netif *netif) 126195972f6Sopenharmony_ci{ 127195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 128195972f6Sopenharmony_ci autoip->tried_llipaddr++; 129195972f6Sopenharmony_ci autoip_start(netif); 130195972f6Sopenharmony_ci} 131195972f6Sopenharmony_ci 132195972f6Sopenharmony_ci/** 133195972f6Sopenharmony_ci * Handle a IP address conflict after an ARP conflict detection 134195972f6Sopenharmony_ci */ 135195972f6Sopenharmony_cistatic void 136195972f6Sopenharmony_ciautoip_handle_arp_conflict(struct netif *netif) 137195972f6Sopenharmony_ci{ 138195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 139195972f6Sopenharmony_ci 140195972f6Sopenharmony_ci /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where 141195972f6Sopenharmony_ci a) means retreat on the first conflict and 142195972f6Sopenharmony_ci b) allows to keep an already configured address when having only one 143195972f6Sopenharmony_ci conflict in 10 seconds 144195972f6Sopenharmony_ci We use option b) since it helps to improve the chance that one of the two 145195972f6Sopenharmony_ci conflicting hosts may be able to retain its address. */ 146195972f6Sopenharmony_ci 147195972f6Sopenharmony_ci if (autoip->lastconflict > 0) { 148195972f6Sopenharmony_ci /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */ 149195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 150195972f6Sopenharmony_ci ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); 151195972f6Sopenharmony_ci 152195972f6Sopenharmony_ci /* Active TCP sessions are aborted when removing the ip addresss */ 153195972f6Sopenharmony_ci autoip_restart(netif); 154195972f6Sopenharmony_ci } else { 155195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 156195972f6Sopenharmony_ci ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); 157195972f6Sopenharmony_ci autoip_arp_announce(netif); 158195972f6Sopenharmony_ci autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; 159195972f6Sopenharmony_ci } 160195972f6Sopenharmony_ci} 161195972f6Sopenharmony_ci 162195972f6Sopenharmony_ci/** 163195972f6Sopenharmony_ci * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 164195972f6Sopenharmony_ci * 165195972f6Sopenharmony_ci * @param netif network interface on which create the IP-Address 166195972f6Sopenharmony_ci * @param ipaddr ip address to initialize 167195972f6Sopenharmony_ci */ 168195972f6Sopenharmony_cistatic void 169195972f6Sopenharmony_ciautoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr) 170195972f6Sopenharmony_ci{ 171195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 172195972f6Sopenharmony_ci 173195972f6Sopenharmony_ci /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 174195972f6Sopenharmony_ci * compliant to RFC 3927 Section 2.1 175195972f6Sopenharmony_ci * We have 254 * 256 possibilities */ 176195972f6Sopenharmony_ci 177195972f6Sopenharmony_ci u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); 178195972f6Sopenharmony_ci addr += autoip->tried_llipaddr; 179195972f6Sopenharmony_ci addr = AUTOIP_NET | (addr & 0xffff); 180195972f6Sopenharmony_ci /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ 181195972f6Sopenharmony_ci 182195972f6Sopenharmony_ci if (addr < AUTOIP_RANGE_START) { 183195972f6Sopenharmony_ci addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; 184195972f6Sopenharmony_ci } 185195972f6Sopenharmony_ci if (addr > AUTOIP_RANGE_END) { 186195972f6Sopenharmony_ci addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; 187195972f6Sopenharmony_ci } 188195972f6Sopenharmony_ci LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && 189195972f6Sopenharmony_ci (addr <= AUTOIP_RANGE_END)); 190195972f6Sopenharmony_ci ip4_addr_set_u32(ipaddr, lwip_htonl(addr)); 191195972f6Sopenharmony_ci 192195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 193195972f6Sopenharmony_ci ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 194195972f6Sopenharmony_ci (u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), 195195972f6Sopenharmony_ci ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); 196195972f6Sopenharmony_ci} 197195972f6Sopenharmony_ci 198195972f6Sopenharmony_ci/** 199195972f6Sopenharmony_ci * Sends an ARP probe from a network interface 200195972f6Sopenharmony_ci * 201195972f6Sopenharmony_ci * @param netif network interface used to send the probe 202195972f6Sopenharmony_ci */ 203195972f6Sopenharmony_cistatic err_t 204195972f6Sopenharmony_ciautoip_arp_probe(struct netif *netif) 205195972f6Sopenharmony_ci{ 206195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 207195972f6Sopenharmony_ci /* this works because netif->ip_addr is ANY */ 208195972f6Sopenharmony_ci return etharp_request(netif, &autoip->llipaddr); 209195972f6Sopenharmony_ci} 210195972f6Sopenharmony_ci 211195972f6Sopenharmony_ci/** 212195972f6Sopenharmony_ci * Sends an ARP announce from a network interface 213195972f6Sopenharmony_ci * 214195972f6Sopenharmony_ci * @param netif network interface used to send the announce 215195972f6Sopenharmony_ci */ 216195972f6Sopenharmony_cistatic err_t 217195972f6Sopenharmony_ciautoip_arp_announce(struct netif *netif) 218195972f6Sopenharmony_ci{ 219195972f6Sopenharmony_ci return etharp_gratuitous(netif); 220195972f6Sopenharmony_ci} 221195972f6Sopenharmony_ci 222195972f6Sopenharmony_ci/** 223195972f6Sopenharmony_ci * Configure interface for use with current LL IP-Address 224195972f6Sopenharmony_ci * 225195972f6Sopenharmony_ci * @param netif network interface to configure with current LL IP-Address 226195972f6Sopenharmony_ci */ 227195972f6Sopenharmony_cistatic err_t 228195972f6Sopenharmony_ciautoip_bind(struct netif *netif) 229195972f6Sopenharmony_ci{ 230195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 231195972f6Sopenharmony_ci ip4_addr_t sn_mask, gw_addr; 232195972f6Sopenharmony_ci 233195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, 234195972f6Sopenharmony_ci ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 235195972f6Sopenharmony_ci (void *)netif, netif->name[0], netif->name[1], (u16_t)netif->num, 236195972f6Sopenharmony_ci ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), 237195972f6Sopenharmony_ci ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); 238195972f6Sopenharmony_ci 239195972f6Sopenharmony_ci IP4_ADDR(&sn_mask, 255, 255, 0, 0); 240195972f6Sopenharmony_ci IP4_ADDR(&gw_addr, 0, 0, 0, 0); 241195972f6Sopenharmony_ci 242195972f6Sopenharmony_ci netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr); 243195972f6Sopenharmony_ci /* interface is used by routing now that an address is set */ 244195972f6Sopenharmony_ci 245195972f6Sopenharmony_ci return ERR_OK; 246195972f6Sopenharmony_ci} 247195972f6Sopenharmony_ci 248195972f6Sopenharmony_ci/** 249195972f6Sopenharmony_ci * @ingroup autoip 250195972f6Sopenharmony_ci * Start AutoIP client 251195972f6Sopenharmony_ci * 252195972f6Sopenharmony_ci * @param netif network interface on which start the AutoIP client 253195972f6Sopenharmony_ci */ 254195972f6Sopenharmony_cierr_t 255195972f6Sopenharmony_ciautoip_start(struct netif *netif) 256195972f6Sopenharmony_ci{ 257195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 258195972f6Sopenharmony_ci err_t result = ERR_OK; 259195972f6Sopenharmony_ci 260195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 261195972f6Sopenharmony_ci LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); 262195972f6Sopenharmony_ci 263195972f6Sopenharmony_ci /* Set IP-Address, Netmask and Gateway to 0 to make sure that 264195972f6Sopenharmony_ci * ARP Packets are formed correctly 265195972f6Sopenharmony_ci */ 266195972f6Sopenharmony_ci netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); 267195972f6Sopenharmony_ci 268195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 269195972f6Sopenharmony_ci ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void *)netif, netif->name[0], 270195972f6Sopenharmony_ci netif->name[1], (u16_t)netif->num)); 271195972f6Sopenharmony_ci if (autoip == NULL) { 272195972f6Sopenharmony_ci /* no AutoIP client attached yet? */ 273195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, 274195972f6Sopenharmony_ci ("autoip_start(): starting new AUTOIP client\n")); 275195972f6Sopenharmony_ci autoip = (struct autoip *)mem_calloc(1, sizeof(struct autoip)); 276195972f6Sopenharmony_ci if (autoip == NULL) { 277195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, 278195972f6Sopenharmony_ci ("autoip_start(): could not allocate autoip\n")); 279195972f6Sopenharmony_ci return ERR_MEM; 280195972f6Sopenharmony_ci } 281195972f6Sopenharmony_ci /* store this AutoIP client in the netif */ 282195972f6Sopenharmony_ci netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); 283195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); 284195972f6Sopenharmony_ci } else { 285195972f6Sopenharmony_ci autoip->state = AUTOIP_STATE_OFF; 286195972f6Sopenharmony_ci autoip->ttw = 0; 287195972f6Sopenharmony_ci autoip->sent_num = 0; 288195972f6Sopenharmony_ci ip4_addr_set_zero(&autoip->llipaddr); 289195972f6Sopenharmony_ci autoip->lastconflict = 0; 290195972f6Sopenharmony_ci } 291195972f6Sopenharmony_ci 292195972f6Sopenharmony_ci autoip_create_addr(netif, &(autoip->llipaddr)); 293195972f6Sopenharmony_ci autoip_start_probing(netif); 294195972f6Sopenharmony_ci 295195972f6Sopenharmony_ci return result; 296195972f6Sopenharmony_ci} 297195972f6Sopenharmony_ci 298195972f6Sopenharmony_cistatic void 299195972f6Sopenharmony_ciautoip_start_probing(struct netif *netif) 300195972f6Sopenharmony_ci{ 301195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 302195972f6Sopenharmony_ci 303195972f6Sopenharmony_ci autoip->state = AUTOIP_STATE_PROBING; 304195972f6Sopenharmony_ci autoip->sent_num = 0; 305195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 306195972f6Sopenharmony_ci ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 307195972f6Sopenharmony_ci ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), 308195972f6Sopenharmony_ci ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); 309195972f6Sopenharmony_ci 310195972f6Sopenharmony_ci /* time to wait to first probe, this is randomly 311195972f6Sopenharmony_ci * chosen out of 0 to PROBE_WAIT seconds. 312195972f6Sopenharmony_ci * compliant to RFC 3927 Section 2.2.1 313195972f6Sopenharmony_ci */ 314195972f6Sopenharmony_ci autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); 315195972f6Sopenharmony_ci 316195972f6Sopenharmony_ci /* 317195972f6Sopenharmony_ci * if we tried more then MAX_CONFLICTS we must limit our rate for 318195972f6Sopenharmony_ci * acquiring and probing address 319195972f6Sopenharmony_ci * compliant to RFC 3927 Section 2.2.1 320195972f6Sopenharmony_ci */ 321195972f6Sopenharmony_ci if (autoip->tried_llipaddr > MAX_CONFLICTS) { 322195972f6Sopenharmony_ci autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; 323195972f6Sopenharmony_ci } 324195972f6Sopenharmony_ci} 325195972f6Sopenharmony_ci 326195972f6Sopenharmony_ci/** 327195972f6Sopenharmony_ci * Handle a possible change in the network configuration. 328195972f6Sopenharmony_ci * 329195972f6Sopenharmony_ci * If there is an AutoIP address configured, take the interface down 330195972f6Sopenharmony_ci * and begin probing with the same address. 331195972f6Sopenharmony_ci */ 332195972f6Sopenharmony_civoid 333195972f6Sopenharmony_ciautoip_network_changed(struct netif *netif) 334195972f6Sopenharmony_ci{ 335195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 336195972f6Sopenharmony_ci 337195972f6Sopenharmony_ci if (autoip && (autoip->state != AUTOIP_STATE_OFF)) { 338195972f6Sopenharmony_ci autoip_start_probing(netif); 339195972f6Sopenharmony_ci } 340195972f6Sopenharmony_ci} 341195972f6Sopenharmony_ci 342195972f6Sopenharmony_ci/** 343195972f6Sopenharmony_ci * @ingroup autoip 344195972f6Sopenharmony_ci * Stop AutoIP client 345195972f6Sopenharmony_ci * 346195972f6Sopenharmony_ci * @param netif network interface on which stop the AutoIP client 347195972f6Sopenharmony_ci */ 348195972f6Sopenharmony_cierr_t 349195972f6Sopenharmony_ciautoip_stop(struct netif *netif) 350195972f6Sopenharmony_ci{ 351195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 352195972f6Sopenharmony_ci 353195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 354195972f6Sopenharmony_ci if (autoip != NULL) { 355195972f6Sopenharmony_ci autoip->state = AUTOIP_STATE_OFF; 356195972f6Sopenharmony_ci if (ip4_addr_islinklocal(netif_ip4_addr(netif))) { 357195972f6Sopenharmony_ci netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); 358195972f6Sopenharmony_ci } 359195972f6Sopenharmony_ci } 360195972f6Sopenharmony_ci return ERR_OK; 361195972f6Sopenharmony_ci} 362195972f6Sopenharmony_ci 363195972f6Sopenharmony_ci#if LWIP_LOWPOWER 364195972f6Sopenharmony_ci#include "lwip/lowpower.h" 365195972f6Sopenharmony_ciu32_t 366195972f6Sopenharmony_ciautoip_tmr_tick(void) 367195972f6Sopenharmony_ci{ 368195972f6Sopenharmony_ci struct netif *netif = NULL; 369195972f6Sopenharmony_ci u32_t tick = 0; 370195972f6Sopenharmony_ci NETIF_FOREACH(netif) { 371195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 372195972f6Sopenharmony_ci if ((autoip != NULL) && (autoip->ttw > 0)) { 373195972f6Sopenharmony_ci if ((autoip->state == AUTOIP_STATE_PROBING) || 374195972f6Sopenharmony_ci (autoip->state == AUTOIP_STATE_ANNOUNCING)) { 375195972f6Sopenharmony_ci SET_TMR_TICK(tick, autoip->ttw); 376195972f6Sopenharmony_ci } 377195972f6Sopenharmony_ci } 378195972f6Sopenharmony_ci } 379195972f6Sopenharmony_ci 380195972f6Sopenharmony_ci LWIP_DEBUGF(LOWPOWER_DEBUG, ("%s tmr tick: %u\n", "autoip_tmr_tick", tick)); 381195972f6Sopenharmony_ci return tick; 382195972f6Sopenharmony_ci} 383195972f6Sopenharmony_ci 384195972f6Sopenharmony_ci#endif 385195972f6Sopenharmony_ci 386195972f6Sopenharmony_ci/** 387195972f6Sopenharmony_ci * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds 388195972f6Sopenharmony_ci */ 389195972f6Sopenharmony_civoid 390195972f6Sopenharmony_ciautoip_tmr(void) 391195972f6Sopenharmony_ci{ 392195972f6Sopenharmony_ci struct netif *netif; 393195972f6Sopenharmony_ci /* loop through netif's */ 394195972f6Sopenharmony_ci NETIF_FOREACH(netif) { 395195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 396195972f6Sopenharmony_ci /* only act on AutoIP configured interfaces */ 397195972f6Sopenharmony_ci if (autoip != NULL) { 398195972f6Sopenharmony_ci if (autoip->lastconflict > 0) { 399195972f6Sopenharmony_ci autoip->lastconflict--; 400195972f6Sopenharmony_ci } 401195972f6Sopenharmony_ci 402195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, 403195972f6Sopenharmony_ci ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", 404195972f6Sopenharmony_ci (u16_t)(autoip->state), autoip->ttw)); 405195972f6Sopenharmony_ci 406195972f6Sopenharmony_ci if (autoip->ttw > 0) { 407195972f6Sopenharmony_ci autoip->ttw--; 408195972f6Sopenharmony_ci } 409195972f6Sopenharmony_ci 410195972f6Sopenharmony_ci switch (autoip->state) { 411195972f6Sopenharmony_ci case AUTOIP_STATE_PROBING: 412195972f6Sopenharmony_ci if (autoip->ttw == 0) { 413195972f6Sopenharmony_ci if (autoip->sent_num >= PROBE_NUM) { 414195972f6Sopenharmony_ci /* Switch to ANNOUNCING: now we can bind to an IP address and use it */ 415195972f6Sopenharmony_ci autoip->state = AUTOIP_STATE_ANNOUNCING; 416195972f6Sopenharmony_ci autoip_bind(netif); 417195972f6Sopenharmony_ci /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP 418195972f6Sopenharmony_ci which counts as an announcement */ 419195972f6Sopenharmony_ci autoip->sent_num = 1; 420195972f6Sopenharmony_ci autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; 421195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 422195972f6Sopenharmony_ci ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 423195972f6Sopenharmony_ci ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), 424195972f6Sopenharmony_ci ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); 425195972f6Sopenharmony_ci } else { 426195972f6Sopenharmony_ci autoip_arp_probe(netif); 427195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n")); 428195972f6Sopenharmony_ci autoip->sent_num++; 429195972f6Sopenharmony_ci if (autoip->sent_num == PROBE_NUM) { 430195972f6Sopenharmony_ci /* calculate time to wait to for announce */ 431195972f6Sopenharmony_ci autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; 432195972f6Sopenharmony_ci } else { 433195972f6Sopenharmony_ci /* calculate time to wait to next probe */ 434195972f6Sopenharmony_ci autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % 435195972f6Sopenharmony_ci ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + 436195972f6Sopenharmony_ci PROBE_MIN * AUTOIP_TICKS_PER_SECOND); 437195972f6Sopenharmony_ci } 438195972f6Sopenharmony_ci } 439195972f6Sopenharmony_ci } 440195972f6Sopenharmony_ci break; 441195972f6Sopenharmony_ci 442195972f6Sopenharmony_ci case AUTOIP_STATE_ANNOUNCING: 443195972f6Sopenharmony_ci if (autoip->ttw == 0) { 444195972f6Sopenharmony_ci autoip_arp_announce(netif); 445195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n")); 446195972f6Sopenharmony_ci autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; 447195972f6Sopenharmony_ci autoip->sent_num++; 448195972f6Sopenharmony_ci 449195972f6Sopenharmony_ci if (autoip->sent_num >= ANNOUNCE_NUM) { 450195972f6Sopenharmony_ci autoip->state = AUTOIP_STATE_BOUND; 451195972f6Sopenharmony_ci autoip->sent_num = 0; 452195972f6Sopenharmony_ci autoip->ttw = 0; 453195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 454195972f6Sopenharmony_ci ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 455195972f6Sopenharmony_ci ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), 456195972f6Sopenharmony_ci ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); 457195972f6Sopenharmony_ci } 458195972f6Sopenharmony_ci } 459195972f6Sopenharmony_ci break; 460195972f6Sopenharmony_ci 461195972f6Sopenharmony_ci default: 462195972f6Sopenharmony_ci /* nothing to do in other states */ 463195972f6Sopenharmony_ci break; 464195972f6Sopenharmony_ci } 465195972f6Sopenharmony_ci } 466195972f6Sopenharmony_ci } 467195972f6Sopenharmony_ci} 468195972f6Sopenharmony_ci 469195972f6Sopenharmony_ci/** 470195972f6Sopenharmony_ci * Handles every incoming ARP Packet, called by etharp_input(). 471195972f6Sopenharmony_ci * 472195972f6Sopenharmony_ci * @param netif network interface to use for autoip processing 473195972f6Sopenharmony_ci * @param hdr Incoming ARP packet 474195972f6Sopenharmony_ci */ 475195972f6Sopenharmony_civoid 476195972f6Sopenharmony_ciautoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) 477195972f6Sopenharmony_ci{ 478195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 479195972f6Sopenharmony_ci 480195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); 481195972f6Sopenharmony_ci if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) { 482195972f6Sopenharmony_ci /* when ip.src == llipaddr && hw.src != netif->hwaddr 483195972f6Sopenharmony_ci * 484195972f6Sopenharmony_ci * when probing ip.dst == llipaddr && hw.src != netif->hwaddr 485195972f6Sopenharmony_ci * we have a conflict and must solve it 486195972f6Sopenharmony_ci */ 487195972f6Sopenharmony_ci ip4_addr_t sipaddr, dipaddr; 488195972f6Sopenharmony_ci struct eth_addr netifaddr; 489195972f6Sopenharmony_ci SMEMCPY(netifaddr.addr, netif->hwaddr, ETH_HWADDR_LEN); 490195972f6Sopenharmony_ci 491195972f6Sopenharmony_ci /* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support compilers without 492195972f6Sopenharmony_ci * structure packing (not using structure copy which breaks strict-aliasing rules). 493195972f6Sopenharmony_ci */ 494195972f6Sopenharmony_ci IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &hdr->sipaddr); 495195972f6Sopenharmony_ci IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&dipaddr, &hdr->dipaddr); 496195972f6Sopenharmony_ci 497195972f6Sopenharmony_ci if (autoip->state == AUTOIP_STATE_PROBING) { 498195972f6Sopenharmony_ci /* RFC 3927 Section 2.2.1: 499195972f6Sopenharmony_ci * from beginning to after ANNOUNCE_WAIT 500195972f6Sopenharmony_ci * seconds we have a conflict if 501195972f6Sopenharmony_ci * ip.src == llipaddr OR 502195972f6Sopenharmony_ci * ip.dst == llipaddr && hw.src != own hwaddr 503195972f6Sopenharmony_ci */ 504195972f6Sopenharmony_ci if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) || 505195972f6Sopenharmony_ci (ip4_addr_isany_val(sipaddr) && 506195972f6Sopenharmony_ci ip4_addr_cmp(&dipaddr, &autoip->llipaddr) && 507195972f6Sopenharmony_ci !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { 508195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, 509195972f6Sopenharmony_ci ("autoip_arp_reply(): Probe Conflict detected\n")); 510195972f6Sopenharmony_ci autoip_restart(netif); 511195972f6Sopenharmony_ci } 512195972f6Sopenharmony_ci } else { 513195972f6Sopenharmony_ci /* RFC 3927 Section 2.5: 514195972f6Sopenharmony_ci * in any state we have a conflict if 515195972f6Sopenharmony_ci * ip.src == llipaddr && hw.src != own hwaddr 516195972f6Sopenharmony_ci */ 517195972f6Sopenharmony_ci if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) && 518195972f6Sopenharmony_ci !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { 519195972f6Sopenharmony_ci LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, 520195972f6Sopenharmony_ci ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); 521195972f6Sopenharmony_ci autoip_handle_arp_conflict(netif); 522195972f6Sopenharmony_ci } 523195972f6Sopenharmony_ci } 524195972f6Sopenharmony_ci } 525195972f6Sopenharmony_ci} 526195972f6Sopenharmony_ci 527195972f6Sopenharmony_ci/** check if AutoIP supplied netif->ip_addr 528195972f6Sopenharmony_ci * 529195972f6Sopenharmony_ci * @param netif the netif to check 530195972f6Sopenharmony_ci * @return 1 if AutoIP supplied netif->ip_addr (state BOUND or ANNOUNCING), 531195972f6Sopenharmony_ci * 0 otherwise 532195972f6Sopenharmony_ci */ 533195972f6Sopenharmony_ciu8_t 534195972f6Sopenharmony_ciautoip_supplied_address(const struct netif *netif) 535195972f6Sopenharmony_ci{ 536195972f6Sopenharmony_ci if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) { 537195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 538195972f6Sopenharmony_ci return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING); 539195972f6Sopenharmony_ci } 540195972f6Sopenharmony_ci return 0; 541195972f6Sopenharmony_ci} 542195972f6Sopenharmony_ci 543195972f6Sopenharmony_ciu8_t 544195972f6Sopenharmony_ciautoip_accept_packet(struct netif *netif, const ip4_addr_t *addr) 545195972f6Sopenharmony_ci{ 546195972f6Sopenharmony_ci struct autoip *autoip = netif_autoip_data(netif); 547195972f6Sopenharmony_ci return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr)); 548195972f6Sopenharmony_ci} 549195972f6Sopenharmony_ci 550195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_AUTOIP */ 551