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"
37 #include "siphash24.h"
40 /* Constants from the RFC */
45 #define ANNOUNCE_WAIT 2
46 #define ANNOUNCE_NUM 2
47 #define ANNOUNCE_INTERVAL 2
48 #define MAX_CONFLICTS 10
49 #define RATE_LIMIT_INTERVAL 60
50 #define DEFEND_INTERVAL 10
52 #define IPV4ACD_NETWORK 0xA9FE0000L
53 #define IPV4ACD_NETMASK 0xFFFF0000L
55 #define log_ipv4acd_full(ll, level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "ACD: " fmt, ##__VA_ARGS__)
57 #define log_ipv4acd_debug(ll, ...) log_ipv4acd_full(ll, LOG_DEBUG, 0, ##__VA_ARGS__)
58 #define log_ipv4acd_info(ll, ...) log_ipv4acd_full(ll, LOG_INFO, 0, ##__VA_ARGS__)
59 #define log_ipv4acd_notice(ll, ...) log_ipv4acd_full(ll, LOG_NOTICE, 0, ##__VA_ARGS__)
60 #define log_ipv4acd_warning(ll, ...) log_ipv4acd_full(ll, LOG_WARNING, 0, ##__VA_ARGS__)
61 #define log_ipv4acd_error(ll, ...) log_ipv4acd_full(ll, LOG_ERR, 0, ##__VA_ARGS__)
63 #define log_ipv4acd_debug_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_DEBUG, error, ##__VA_ARGS__)
64 #define log_ipv4acd_info_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_INFO, error, ##__VA_ARGS__)
65 #define log_ipv4acd_notice_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_NOTICE, error, ##__VA_ARGS__)
66 #define log_ipv4acd_warning_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_WARNING, error, ##__VA_ARGS__)
67 #define log_ipv4acd_error_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_ERR, error, ##__VA_ARGS__)
69 typedef enum IPv4ACDState
{
71 IPV4ACD_STATE_WAITING_PROBE
,
72 IPV4ACD_STATE_PROBING
,
73 IPV4ACD_STATE_WAITING_ANNOUNCE
,
74 IPV4ACD_STATE_ANNOUNCING
,
75 IPV4ACD_STATE_RUNNING
,
77 _IPV4ACD_STATE_INVALID
= -1
88 sd_event_source
*receive_message
;
89 sd_event_source
*timer
;
93 struct ether_addr mac_addr
;
96 sd_ipv4acd_callback_t cb
;
100 sd_ipv4acd
*sd_ipv4acd_ref(sd_ipv4acd
*ll
) {
102 assert_se(REFCNT_INC(ll
->n_ref
) >= 2);
107 sd_ipv4acd
*sd_ipv4acd_unref(sd_ipv4acd
*ll
) {
108 if (!ll
|| REFCNT_DEC(ll
->n_ref
) > 0)
111 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
112 ll
->fd
= safe_close(ll
->fd
);
114 ll
->timer
= sd_event_source_unref(ll
->timer
);
116 sd_ipv4acd_detach_event(ll
);
123 int sd_ipv4acd_new(sd_ipv4acd
**ret
) {
124 _cleanup_(sd_ipv4acd_unrefp
) sd_ipv4acd
*ll
= NULL
;
126 assert_return(ret
, -EINVAL
);
128 ll
= new0(sd_ipv4acd
, 1);
132 ll
->n_ref
= REFCNT_INIT
;
133 ll
->state
= IPV4ACD_STATE_INIT
;
143 static void ipv4acd_set_state(sd_ipv4acd
*ll
, IPv4ACDState st
, bool reset_counter
) {
146 assert(st
< _IPV4ACD_STATE_MAX
);
148 if (st
== ll
->state
&& !reset_counter
)
156 static void ipv4acd_client_notify(sd_ipv4acd
*ll
, int event
) {
162 ll
->cb(ll
, event
, ll
->userdata
);
165 static void ipv4acd_stop(sd_ipv4acd
*ll
) {
168 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
169 ll
->fd
= safe_close(ll
->fd
);
171 ll
->timer
= sd_event_source_unref(ll
->timer
);
173 log_ipv4acd_debug(ll
, "STOPPED");
175 ipv4acd_set_state (ll
, IPV4ACD_STATE_INIT
, true);
178 int sd_ipv4acd_stop(sd_ipv4acd
*ll
) {
179 assert_return(ll
, -EINVAL
);
183 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_STOP
);
188 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
);
190 static int ipv4acd_set_next_wakeup(sd_ipv4acd
*ll
, int sec
, int random_sec
) {
191 _cleanup_(sd_event_source_unrefp
) sd_event_source
*timer
= NULL
;
197 assert(random_sec
>= 0);
200 next_timeout
= sec
* USEC_PER_SEC
;
203 next_timeout
+= random_u32() % (random_sec
* USEC_PER_SEC
);
205 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &time_now
) >= 0);
207 r
= sd_event_add_time(ll
->event
, &timer
, clock_boottime_or_monotonic(),
208 time_now
+ next_timeout
, 0, ipv4acd_on_timeout
, ll
);
212 r
= sd_event_source_set_priority(timer
, ll
->event_priority
);
216 r
= sd_event_source_set_description(timer
, "ipv4acd-timer");
220 ll
->timer
= sd_event_source_unref(ll
->timer
);
227 static bool ipv4acd_arp_conflict(sd_ipv4acd
*ll
, struct ether_arp
*arp
) {
232 if (memcmp(arp
->arp_spa
, &ll
->address
, sizeof(ll
->address
)) == 0)
235 /* the TPA matched instead of the SPA, this is not a conflict */
239 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
240 sd_ipv4acd
*ll
= userdata
;
246 case IPV4ACD_STATE_INIT
:
248 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_PROBE
, true);
250 if (ll
->conflict
>= MAX_CONFLICTS
) {
251 log_ipv4acd_notice(ll
, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL
);
252 r
= ipv4acd_set_next_wakeup(ll
, RATE_LIMIT_INTERVAL
, PROBE_WAIT
);
258 r
= ipv4acd_set_next_wakeup(ll
, 0, PROBE_WAIT
);
264 case IPV4ACD_STATE_WAITING_PROBE
:
265 case IPV4ACD_STATE_PROBING
:
267 r
= arp_send_probe(ll
->fd
, ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
269 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP probe: %m");
272 _cleanup_free_
char *address
= NULL
;
273 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
275 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
277 log_ipv4acd_debug(ll
, "Probing %s", address
);
280 if (ll
->iteration
< PROBE_NUM
- 2) {
281 ipv4acd_set_state(ll
, IPV4ACD_STATE_PROBING
, false);
283 r
= ipv4acd_set_next_wakeup(ll
, PROBE_MIN
, (PROBE_MAX
-PROBE_MIN
));
287 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_ANNOUNCE
, true);
289 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_WAIT
, 0);
296 case IPV4ACD_STATE_ANNOUNCING
:
297 if (ll
->iteration
>= ANNOUNCE_NUM
- 1) {
298 ipv4acd_set_state(ll
, IPV4ACD_STATE_RUNNING
, false);
302 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
303 /* Send announcement packet */
304 r
= arp_send_announcement(ll
->fd
, ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
306 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
309 log_ipv4acd_debug(ll
, "ANNOUNCE");
311 ipv4acd_set_state(ll
, IPV4ACD_STATE_ANNOUNCING
, false);
313 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_INTERVAL
, 0);
317 if (ll
->iteration
== 0) {
319 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_BIND
);
324 assert_not_reached("Invalid state.");
334 static void ipv4acd_on_conflict(sd_ipv4acd
*ll
) {
335 _cleanup_free_
char *address
= NULL
;
336 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
343 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
345 log_ipv4acd_debug(ll
, "Conflict on %s (%u)", address
, ll
->conflict
);
349 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_CONFLICT
);
352 static int ipv4acd_on_packet(
358 sd_ipv4acd
*ll
= userdata
;
359 struct ether_arp packet
;
367 n
= recv(fd
, &packet
, sizeof(struct ether_arp
), 0);
369 if (errno
== EAGAIN
|| errno
== EINTR
)
372 r
= log_ipv4acd_debug_errno(ll
, errno
, "Failed to read ARP packet: %m");
375 if ((size_t) n
!= sizeof(struct ether_arp
)) {
376 log_ipv4acd_debug(ll
, "Ignoring too short ARP packet.");
382 case IPV4ACD_STATE_ANNOUNCING
:
383 case IPV4ACD_STATE_RUNNING
:
385 if (ipv4acd_arp_conflict(ll
, &packet
)) {
388 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
391 if (ts
> ll
->defend_window
) {
392 ll
->defend_window
= ts
+ DEFEND_INTERVAL
* USEC_PER_SEC
;
393 r
= arp_send_announcement(ll
->fd
, ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
395 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
398 log_ipv4acd_debug(ll
, "DEFEND");
401 ipv4acd_on_conflict(ll
);
405 case IPV4ACD_STATE_WAITING_PROBE
:
406 case IPV4ACD_STATE_PROBING
:
407 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
408 /* BPF ensures this packet indicates a conflict */
409 ipv4acd_on_conflict(ll
);
413 assert_not_reached("Invalid state.");
423 int sd_ipv4acd_set_ifindex(sd_ipv4acd
*ll
, int ifindex
) {
424 assert_return(ll
, -EINVAL
);
425 assert_return(ifindex
> 0, -EINVAL
);
426 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
428 ll
->ifindex
= ifindex
;
433 int sd_ipv4acd_set_mac(sd_ipv4acd
*ll
, const struct ether_addr
*addr
) {
434 assert_return(ll
, -EINVAL
);
435 assert_return(addr
, -EINVAL
);
436 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
438 memcpy(&ll
->mac_addr
, addr
, ETH_ALEN
);
443 int sd_ipv4acd_detach_event(sd_ipv4acd
*ll
) {
444 assert_return(ll
, -EINVAL
);
446 ll
->event
= sd_event_unref(ll
->event
);
451 int sd_ipv4acd_attach_event(sd_ipv4acd
*ll
, sd_event
*event
, int64_t priority
) {
454 assert_return(ll
, -EINVAL
);
455 assert_return(!ll
->event
, -EBUSY
);
458 ll
->event
= sd_event_ref(event
);
460 r
= sd_event_default(&ll
->event
);
465 ll
->event_priority
= priority
;
470 int sd_ipv4acd_set_callback(sd_ipv4acd
*ll
, sd_ipv4acd_callback_t cb
, void *userdata
) {
471 assert_return(ll
, -EINVAL
);
474 ll
->userdata
= userdata
;
479 int sd_ipv4acd_set_address(sd_ipv4acd
*ll
, const struct in_addr
*address
) {
480 assert_return(ll
, -EINVAL
);
481 assert_return(address
, -EINVAL
);
482 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
484 ll
->address
= address
->s_addr
;
489 int sd_ipv4acd_is_running(sd_ipv4acd
*ll
) {
490 assert_return(ll
, false);
492 return ll
->state
!= IPV4ACD_STATE_INIT
;
495 int sd_ipv4acd_start(sd_ipv4acd
*ll
) {
498 assert_return(ll
, -EINVAL
);
499 assert_return(ll
->event
, -EINVAL
);
500 assert_return(ll
->ifindex
> 0, -EINVAL
);
501 assert_return(ll
->address
!= 0, -EINVAL
);
502 assert_return(!ether_addr_is_null(&ll
->mac_addr
), -EINVAL
);
503 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
505 ll
->defend_window
= 0;
507 r
= arp_network_bind_raw_socket(ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
511 ll
->fd
= safe_close(ll
->fd
);
514 r
= sd_event_add_io(ll
->event
, &ll
->receive_message
, ll
->fd
,
515 EPOLLIN
, ipv4acd_on_packet
, ll
);
519 r
= sd_event_source_set_priority(ll
->receive_message
, ll
->event_priority
);
523 r
= sd_event_source_set_description(ll
->receive_message
, "ipv4acd-receive-message");
527 r
= ipv4acd_set_next_wakeup(ll
, 0, 0);