The Pedigree Project 0.1
autoip.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
48/*
49 *
50 * Copyright (c) 2007 Dominik Spies <kontakt@dspies.de>
51 * All rights reserved.
52 *
53 * Redistribution and use in source and binary forms, with or without modification,
54 * are permitted provided that the following conditions are met:
55 *
56 * 1. Redistributions of source code must retain the above copyright notice,
57 * this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright notice,
59 * this list of conditions and the following disclaimer in the documentation
60 * and/or other materials provided with the distribution.
61 * 3. The name of the author may not be used to endorse or promote products
62 * derived from this software without specific prior written permission.
63 *
64 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
65 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
66 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
67 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
68 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
69 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
70 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
71 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
72 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
73 * OF SUCH DAMAGE.
74 *
75 * Author: Dominik Spies <kontakt@dspies.de>
76 */
77
78#include "lwip/opt.h"
79
80#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
81
82#include "lwip/mem.h"
83/* #include "lwip/udp.h" */
84#include "lwip/ip_addr.h"
85#include "lwip/netif.h"
86#include "lwip/autoip.h"
87#include "lwip/etharp.h"
88#include "lwip/prot/autoip.h"
89
90#include <string.h>
91
94#ifndef LWIP_AUTOIP_RAND
95#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
96 ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
97 ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
98 ((u32_t)((netif->hwaddr[4]) & 0xff))) + \
99 (netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0))
100#endif /* LWIP_AUTOIP_RAND */
101
106#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
107#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
108 lwip_htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
109 ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
110#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
111
112/* static functions */
113static err_t autoip_arp_announce(struct netif *netif);
114static void autoip_start_probing(struct netif *netif);
115
124void
125autoip_set_struct(struct netif *netif, struct autoip *autoip)
126{
127 LWIP_ASSERT("netif != NULL", netif != NULL);
128 LWIP_ASSERT("autoip != NULL", autoip != NULL);
129 LWIP_ASSERT("netif already has a struct autoip set",
130 netif_autoip_data(netif) == NULL);
131
132 /* clear data structure */
133 memset(autoip, 0, sizeof(struct autoip));
134 /* autoip->state = AUTOIP_STATE_OFF; */
135 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
136}
137
142static void
143autoip_restart(struct netif *netif)
144{
145 struct autoip* autoip = netif_autoip_data(netif);
146 autoip->tried_llipaddr++;
147 autoip_start(netif);
148}
149
153static void
154autoip_handle_arp_conflict(struct netif *netif)
155{
156 struct autoip* autoip = netif_autoip_data(netif);
157
158 /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where
159 a) means retreat on the first conflict and
160 b) allows to keep an already configured address when having only one
161 conflict in 10 seconds
162 We use option b) since it helps to improve the chance that one of the two
163 conflicting hosts may be able to retain its address. */
164
165 if (autoip->lastconflict > 0) {
166 /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */
168 ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
169
170 /* Active TCP sessions are aborted when removing the ip addresss */
171 autoip_restart(netif);
172 } else {
174 ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
175 autoip_arp_announce(netif);
176 autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
177 }
178}
179
186static void
187autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr)
188{
189 struct autoip* autoip = netif_autoip_data(netif);
190
191 /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
192 * compliant to RFC 3927 Section 2.1
193 * We have 254 * 256 possibilities */
194
195 u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
196 addr += autoip->tried_llipaddr;
197 addr = AUTOIP_NET | (addr & 0xffff);
198 /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
199
200 if (addr < AUTOIP_RANGE_START) {
201 addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
202 }
203 if (addr > AUTOIP_RANGE_END) {
204 addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
205 }
206 LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
207 (addr <= AUTOIP_RANGE_END));
208 ip4_addr_set_u32(ipaddr, lwip_htonl(addr));
209
211 ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
212 (u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr),
213 ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
214}
215
221static err_t
222autoip_arp_probe(struct netif *netif)
223{
224 struct autoip* autoip = netif_autoip_data(netif);
225 /* this works because netif->ip_addr is ANY */
226 return etharp_request(netif, &autoip->llipaddr);
227}
228
234static err_t
235autoip_arp_announce(struct netif *netif)
236{
237 return etharp_gratuitous(netif);
238}
239
245static err_t
246autoip_bind(struct netif *netif)
247{
248 struct autoip* autoip = netif_autoip_data(netif);
249 ip4_addr_t sn_mask, gw_addr;
250
252 ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
253 (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num,
254 ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
255 ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
256
257 IP4_ADDR(&sn_mask, 255, 255, 0, 0);
258 IP4_ADDR(&gw_addr, 0, 0, 0, 0);
259
260 netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr);
261 /* interface is used by routing now that an address is set */
262
263 return ERR_OK;
264}
265
272err_t
273autoip_start(struct netif *netif)
274{
275 struct autoip* autoip = netif_autoip_data(netif);
276 err_t result = ERR_OK;
277
278 LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
279
280 /* Set IP-Address, Netmask and Gateway to 0 to make sure that
281 * ARP Packets are formed correctly
282 */
283 netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
284
286 ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
287 netif->name[1], (u16_t)netif->num));
288 if (autoip == NULL) {
289 /* no AutoIP client attached yet? */
291 ("autoip_start(): starting new AUTOIP client\n"));
292 autoip = (struct autoip *)mem_malloc(sizeof(struct autoip));
293 if (autoip == NULL) {
295 ("autoip_start(): could not allocate autoip\n"));
296 return ERR_MEM;
297 }
298 memset(autoip, 0, sizeof(struct autoip));
299 /* store this AutoIP client in the netif */
300 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
301 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
302 } else {
303 autoip->state = AUTOIP_STATE_OFF;
304 autoip->ttw = 0;
305 autoip->sent_num = 0;
306 ip4_addr_set_zero(&autoip->llipaddr);
307 autoip->lastconflict = 0;
308 }
309
310 autoip_create_addr(netif, &(autoip->llipaddr));
311 autoip_start_probing(netif);
312
313 return result;
314}
315
316static void
317autoip_start_probing(struct netif *netif)
318{
319 struct autoip* autoip = netif_autoip_data(netif);
320
321 autoip->state = AUTOIP_STATE_PROBING;
322 autoip->sent_num = 0;
324 ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
325 ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
326 ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
327
328 /* time to wait to first probe, this is randomly
329 * chosen out of 0 to PROBE_WAIT seconds.
330 * compliant to RFC 3927 Section 2.2.1
331 */
332 autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND));
333
334 /*
335 * if we tried more then MAX_CONFLICTS we must limit our rate for
336 * acquiring and probing address
337 * compliant to RFC 3927 Section 2.2.1
338 */
339 if (autoip->tried_llipaddr > MAX_CONFLICTS) {
340 autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
341 }
342}
343
350void
351autoip_network_changed(struct netif *netif)
352{
353 struct autoip* autoip = netif_autoip_data(netif);
354
355 if (autoip && (autoip->state != AUTOIP_STATE_OFF)) {
356 autoip_start_probing(netif);
357 }
358}
359
366err_t
367autoip_stop(struct netif *netif)
368{
369 struct autoip* autoip = netif_autoip_data(netif);
370
371 if (autoip != NULL) {
372 autoip->state = AUTOIP_STATE_OFF;
373 if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
374 netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
375 }
376 }
377 return ERR_OK;
378}
379
383void
384autoip_tmr(void)
385{
386 struct netif *netif = netif_list;
387 /* loop through netif's */
388 while (netif != NULL) {
389 struct autoip* autoip = netif_autoip_data(netif);
390 /* only act on AutoIP configured interfaces */
391 if (autoip != NULL) {
392 if (autoip->lastconflict > 0) {
393 autoip->lastconflict--;
394 }
395
397 ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n",
398 (u16_t)(autoip->state), autoip->ttw));
399
400 if (autoip->ttw > 0) {
401 autoip->ttw--;
402 }
403
404 switch(autoip->state) {
405 case AUTOIP_STATE_PROBING:
406 if (autoip->ttw == 0) {
407 if (autoip->sent_num >= PROBE_NUM) {
408 /* Switch to ANNOUNCING: now we can bind to an IP address and use it */
409 autoip->state = AUTOIP_STATE_ANNOUNCING;
410 autoip_bind(netif);
411 /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP
412 which counts as an announcement */
413 autoip->sent_num = 1;
414 autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
416 ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
417 ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
418 ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
419 } else {
420 autoip_arp_probe(netif);
421 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n"));
422 autoip->sent_num++;
423 if (autoip->sent_num == PROBE_NUM) {
424 /* calculate time to wait to for announce */
425 autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
426 } else {
427 /* calculate time to wait to next probe */
428 autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
429 ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) +
430 PROBE_MIN * AUTOIP_TICKS_PER_SECOND);
431 }
432 }
433 }
434 break;
435
436 case AUTOIP_STATE_ANNOUNCING:
437 if (autoip->ttw == 0) {
438 autoip_arp_announce(netif);
439 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n"));
440 autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
441 autoip->sent_num++;
442
443 if (autoip->sent_num >= ANNOUNCE_NUM) {
444 autoip->state = AUTOIP_STATE_BOUND;
445 autoip->sent_num = 0;
446 autoip->ttw = 0;
448 ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
449 ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
450 ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
451 }
452 }
453 break;
454
455 default:
456 /* nothing to do in other states */
457 break;
458 }
459 }
460 /* proceed to next network interface */
461 netif = netif->next;
462 }
463}
464
471void
472autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
473{
474 struct autoip* autoip = netif_autoip_data(netif);
475
476 LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
477 if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) {
478 /* when ip.src == llipaddr && hw.src != netif->hwaddr
479 *
480 * when probing ip.dst == llipaddr && hw.src != netif->hwaddr
481 * we have a conflict and must solve it
482 */
483 ip4_addr_t sipaddr, dipaddr;
484 struct eth_addr netifaddr;
485 ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
486
487 /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without
488 * structure packing (not using structure copy which breaks strict-aliasing rules).
489 */
490 IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
491 IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
492
493 if (autoip->state == AUTOIP_STATE_PROBING) {
494 /* RFC 3927 Section 2.2.1:
495 * from beginning to after ANNOUNCE_WAIT
496 * seconds we have a conflict if
497 * ip.src == llipaddr OR
498 * ip.dst == llipaddr && hw.src != own hwaddr
499 */
500 if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) ||
501 (ip4_addr_isany_val(sipaddr) &&
502 ip4_addr_cmp(&dipaddr, &autoip->llipaddr) &&
503 !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
505 ("autoip_arp_reply(): Probe Conflict detected\n"));
506 autoip_restart(netif);
507 }
508 } else {
509 /* RFC 3927 Section 2.5:
510 * in any state we have a conflict if
511 * ip.src == llipaddr && hw.src != own hwaddr
512 */
513 if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) &&
514 !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
516 ("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
517 autoip_handle_arp_conflict(netif);
518 }
519 }
520 }
521}
522
529u8_t
530autoip_supplied_address(const struct netif *netif)
531{
532 if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) {
533 struct autoip* autoip = netif_autoip_data(netif);
534 return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING);
535 }
536 return 0;
537}
538
539u8_t
540autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr)
541{
542 struct autoip* autoip = netif_autoip_data(netif);
543 return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr));
544}
545
546#endif /* LWIP_IPV4 && LWIP_AUTOIP */
#define LWIP_DEBUGF(debug, message)
Definition debug.h:183
#define LWIP_DBG_STATE
Definition debug.h:104
#define LWIP_DBG_LEVEL_WARNING
Definition debug.h:74
#define LWIP_DBG_TRACE
Definition debug.h:102
s8_t err_t
Definition err.h:76
@ ERR_OK
Definition err.h:82
@ ERR_MEM
Definition err.h:84
@ ERR_ARG
Definition err.h:115
#define AUTOIP_DEBUG
Definition opt.h:2854
#define netif_is_up(netif)
Definition netif.h:420
#define ETHADDR16_COPY(dst, src)
void * mem_malloc(mem_size_t size)
Definition mem.c:622
struct netif * netif_list
Definition netif.c:123
Definition netif.h:244
char name[2]
Definition netif.h:326
u8_t num
Definition netif.h:328
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition netif.h:322
struct netif * next
Definition netif.h:246