📄 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, struct ip_addr *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"));}/** * 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_start(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_start(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, struct ip_addr *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)); ipaddr->addr = htonl(addr); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n", (u16_t)(netif->autoip->tried_llipaddr), (u32_t)(ipaddr->addr)));}/** * 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; struct ip_addr sn_mask, gw_addr; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_bind(netif=%p) %c%c%"U16_F" 0x%08"X32_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, autoip->llipaddr.addr)); IP4_ADDR(&sn_mask, 255, 255, 0, 0); IP4_ADDR(&gw_addr, 0, 0, 0, 0); netif_set_ipaddr(netif, &autoip->llipaddr); netif_set_netmask(netif, &sn_mask); netif_set_gw(netif, &gw_addr); /* bring the interface up */ netif_set_up(netif);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -