Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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