1 /**
2 * @file
3 *
4 * ACD IPv4 Address Conflict Detection
5 *
6 * This is an IPv4 address conflict detection implementation for the lwIP TCP/IP
7 * stack. It aims to be conform to RFC5227.
8 *
9 * @defgroup acd ACD
10 * @ingroup ip4
11 * ACD related functions
12 * USAGE:
13 *
14 * define @ref LWIP_ACD 1 in your lwipopts.h
15 * Options:
16 * ACD_TMR_INTERVAL msecs,
17 * I recommend a value of 100. The value must divide 1000 with a remainder almost 0.
18 * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 ....
19 *
20 * For fixed IP:
21 * - call acd_start after selecting an IP address. The caller will be informed
22 * on conflict status via the callback function.
23 *
24 * With AUTOIP:
25 * - will be called from the autoip module. No extra's needed.
26 *
27 * With DHCP:
28 * - enable LWIP_DHCP_DOES_ACD_CHECK. Then it will be called from the dhcp module.
29 * No extra's needed.
30 */
31
32 /*
33 *
34 * Copyright (c) 2007 Dominik Spies <[email protected]>
35 * Copyright (c) 2018 Jasper Verschueren <[email protected]>
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without modification,
39 * are permitted provided that the following conditions are met:
40 *
41 * 1. Redistributions of source code must retain the above copyright notice,
42 * this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright notice,
44 * this list of conditions and the following disclaimer in the documentation
45 * and/or other materials provided with the distribution.
46 * 3. The name of the author may not be used to endorse or promote products
47 * derived from this software without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
50 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
51 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
52 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
53 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
54 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
57 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
58 * OF SUCH DAMAGE.
59 *
60 * Author: Jasper Verschueren <[email protected]>
61 * Author: Dominik Spies <[email protected]>
62 */
63
64 #include "lwip/opt.h"
65
66 /* don't build if not configured for use in lwipopts.h */
67 #if LWIP_IPV4 && LWIP_ACD
68
69 #include <string.h>
70
71 #include "lwip/acd.h"
72 #include "lwip/prot/acd.h"
73
74 #define ACD_FOREACH(acd, acd_list) for ((acd) = acd_list; (acd) != NULL; (acd) = (acd)->next)
75
76 #define ACD_TICKS_PER_SECOND (1000 / ACD_TMR_INTERVAL)
77
78 /* Define good random function (LWIP_RAND) in lwipopts.h */
79 #ifdef LWIP_RAND
80 #define LWIP_ACD_RAND(netif, acd) LWIP_RAND()
81 #else /* LWIP_RAND */
82 #ifdef LWIP_AUTOIP_RAND
83 #include "lwip/autoip.h"
84 #define LWIP_ACD_RAND(netif, acd) LWIP_AUTOIP_RAND(netif) /* for backwards compatibility */
85 #else
86 #define LWIP_ACD_RAND(netif, acd) ((((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
87 ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
88 ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
89 ((u32_t)((netif->hwaddr[4]) & 0xff))) + \
90 (acd->sent_num))
91 #endif /* LWIP_AUTOIP_RAND */
92 #endif /* LWIP_RAND */
93
94
95 #define ACD_RANDOM_PROBE_WAIT(netif, acd) (LWIP_ACD_RAND(netif, acd) % \
96 (PROBE_WAIT * ACD_TICKS_PER_SECOND))
97
98 #define ACD_RANDOM_PROBE_INTERVAL(netif, acd) ((LWIP_ACD_RAND(netif, acd) % \
99 ((PROBE_MAX - PROBE_MIN) * ACD_TICKS_PER_SECOND)) + \
100 (PROBE_MIN * ACD_TICKS_PER_SECOND ))
101
102 /* Function definitions */
103 static void acd_restart(struct netif *netif, struct acd *acd);
104 static void acd_handle_arp_conflict(struct netif *netif, struct acd *acd);
105 static void acd_put_in_passive_mode(struct netif *netif, struct acd *acd);
106
107 /**
108 * @ingroup acd
109 * Add ACD client to the client list and initialize callback function
110 *
111 * @param netif network interface on which to start the acd
112 * client
113 * @param acd acd module to be added to the list
114 * @param acd_conflict_callback callback to be called when conflict information
115 * is available
116 */
117 err_t
acd_add(struct netif * netif,struct acd * acd,acd_conflict_callback_t acd_conflict_callback)118 acd_add(struct netif *netif, struct acd *acd,
119 acd_conflict_callback_t acd_conflict_callback)
120 {
121 struct acd *acd2;
122
123 /* Set callback */
124 LWIP_ASSERT_CORE_LOCKED();
125 LWIP_ASSERT("acd_conflict_callback != NULL", acd_conflict_callback != NULL);
126 acd->acd_conflict_callback = acd_conflict_callback;
127
128 /* Check if the acd struct is already added */
129 for (acd2 = netif->acd_list; acd2 != NULL; acd2 = acd2->next) {
130 if (acd2 == acd) {
131 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
132 ("acd_add(): acd already added to list\n"));
133 return ERR_OK;
134 }
135 }
136
137 /* add acd struct to the list */
138 acd->next = netif->acd_list;
139 netif->acd_list = acd;
140
141 return ERR_OK;
142 }
143
144 /**
145 * @ingroup acd
146 * Start ACD client
147 *
148 * @param netif network interface on which to start the acd client
149 * @param acd acd module to start
150 * @param ipaddr ip address to perform acd on
151 */
152 err_t
acd_start(struct netif * netif,struct acd * acd,ip4_addr_t ipaddr)153 acd_start(struct netif *netif, struct acd *acd, ip4_addr_t ipaddr)
154 {
155 err_t result = ERR_OK;
156
157 LWIP_UNUSED_ARG(netif);
158 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
159 ("acd_start(netif=%p) %c%c%"U16_F"\n",
160 (void *)netif, netif->name[0],
161 netif->name[1], (u16_t)netif->num));
162
163 /* init probing state */
164 acd->sent_num = 0;
165 acd->lastconflict = 0;
166 ip4_addr_copy(acd->ipaddr, ipaddr);
167 acd->state = ACD_STATE_PROBE_WAIT;
168
169 acd->ttw = (u16_t)(ACD_RANDOM_PROBE_WAIT(netif, acd));
170
171 return result;
172 }
173
174 /**
175 * @ingroup acd
176 * Stop ACD client
177 *
178 * @param acd acd module to stop
179 */
180 err_t
acd_stop(struct acd * acd)181 acd_stop(struct acd *acd)
182 {
183 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("acd_stop\n"));
184
185 if (acd != NULL) {
186 acd->state = ACD_STATE_OFF;
187 }
188 return ERR_OK;
189 }
190
191 /**
192 * @ingroup acd
193 * Inform the ACD modules when the link goes down
194 *
195 * @param netif network interface on which to inform the ACD clients
196 */
197 void
acd_network_changed_link_down(struct netif * netif)198 acd_network_changed_link_down(struct netif *netif)
199 {
200 struct acd *acd;
201 /* loop over the acd's*/
202 ACD_FOREACH(acd, netif->acd_list) {
203 acd_stop(acd);
204 }
205 }
206
207 /**
208 * Has to be called in loop every ACD_TMR_INTERVAL milliseconds
209 */
210 void
acd_tmr(void)211 acd_tmr(void)
212 {
213 struct netif *netif;
214 struct acd *acd;
215 /* loop through netif's */
216 NETIF_FOREACH(netif) {
217 ACD_FOREACH(acd, netif->acd_list) {
218 if (acd->lastconflict > 0) {
219 acd->lastconflict--;
220 }
221
222 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE,
223 ("acd_tmr() ACD-State: %"U16_F", ttw=%"U16_F"\n",
224 (u16_t)(acd->state), acd->ttw));
225
226 if (acd->ttw > 0) {
227 acd->ttw--;
228 }
229
230 switch (acd->state) {
231 case ACD_STATE_PROBE_WAIT:
232 case ACD_STATE_PROBING:
233 if (acd->ttw == 0) {
234 acd->state = ACD_STATE_PROBING;
235 etharp_acd_probe(netif, &acd->ipaddr);
236 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE,
237 ("acd_tmr() PROBING Sent Probe\n"));
238 acd->sent_num++;
239 if (acd->sent_num >= PROBE_NUM) {
240 /* Switch to ANNOUNCE_WAIT: last probe is sent*/
241 acd->state = ACD_STATE_ANNOUNCE_WAIT;
242
243 acd->sent_num = 0;
244
245 /* calculate time to wait before announcing */
246 acd->ttw = (u16_t)(ANNOUNCE_WAIT * ACD_TICKS_PER_SECOND);
247 } else {
248 /* calculate time to wait to next probe */
249 acd->ttw = (u16_t)(ACD_RANDOM_PROBE_INTERVAL(netif, acd));
250 }
251 }
252 break;
253
254 case ACD_STATE_ANNOUNCE_WAIT:
255 case ACD_STATE_ANNOUNCING:
256 if (acd->ttw == 0) {
257 if (acd->sent_num == 0) {
258 acd->state = ACD_STATE_ANNOUNCING;
259
260 /* let acd user know that the address is good and can be used */
261 acd->acd_conflict_callback(netif, ACD_IP_OK);
262
263 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
264 ("acd_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
265 ip4_addr1_16(&acd->ipaddr), ip4_addr2_16(&acd->ipaddr),
266 ip4_addr3_16(&acd->ipaddr), ip4_addr4_16(&acd->ipaddr)));
267 }
268
269 etharp_acd_announce(netif, &acd->ipaddr);
270 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE,
271 ("acd_tmr() ANNOUNCING Sent Announce\n"));
272 acd->ttw = ANNOUNCE_INTERVAL * ACD_TICKS_PER_SECOND;
273 acd->sent_num++;
274
275 if (acd->sent_num >= ANNOUNCE_NUM) {
276 acd->state = ACD_STATE_ONGOING;
277 acd->sent_num = 0;
278 acd->ttw = 0;
279 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
280 ("acd_tmr(): changing state to ONGOING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
281 ip4_addr1_16(&acd->ipaddr), ip4_addr2_16(&acd->ipaddr),
282 ip4_addr3_16(&acd->ipaddr), ip4_addr4_16(&acd->ipaddr)));
283 }
284 }
285 break;
286
287 case ACD_STATE_RATE_LIMIT:
288 if (acd->ttw == 0) {
289 /* acd should be stopped because ipaddr isn't valid any more */
290 acd_stop(acd);
291 /* let the acd user (after rate limit interval) know that their is
292 * a conflict detected. So it can restart the address acquiring
293 * process.*/
294 acd->acd_conflict_callback(netif, ACD_RESTART_CLIENT);
295 }
296 break;
297
298 default:
299 /* nothing to do in other states */
300 break;
301 }
302 }
303 }
304 }
305
306 /**
307 * Restarts the acd module
308 *
309 * The number of conflicts is increased and the upper layer is informed.
310 */
311 static void
acd_restart(struct netif * netif,struct acd * acd)312 acd_restart(struct netif *netif, struct acd *acd)
313 {
314 /* increase conflict counter. */
315 acd->num_conflicts++;
316
317 /* Decline the address */
318 acd->acd_conflict_callback(netif, ACD_DECLINE);
319
320 /* if we tried more then MAX_CONFLICTS we must limit our rate for
321 * acquiring and probing addresses. compliant to RFC 5227 Section 2.1.1 */
322 if (acd->num_conflicts > MAX_CONFLICTS) {
323 acd->state = ACD_STATE_RATE_LIMIT;
324 acd->ttw = (u16_t)(RATE_LIMIT_INTERVAL * ACD_TICKS_PER_SECOND);
325 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
326 ("acd_restart(): rate limiting initiated. too many conflicts\n"));
327 }
328 else {
329 /* acd should be stopped because ipaddr isn't valid any more */
330 acd_stop(acd);
331 /* let the acd user know right away that their is a conflict detected.
332 * So it can restart the address acquiring process. */
333 acd->acd_conflict_callback(netif, ACD_RESTART_CLIENT);
334 }
335 }
336
337 /**
338 * Handles every incoming ARP Packet, called by etharp_input().
339 *
340 * @param netif network interface to use for acd processing
341 * @param hdr Incoming ARP packet
342 */
343 void
acd_arp_reply(struct netif * netif,struct etharp_hdr * hdr)344 acd_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
345 {
346 struct acd *acd;
347 ip4_addr_t sipaddr, dipaddr;
348 struct eth_addr netifaddr;
349 SMEMCPY(netifaddr.addr, netif->hwaddr, ETH_HWADDR_LEN);
350
351 /* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support
352 * compilers without structure packing (not using structure copy which
353 * breaks strict-aliasing rules).
354 */
355 IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &hdr->sipaddr);
356 IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&dipaddr, &hdr->dipaddr);
357
358 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE, ("acd_arp_reply()\n"));
359
360 /* loop over the acd's*/
361 ACD_FOREACH(acd, netif->acd_list) {
362 switch(acd->state) {
363 case ACD_STATE_OFF:
364 case ACD_STATE_RATE_LIMIT:
365 default:
366 /* do nothing */
367 break;
368
369 case ACD_STATE_PROBE_WAIT:
370 case ACD_STATE_PROBING:
371 case ACD_STATE_ANNOUNCE_WAIT:
372 /* RFC 5227 Section 2.1.1:
373 * from beginning to after ANNOUNCE_WAIT seconds we have a conflict if
374 * ip.src == ipaddr (someone is already using the address)
375 * OR
376 * ip.dst == ipaddr && hw.src != own hwaddr (someone else is probing it)
377 */
378 if ((ip4_addr_cmp(&sipaddr, &acd->ipaddr)) ||
379 (ip4_addr_isany_val(sipaddr) &&
380 ip4_addr_cmp(&dipaddr, &acd->ipaddr) &&
381 !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
382 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
383 ("acd_arp_reply(): Probe Conflict detected\n"));
384 acd_restart(netif, acd);
385 }
386 break;
387
388 case ACD_STATE_ANNOUNCING:
389 case ACD_STATE_ONGOING:
390 case ACD_STATE_PASSIVE_ONGOING:
391 /* RFC 5227 Section 2.4:
392 * in any state we have a conflict if
393 * ip.src == ipaddr && hw.src != own hwaddr (someone is using our address)
394 */
395 if (ip4_addr_cmp(&sipaddr, &acd->ipaddr) &&
396 !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
397 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
398 ("acd_arp_reply(): Conflicting ARP-Packet detected\n"));
399 acd_handle_arp_conflict(netif, acd);
400 }
401 break;
402 }
403 }
404 }
405
406 /**
407 * Handle a IP address conflict after an ARP conflict detection
408 */
409 static void
acd_handle_arp_conflict(struct netif * netif,struct acd * acd)410 acd_handle_arp_conflict(struct netif *netif, struct acd *acd)
411 {
412 /* RFC5227, 2.4 "Ongoing Address Conflict Detection and Address Defense"
413 allows three options where:
414 a) means retreat on the first conflict,
415 b) allows to keep an already configured address when having only one
416 conflict in DEFEND_INTERVAL seconds and
417 c) the host will not give up it's address and defend it indefinitely
418
419 We use option b) when the acd module represents the netif address, since it
420 helps to improve the chance that one of the two conflicting hosts may be
421 able to retain its address. while we are flexible enough to help network
422 performance
423
424 We use option a) when the acd module does not represent the netif address,
425 since we cannot have the acd module announcing or restarting. This
426 situation occurs for the LL acd module when a routable address is used on
427 the netif but the LL address is still open in the background. */
428
429 if (acd->state == ACD_STATE_PASSIVE_ONGOING) {
430 /* Imediatly back off on a conflict. */
431 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
432 ("acd_handle_arp_conflict(): conflict when we are in passive mode -> back off\n"));
433 acd_stop(acd);
434 acd->acd_conflict_callback(netif, ACD_DECLINE);
435 }
436 else {
437 if (acd->lastconflict > 0) {
438 /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */
439 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
440 ("acd_handle_arp_conflict(): conflict within DEFEND_INTERVAL -> retreating\n"));
441
442 /* Active TCP sessions are aborted when removing the ip address but a bad
443 * connection was inevitable anyway with conflicting hosts */
444 acd_restart(netif, acd);
445 } else {
446 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
447 ("acd_handle_arp_conflict(): we are defending, send ARP Announce\n"));
448 etharp_acd_announce(netif, &acd->ipaddr);
449 acd->lastconflict = DEFEND_INTERVAL * ACD_TICKS_PER_SECOND;
450 }
451 }
452 }
453
454 /**
455 * Put the acd module in passive ongoing conflict detection.
456 */
457 static void
acd_put_in_passive_mode(struct netif * netif,struct acd * acd)458 acd_put_in_passive_mode(struct netif *netif, struct acd *acd)
459 {
460 switch(acd->state) {
461 case ACD_STATE_OFF:
462 case ACD_STATE_PASSIVE_ONGOING:
463 default:
464 /* do nothing */
465 break;
466
467 case ACD_STATE_PROBE_WAIT:
468 case ACD_STATE_PROBING:
469 case ACD_STATE_ANNOUNCE_WAIT:
470 case ACD_STATE_RATE_LIMIT:
471 acd_stop(acd);
472 acd->acd_conflict_callback(netif, ACD_DECLINE);
473 break;
474
475 case ACD_STATE_ANNOUNCING:
476 case ACD_STATE_ONGOING:
477 acd->state = ACD_STATE_PASSIVE_ONGOING;
478 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
479 ("acd_put_in_passive_mode()\n"));
480 break;
481 }
482 }
483
484 /**
485 * @ingroup acd
486 * Inform the ACD modules of address changes
487 *
488 * @param netif network interface on which the address is changing
489 * @param old_addr old ip address
490 * @param new_addr new ip address
491 */
492 void
acd_netif_ip_addr_changed(struct netif * netif,const ip_addr_t * old_addr,const ip_addr_t * new_addr)493 acd_netif_ip_addr_changed(struct netif *netif, const ip_addr_t *old_addr,
494 const ip_addr_t *new_addr)
495 {
496 struct acd *acd;
497
498 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
499 ("acd_netif_ip_addr_changed(): Address changed\n"));
500
501 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
502 ("acd_netif_ip_addr_changed(): old address = %s\n", ipaddr_ntoa(old_addr)));
503 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
504 ("acd_netif_ip_addr_changed(): new address = %s\n", ipaddr_ntoa(new_addr)));
505
506 /* If we change from ANY to an IP or from an IP to ANY we do nothing */
507 if (ip_addr_isany(old_addr) || ip_addr_isany(new_addr)) {
508 return;
509 }
510
511 ACD_FOREACH(acd, netif->acd_list) {
512 /* Find ACD module of old address */
513 if(ip4_addr_cmp(&acd->ipaddr, ip_2_ip4(old_addr))) {
514 /* Did we change from a LL address to a routable address? */
515 if (ip_addr_islinklocal(old_addr) && !ip_addr_islinklocal(new_addr)) {
516 LWIP_DEBUGF(ACD_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
517 ("acd_netif_ip_addr_changed(): changed from LL to routable address\n"));
518 /* Put the module in passive conflict detection mode */
519 acd_put_in_passive_mode(netif, acd);
520 }
521 }
522 }
523 }
524
525 #endif /* LWIP_IPV4 && LWIP_ACD */
526