ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

autoip.c
Go to the documentation of this file.
00001 
00007 /*
00008  *
00009  * Copyright (c) 2007 Dominik Spies <kontakt@dspies.de>
00010  * All rights reserved.
00011  *
00012  * Redistribution and use in source and binary forms, with or without modification,
00013  * are permitted provided that the following conditions are met:
00014  *
00015  * 1. Redistributions of source code must retain the above copyright notice,
00016  *    this list of conditions and the following disclaimer.
00017  * 2. Redistributions in binary form must reproduce the above copyright notice,
00018  *    this list of conditions and the following disclaimer in the documentation
00019  *    and/or other materials provided with the distribution.
00020  * 3. The name of the author may not be used to endorse or promote products
00021  *    derived from this software without specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00024  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00025  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00026  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00027  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00028  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00029  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00030  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00031  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00032  * OF SUCH DAMAGE.
00033  *
00034  * Author: Dominik Spies <kontakt@dspies.de>
00035  *
00036  * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform
00037  * with RFC 3927.
00038  *
00039  *
00040  * Please coordinate changes and requests with Dominik Spies
00041  * <kontakt@dspies.de>
00042  */
00043 
00044 /*******************************************************************************
00045  * USAGE:
00046  * 
00047  * define LWIP_AUTOIP 1  in your lwipopts.h
00048  * 
00049  * If you don't use tcpip.c (so, don't call, you don't call tcpip_init):
00050  * - First, call autoip_init().
00051  * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces,
00052  *   that should be defined in autoip.h.
00053  *   I recommend a value of 100. The value must divide 1000 with a remainder almost 0.
00054  *   Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 ....
00055  *
00056  * Without DHCP:
00057  * - Call autoip_start() after netif_add().
00058  * 
00059  * With DHCP:
00060  * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h.
00061  * - Configure your DHCP Client.
00062  *
00063  */
00064 
00065 #include "lwip/opt.h"
00066 
00067 #if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
00068 
00069 #include "lwip/mem.h"
00070 #include "lwip/udp.h"
00071 #include "lwip/ip_addr.h"
00072 #include "lwip/netif.h"
00073 #include "lwip/autoip.h"
00074 #include "netif/etharp.h"
00075 
00076 #include <stdlib.h>
00077 #include <string.h>
00078 
00079 /* 169.254.0.0 */
00080 #define AUTOIP_NET         0xA9FE0000
00081 /* 169.254.1.0 */
00082 #define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100)
00083 /* 169.254.254.255 */
00084 #define AUTOIP_RANGE_END   (AUTOIP_NET | 0xFEFF)
00085 
00086 
00089 #ifndef LWIP_AUTOIP_RAND
00090 #define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
00091                                    ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
00092                                    ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
00093                                    ((u32_t)((netif->hwaddr[4]) & 0xff))) + \
00094                                    (netif->autoip?netif->autoip->tried_llipaddr:0))
00095 #endif /* LWIP_AUTOIP_RAND */
00096 
00101 #ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
00102 #define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
00103   htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
00104                  ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
00105 #endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
00106 
00107 /* static functions */
00108 static void autoip_handle_arp_conflict(struct netif *netif);
00109 
00110 /* creates a pseudo random LL IP-Address for a network interface */
00111 static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr);
00112 
00113 /* sends an ARP probe */
00114 static err_t autoip_arp_probe(struct netif *netif);
00115 
00116 /* sends an ARP announce */
00117 static err_t autoip_arp_announce(struct netif *netif);
00118 
00119 /* configure interface for use with current LL IP-Address */
00120 static err_t autoip_bind(struct netif *netif);
00121 
00122 /* start sending probes for llipaddr */
00123 static void autoip_start_probing(struct netif *netif);
00124 
00128 void
00129 autoip_init(void)
00130 {
00131   LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_init()\n"));
00132 }
00133 
00140 void
00141 autoip_set_struct(struct netif *netif, struct autoip *autoip)
00142 {
00143   LWIP_ASSERT("netif != NULL", netif != NULL);
00144   LWIP_ASSERT("autoip != NULL", autoip != NULL);
00145   LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL);
00146 
00147   /* clear data structure */
00148   memset(autoip, 0, sizeof(struct autoip));
00149   /* autoip->state = AUTOIP_STATE_OFF; */
00150   netif->autoip = autoip;
00151 }
00152 
00157 static void
00158 autoip_restart(struct netif *netif)
00159 {
00160   netif->autoip->tried_llipaddr++;
00161   autoip_start(netif);
00162 }
00163 
00167 static void
00168 autoip_handle_arp_conflict(struct netif *netif)
00169 {
00170   /* Somehow detect if we are defending or retreating */
00171   unsigned char defend = 1; /* tbd */
00172 
00173   if(defend) {
00174     if(netif->autoip->lastconflict > 0) {
00175       /* retreat, there was a conflicting ARP in the last
00176        * DEFEND_INTERVAL seconds
00177        */
00178       LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00179         ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
00180 
00181       /* TODO: close all TCP sessions */
00182       autoip_restart(netif);
00183     } else {
00184       LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00185         ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
00186       autoip_arp_announce(netif);
00187       netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
00188     }
00189   } else {
00190     LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00191       ("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
00192     /* TODO: close all TCP sessions */
00193     autoip_restart(netif);
00194   }
00195 }
00196 
00203 static void
00204 autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr)
00205 {
00206   /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
00207    * compliant to RFC 3927 Section 2.1
00208    * We have 254 * 256 possibilities */
00209 
00210   u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
00211   addr += netif->autoip->tried_llipaddr;
00212   addr = AUTOIP_NET | (addr & 0xffff);
00213   /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ 
00214 
00215   if (addr < AUTOIP_RANGE_START) {
00216     addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
00217   }
00218   if (addr > AUTOIP_RANGE_END) {
00219     addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
00220   }
00221   LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
00222     (addr <= AUTOIP_RANGE_END));
00223   ip4_addr_set_u32(ipaddr, htonl(addr));
00224   
00225   LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00226     ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00227     (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr),
00228     ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
00229 }
00230 
00236 static err_t
00237 autoip_arp_probe(struct netif *netif)
00238 {
00239   return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
00240     (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, &ethzero,
00241     &netif->autoip->llipaddr, ARP_REQUEST);
00242 }
00243 
00249 static err_t
00250 autoip_arp_announce(struct netif *netif)
00251 {
00252   return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
00253     (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, &ethzero,
00254     &netif->autoip->llipaddr, ARP_REQUEST);
00255 }
00256 
00262 static err_t
00263 autoip_bind(struct netif *netif)
00264 {
00265   struct autoip *autoip = netif->autoip;
00266   ip_addr_t sn_mask, gw_addr;
00267 
00268   LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
00269     ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00270     (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num,
00271     ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
00272     ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
00273 
00274   IP4_ADDR(&sn_mask, 255, 255, 0, 0);
00275   IP4_ADDR(&gw_addr, 0, 0, 0, 0);
00276 
00277   netif_set_ipaddr(netif, &autoip->llipaddr);
00278   netif_set_netmask(netif, &sn_mask);
00279   netif_set_gw(netif, &gw_addr);  
00280 
00281   /* bring the interface up */
00282   netif_set_up(netif);
00283 
00284   return ERR_OK;
00285 }
00286 
00292 err_t
00293 autoip_start(struct netif *netif)
00294 {
00295   struct autoip *autoip = netif->autoip;
00296   err_t result = ERR_OK;
00297 
00298   if(netif_is_up(netif)) {
00299     netif_set_down(netif);
00300   }
00301 
00302   /* Set IP-Address, Netmask and Gateway to 0 to make sure that
00303    * ARP Packets are formed correctly
00304    */
00305   ip_addr_set_zero(&netif->ip_addr);
00306   ip_addr_set_zero(&netif->netmask);
00307   ip_addr_set_zero(&netif->gw);
00308 
00309   LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00310     ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
00311     netif->name[1], (u16_t)netif->num));
00312   if(autoip == NULL) {
00313     /* no AutoIP client attached yet? */
00314     LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
00315       ("autoip_start(): starting new AUTOIP client\n"));
00316     autoip = (struct autoip *)mem_malloc(sizeof(struct autoip));
00317     if(autoip == NULL) {
00318       LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
00319         ("autoip_start(): could not allocate autoip\n"));
00320       return ERR_MEM;
00321     }
00322     memset(autoip, 0, sizeof(struct autoip));
00323     /* store this AutoIP client in the netif */
00324     netif->autoip = autoip;
00325     LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
00326   } else {
00327     autoip->state = AUTOIP_STATE_OFF;
00328     autoip->ttw = 0;
00329     autoip->sent_num = 0;
00330     ip_addr_set_zero(&autoip->llipaddr);
00331     autoip->lastconflict = 0;
00332   }
00333 
00334   autoip_create_addr(netif, &(autoip->llipaddr));
00335   autoip_start_probing(netif);
00336 
00337   return result;
00338 }
00339 
00340 static void
00341 autoip_start_probing(struct netif *netif)
00342 {
00343   struct autoip *autoip = netif->autoip;
00344 
00345   autoip->state = AUTOIP_STATE_PROBING;
00346   autoip->sent_num = 0;
00347   LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00348      ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00349       ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
00350       ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
00351 
00352   /* time to wait to first probe, this is randomly
00353    * choosen out of 0 to PROBE_WAIT seconds.
00354    * compliant to RFC 3927 Section 2.2.1
00355    */
00356   autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND));
00357 
00358   /*
00359    * if we tried more then MAX_CONFLICTS we must limit our rate for
00360    * accquiring and probing address
00361    * compliant to RFC 3927 Section 2.2.1
00362    */
00363   if(autoip->tried_llipaddr > MAX_CONFLICTS) {
00364     autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
00365   }
00366 }
00367 
00374 void
00375 autoip_network_changed(struct netif *netif)
00376 {
00377   if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) {
00378     netif_set_down(netif);
00379     autoip_start_probing(netif);
00380   }
00381 }
00382 
00388 err_t
00389 autoip_stop(struct netif *netif)
00390 {
00391   netif->autoip->state = AUTOIP_STATE_OFF;
00392   netif_set_down(netif);
00393   return ERR_OK;
00394 }
00395 
00399 void
00400 autoip_tmr()
00401 {
00402   struct netif *netif = netif_list;
00403   /* loop through netif's */
00404   while (netif != NULL) {
00405     /* only act on AutoIP configured interfaces */
00406     if (netif->autoip != NULL) {
00407       if(netif->autoip->lastconflict > 0) {
00408         netif->autoip->lastconflict--;
00409       }
00410 
00411       LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
00412         ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n",
00413         (u16_t)(netif->autoip->state), netif->autoip->ttw));
00414 
00415       switch(netif->autoip->state) {
00416         case AUTOIP_STATE_PROBING:
00417           if(netif->autoip->ttw > 0) {
00418             netif->autoip->ttw--;
00419           } else {
00420             if(netif->autoip->sent_num >= PROBE_NUM) {
00421               netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
00422               netif->autoip->sent_num = 0;
00423               netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
00424               LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00425                  ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00426                   ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
00427                   ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
00428             } else {
00429               autoip_arp_probe(netif);
00430               LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
00431                 ("autoip_tmr() PROBING Sent Probe\n"));
00432               netif->autoip->sent_num++;
00433               /* calculate time to wait to next probe */
00434               netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
00435                 ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) +
00436                 PROBE_MIN * AUTOIP_TICKS_PER_SECOND);
00437             }
00438           }
00439           break;
00440 
00441         case AUTOIP_STATE_ANNOUNCING:
00442           if(netif->autoip->ttw > 0) {
00443             netif->autoip->ttw--;
00444           } else {
00445             if(netif->autoip->sent_num == 0) {
00446              /* We are here the first time, so we waited ANNOUNCE_WAIT seconds
00447               * Now we can bind to an IP address and use it.
00448               *
00449               * autoip_bind calls netif_set_up. This triggers a gratuitous ARP
00450               * which counts as an announcement.
00451               */
00452               autoip_bind(netif);
00453             } else {
00454               autoip_arp_announce(netif);
00455               LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
00456                 ("autoip_tmr() ANNOUNCING Sent Announce\n"));
00457             }
00458             netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
00459             netif->autoip->sent_num++;
00460 
00461             if(netif->autoip->sent_num >= ANNOUNCE_NUM) {
00462                 netif->autoip->state = AUTOIP_STATE_BOUND;
00463                 netif->autoip->sent_num = 0;
00464                 netif->autoip->ttw = 0;
00465                  LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00466                     ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00467                      ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
00468                      ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
00469             }
00470           }
00471           break;
00472       }
00473     }
00474     /* proceed to next network interface */
00475     netif = netif->next;
00476   }
00477 }
00478 
00485 void
00486 autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
00487 {
00488   LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
00489   if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) {
00490    /* when ip.src == llipaddr && hw.src != netif->hwaddr
00491     *
00492     * when probing  ip.dst == llipaddr && hw.src != netif->hwaddr
00493     * we have a conflict and must solve it
00494     */
00495     ip_addr_t sipaddr, dipaddr;
00496     struct eth_addr netifaddr;
00497     ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
00498 
00499     /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
00500      * structure packing (not using structure copy which breaks strict-aliasing rules).
00501      */
00502     IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
00503     IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
00504       
00505     if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
00506         ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
00507          (netif->autoip->sent_num == 0))) {
00508      /* RFC 3927 Section 2.2.1:
00509       * from beginning to after ANNOUNCE_WAIT
00510       * seconds we have a conflict if
00511       * ip.src == llipaddr OR
00512       * ip.dst == llipaddr && hw.src != own hwaddr
00513       */
00514       if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) ||
00515           (ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) &&
00516            !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
00517         LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
00518           ("autoip_arp_reply(): Probe Conflict detected\n"));
00519         autoip_restart(netif);
00520       }
00521     } else {
00522      /* RFC 3927 Section 2.5:
00523       * in any state we have a conflict if
00524       * ip.src == llipaddr && hw.src != own hwaddr
00525       */
00526       if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) &&
00527           !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
00528         LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
00529           ("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
00530         autoip_handle_arp_conflict(netif);
00531       }
00532     }
00533   }
00534 }
00535 
00536 #endif /* LWIP_AUTOIP */

Generated on Sat May 26 2012 04:34:56 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.