📄 autoip.c
字号:
/** * @file * AutoIP Automatic LinkLocal IP Configuration * *//* * * Copyright (c) 2007 Dominik Spies <kontakt@dspies.de> * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * Author: Dominik Spies <kontakt@dspies.de> * * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform * with RFC 3927. * * * Please coordinate changes and requests with Dominik Spies * <kontakt@dspies.de> *//******************************************************************************* * USAGE: * * define LWIP_AUTOIP 1 in your lwipopts.h * * If you don't use tcpip.c (so, don't call, you don't call tcpip_init): * - First, call autoip_init(). * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces, * that should be defined in autoip.h. * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... * * Without DHCP: * - Call autoip_start() after netif_add(). * * With DHCP: * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. * - Configure your DHCP Client. * */#include "lwip/opt.h"#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */#include "lwip/mem.h"#include "lwip/udp.h"#include "lwip/ip_addr.h"#include "lwip/netif.h"#include "lwip/autoip.h"#include "netif/etharp.h"#include <stdlib.h>#include <string.h>/* 169.254.0.0 */#define AUTOIP_NET 0xA9FE0000/* 169.254.1.0 */#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100)/* 169.254.254.255 */#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF)/** Pseudo random macro based on netif informations. * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */#ifndef LWIP_AUTOIP_RAND#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ (netif->autoip?netif->autoip->tried_llipaddr:0))#endif /* LWIP_AUTOIP_RAND *//** * Macro that generates the initial IP address to be tried by AUTOIP. * If you want to override this, define it to something else in lwipopts.h. */#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR *//* static functions */static void autoip_handle_arp_conflict(struct netif *netif);/* creates a pseudo random LL IP-Address for a network interface */static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr);/* sends an ARP probe */static err_t autoip_arp_probe(struct netif *netif);/* sends an ARP announce */static err_t autoip_arp_announce(struct netif *netif);/* configure interface for use with current LL IP-Address */static err_t autoip_bind(struct netif *netif);/* start sending probes for llipaddr */static void autoip_start_probing(struct netif *netif);/** * Initialize this module */voidautoip_init(void){ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_init()\n"));}/** Set a statically allocated struct autoip to work with. * Using this prevents autoip_start to allocate it using mem_malloc. * * @param netif the netif for which to set the struct autoip * @param dhcp (uninitialised) dhcp struct allocated by the application */voidautoip_set_struct(struct netif *netif, struct autoip *autoip){ LWIP_ASSERT("netif != NULL", netif != NULL); LWIP_ASSERT("autoip != NULL", autoip != NULL); LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL); /* clear data structure */ memset(autoip, 0, sizeof(struct autoip)); /* autoip->state = AUTOIP_STATE_OFF; */ netif->autoip = autoip;}/** Restart AutoIP client and check the next address (conflict detected) * * @param netif The netif under AutoIP control */static voidautoip_restart(struct netif *netif){ netif->autoip->tried_llipaddr++; autoip_start(netif);}/** * Handle a IP address conflict after an ARP conflict detection */static voidautoip_handle_arp_conflict(struct netif *netif){ /* Somehow detect if we are defending or retreating */ unsigned char defend = 1; /* tbd */ if(defend) { if(netif->autoip->lastconflict > 0) { /* retreat, there was a conflicting ARP in the last * DEFEND_INTERVAL seconds */ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); /* TODO: close all TCP sessions */ autoip_restart(netif); } else { LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); autoip_arp_announce(netif); netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; } } else { LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_handle_arp_conflict(): we do not defend, retreating\n")); /* TODO: close all TCP sessions */ autoip_restart(netif); }}/** * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 * * @param netif network interface on which create the IP-Address * @param ipaddr ip address to initialize */static voidautoip_create_addr(struct netif *netif, ip_addr_t *ipaddr){ /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 * compliant to RFC 3927 Section 2.1 * We have 254 * 256 possibilities */ u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); addr += netif->autoip->tried_llipaddr; addr = AUTOIP_NET | (addr & 0xffff); /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ if (addr < AUTOIP_RANGE_START) { addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; } if (addr > AUTOIP_RANGE_END) { addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; } LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && (addr <= AUTOIP_RANGE_END)); ip4_addr_set_u32(ipaddr, htonl(addr)); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));}/** * Sends an ARP probe from a network interface * * @param netif network interface used to send the probe */static err_tautoip_arp_probe(struct netif *netif){ return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, ðzero, &netif->autoip->llipaddr, ARP_REQUEST);}/** * Sends an ARP announce from a network interface * * @param netif network interface used to send the announce */static err_tautoip_arp_announce(struct netif *netif){ return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, ðzero, &netif->autoip->llipaddr, ARP_REQUEST);}/** * Configure interface for use with current LL IP-Address * * @param netif network interface to configure with current LL IP-Address */static err_tautoip_bind(struct netif *netif){ struct autoip *autoip = netif->autoip; ip_addr_t sn_mask, gw_addr; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -