2 This file is part of systemd.
4 Copyright (C) 2014 Axis Communications AB. All rights reserved.
5 Copyright (C) 2015 Tom Gundersen
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <arpa/inet.h>
27 #include "sd-ipv4acd.h"
29 #include "alloc-util.h"
31 #include "ether-addr-util.h"
33 #include "in-addr-util.h"
35 #include "random-util.h"
36 #include "siphash24.h"
39 /* Constants from the RFC */
44 #define ANNOUNCE_WAIT 2
45 #define ANNOUNCE_NUM 2
46 #define ANNOUNCE_INTERVAL 2
47 #define MAX_CONFLICTS 10
48 #define RATE_LIMIT_INTERVAL 60
49 #define DEFEND_INTERVAL 10
51 #define IPV4ACD_NETWORK 0xA9FE0000UL
52 #define IPV4ACD_NETMASK 0xFFFF0000UL
54 #define log_ipv4acd_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "ACD: " fmt, ##__VA_ARGS__)
55 #define log_ipv4acd(ll, fmt, ...) log_ipv4acd_errno(ll, 0, fmt, ##__VA_ARGS__)
57 typedef enum IPv4ACDState
{
59 IPV4ACD_STATE_WAITING_PROBE
,
60 IPV4ACD_STATE_PROBING
,
61 IPV4ACD_STATE_WAITING_ANNOUNCE
,
62 IPV4ACD_STATE_ANNOUNCING
,
63 IPV4ACD_STATE_RUNNING
,
65 _IPV4ACD_STATE_INVALID
= -1
76 sd_event_source
*receive_message
;
77 sd_event_source
*timer
;
81 struct ether_addr mac_addr
;
84 sd_ipv4acd_callback_t callback
;
88 sd_ipv4acd
*sd_ipv4acd_ref(sd_ipv4acd
*ll
) {
92 assert_se(ll
->n_ref
>= 1);
98 sd_ipv4acd
*sd_ipv4acd_unref(sd_ipv4acd
*ll
) {
102 assert_se(ll
->n_ref
>= 1);
108 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
109 ll
->fd
= safe_close(ll
->fd
);
111 ll
->timer
= sd_event_source_unref(ll
->timer
);
113 sd_ipv4acd_detach_event(ll
);
120 int sd_ipv4acd_new(sd_ipv4acd
**ret
) {
121 _cleanup_(sd_ipv4acd_unrefp
) sd_ipv4acd
*ll
= NULL
;
123 assert_return(ret
, -EINVAL
);
125 ll
= new0(sd_ipv4acd
, 1);
130 ll
->state
= IPV4ACD_STATE_INIT
;
140 static void ipv4acd_set_state(sd_ipv4acd
*ll
, IPv4ACDState st
, bool reset_counter
) {
143 assert(st
< _IPV4ACD_STATE_MAX
);
145 if (st
== ll
->state
&& !reset_counter
)
153 static void ipv4acd_client_notify(sd_ipv4acd
*ll
, int event
) {
159 ll
->callback(ll
, event
, ll
->userdata
);
162 static void ipv4acd_stop(sd_ipv4acd
*ll
) {
165 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
166 ll
->fd
= safe_close(ll
->fd
);
168 ll
->timer
= sd_event_source_unref(ll
->timer
);
170 log_ipv4acd(ll
, "STOPPED");
172 ipv4acd_set_state (ll
, IPV4ACD_STATE_INIT
, true);
175 int sd_ipv4acd_stop(sd_ipv4acd
*ll
) {
176 assert_return(ll
, -EINVAL
);
180 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_STOP
);
185 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
);
187 static int ipv4acd_set_next_wakeup(sd_ipv4acd
*ll
, int sec
, int random_sec
) {
188 _cleanup_(sd_event_source_unrefp
) sd_event_source
*timer
= NULL
;
194 assert(random_sec
>= 0);
197 next_timeout
= sec
* USEC_PER_SEC
;
200 next_timeout
+= random_u32() % (random_sec
* USEC_PER_SEC
);
202 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &time_now
) >= 0);
204 r
= sd_event_add_time(ll
->event
, &timer
, clock_boottime_or_monotonic(),
205 time_now
+ next_timeout
, 0, ipv4acd_on_timeout
, ll
);
209 r
= sd_event_source_set_priority(timer
, ll
->event_priority
);
213 r
= sd_event_source_set_description(timer
, "ipv4acd-timer");
217 ll
->timer
= sd_event_source_unref(ll
->timer
);
224 static bool ipv4acd_arp_conflict(sd_ipv4acd
*ll
, struct ether_arp
*arp
) {
229 if (memcmp(arp
->arp_spa
, &ll
->address
, sizeof(ll
->address
)) == 0)
232 /* the TPA matched instead of the SPA, this is not a conflict */
236 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
237 sd_ipv4acd
*ll
= userdata
;
243 case IPV4ACD_STATE_INIT
:
245 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_PROBE
, true);
247 if (ll
->conflict
>= MAX_CONFLICTS
) {
248 log_ipv4acd(ll
, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL
);
250 r
= ipv4acd_set_next_wakeup(ll
, RATE_LIMIT_INTERVAL
, PROBE_WAIT
);
256 r
= ipv4acd_set_next_wakeup(ll
, 0, PROBE_WAIT
);
262 case IPV4ACD_STATE_WAITING_PROBE
:
263 case IPV4ACD_STATE_PROBING
:
265 r
= arp_send_probe(ll
->fd
, ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
267 log_ipv4acd_errno(ll
, r
, "Failed to send ARP probe: %m");
270 _cleanup_free_
char *address
= NULL
;
271 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
273 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
275 log_ipv4acd(ll
, "Probing %s", address
);
278 if (ll
->iteration
< PROBE_NUM
- 2) {
279 ipv4acd_set_state(ll
, IPV4ACD_STATE_PROBING
, false);
281 r
= ipv4acd_set_next_wakeup(ll
, PROBE_MIN
, (PROBE_MAX
-PROBE_MIN
));
285 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_ANNOUNCE
, true);
287 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_WAIT
, 0);
294 case IPV4ACD_STATE_ANNOUNCING
:
295 if (ll
->iteration
>= ANNOUNCE_NUM
- 1) {
296 ipv4acd_set_state(ll
, IPV4ACD_STATE_RUNNING
, false);
300 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
301 /* Send announcement packet */
302 r
= arp_send_announcement(ll
->fd
, ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
304 log_ipv4acd_errno(ll
, r
, "Failed to send ARP announcement: %m");
307 log_ipv4acd(ll
, "ANNOUNCE");
309 ipv4acd_set_state(ll
, IPV4ACD_STATE_ANNOUNCING
, false);
311 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_INTERVAL
, 0);
315 if (ll
->iteration
== 0) {
317 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_BIND
);
322 assert_not_reached("Invalid state.");
332 static void ipv4acd_on_conflict(sd_ipv4acd
*ll
) {
333 _cleanup_free_
char *address
= NULL
;
334 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
341 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
343 log_ipv4acd(ll
, "Conflict on %s (%u)", address
, ll
->conflict
);
347 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_CONFLICT
);
350 static int ipv4acd_on_packet(
356 sd_ipv4acd
*ll
= userdata
;
357 struct ether_arp packet
;
365 n
= recv(fd
, &packet
, sizeof(struct ether_arp
), 0);
367 if (errno
== EAGAIN
|| errno
== EINTR
)
370 r
= log_ipv4acd_errno(ll
, errno
, "Failed to read ARP packet: %m");
373 if ((size_t) n
!= sizeof(struct ether_arp
)) {
374 log_ipv4acd(ll
, "Ignoring too short ARP packet.");
380 case IPV4ACD_STATE_ANNOUNCING
:
381 case IPV4ACD_STATE_RUNNING
:
383 if (ipv4acd_arp_conflict(ll
, &packet
)) {
386 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
389 if (ts
> ll
->defend_window
) {
390 ll
->defend_window
= ts
+ DEFEND_INTERVAL
* USEC_PER_SEC
;
391 r
= arp_send_announcement(ll
->fd
, ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
393 log_ipv4acd_errno(ll
, r
, "Failed to send ARP announcement: %m");
396 log_ipv4acd(ll
, "DEFEND");
399 ipv4acd_on_conflict(ll
);
403 case IPV4ACD_STATE_WAITING_PROBE
:
404 case IPV4ACD_STATE_PROBING
:
405 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
406 /* BPF ensures this packet indicates a conflict */
407 ipv4acd_on_conflict(ll
);
411 assert_not_reached("Invalid state.");
421 int sd_ipv4acd_set_ifindex(sd_ipv4acd
*ll
, int ifindex
) {
422 assert_return(ll
, -EINVAL
);
423 assert_return(ifindex
> 0, -EINVAL
);
424 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
426 ll
->ifindex
= ifindex
;
431 int sd_ipv4acd_set_mac(sd_ipv4acd
*ll
, const struct ether_addr
*addr
) {
432 assert_return(ll
, -EINVAL
);
433 assert_return(addr
, -EINVAL
);
434 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
436 memcpy(&ll
->mac_addr
, addr
, ETH_ALEN
);
441 int sd_ipv4acd_detach_event(sd_ipv4acd
*ll
) {
442 assert_return(ll
, -EINVAL
);
444 ll
->event
= sd_event_unref(ll
->event
);
449 int sd_ipv4acd_attach_event(sd_ipv4acd
*ll
, sd_event
*event
, int64_t priority
) {
452 assert_return(ll
, -EINVAL
);
453 assert_return(!ll
->event
, -EBUSY
);
456 ll
->event
= sd_event_ref(event
);
458 r
= sd_event_default(&ll
->event
);
463 ll
->event_priority
= priority
;
468 int sd_ipv4acd_set_callback(sd_ipv4acd
*ll
, sd_ipv4acd_callback_t cb
, void *userdata
) {
469 assert_return(ll
, -EINVAL
);
472 ll
->userdata
= userdata
;
477 int sd_ipv4acd_set_address(sd_ipv4acd
*ll
, const struct in_addr
*address
) {
478 assert_return(ll
, -EINVAL
);
479 assert_return(address
, -EINVAL
);
480 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
482 ll
->address
= address
->s_addr
;
487 int sd_ipv4acd_is_running(sd_ipv4acd
*ll
) {
488 assert_return(ll
, false);
490 return ll
->state
!= IPV4ACD_STATE_INIT
;
493 int sd_ipv4acd_start(sd_ipv4acd
*ll
) {
496 assert_return(ll
, -EINVAL
);
497 assert_return(ll
->event
, -EINVAL
);
498 assert_return(ll
->ifindex
> 0, -EINVAL
);
499 assert_return(ll
->address
!= 0, -EINVAL
);
500 assert_return(!ether_addr_is_null(&ll
->mac_addr
), -EINVAL
);
501 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
503 ll
->defend_window
= 0;
505 r
= arp_network_bind_raw_socket(ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
509 ll
->fd
= safe_close(ll
->fd
);
512 r
= sd_event_add_io(ll
->event
, &ll
->receive_message
, ll
->fd
,
513 EPOLLIN
, ipv4acd_on_packet
, ll
);
517 r
= sd_event_source_set_priority(ll
->receive_message
, ll
->event_priority
);
521 r
= sd_event_source_set_description(ll
->receive_message
, "ipv4acd-receive-message");
525 r
= ipv4acd_set_next_wakeup(ll
, 0, 0);