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 0xA9FE0000L
52 #define IPV4ACD_NETMASK 0xFFFF0000L
54 #define log_ipv4acd_full(ll, level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "ACD: " fmt, ##__VA_ARGS__)
56 #define log_ipv4acd_debug(ll, ...) log_ipv4acd_full(ll, LOG_DEBUG, 0, ##__VA_ARGS__)
57 #define log_ipv4acd_info(ll, ...) log_ipv4acd_full(ll, LOG_INFO, 0, ##__VA_ARGS__)
58 #define log_ipv4acd_notice(ll, ...) log_ipv4acd_full(ll, LOG_NOTICE, 0, ##__VA_ARGS__)
59 #define log_ipv4acd_warning(ll, ...) log_ipv4acd_full(ll, LOG_WARNING, 0, ##__VA_ARGS__)
60 #define log_ipv4acd_error(ll, ...) log_ipv4acd_full(ll, LOG_ERR, 0, ##__VA_ARGS__)
62 #define log_ipv4acd_debug_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_DEBUG, error, ##__VA_ARGS__)
63 #define log_ipv4acd_info_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_INFO, error, ##__VA_ARGS__)
64 #define log_ipv4acd_notice_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_NOTICE, error, ##__VA_ARGS__)
65 #define log_ipv4acd_warning_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_WARNING, error, ##__VA_ARGS__)
66 #define log_ipv4acd_error_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_ERR, error, ##__VA_ARGS__)
68 typedef enum IPv4ACDState
{
70 IPV4ACD_STATE_WAITING_PROBE
,
71 IPV4ACD_STATE_PROBING
,
72 IPV4ACD_STATE_WAITING_ANNOUNCE
,
73 IPV4ACD_STATE_ANNOUNCING
,
74 IPV4ACD_STATE_RUNNING
,
76 _IPV4ACD_STATE_INVALID
= -1
87 sd_event_source
*receive_message
;
88 sd_event_source
*timer
;
92 struct ether_addr mac_addr
;
95 sd_ipv4acd_callback_t callback
;
99 sd_ipv4acd
*sd_ipv4acd_ref(sd_ipv4acd
*ll
) {
103 assert_se(ll
->n_ref
>= 1);
109 sd_ipv4acd
*sd_ipv4acd_unref(sd_ipv4acd
*ll
) {
113 assert_se(ll
->n_ref
>= 1);
119 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
120 ll
->fd
= safe_close(ll
->fd
);
122 ll
->timer
= sd_event_source_unref(ll
->timer
);
124 sd_ipv4acd_detach_event(ll
);
131 int sd_ipv4acd_new(sd_ipv4acd
**ret
) {
132 _cleanup_(sd_ipv4acd_unrefp
) sd_ipv4acd
*ll
= NULL
;
134 assert_return(ret
, -EINVAL
);
136 ll
= new0(sd_ipv4acd
, 1);
141 ll
->state
= IPV4ACD_STATE_INIT
;
151 static void ipv4acd_set_state(sd_ipv4acd
*ll
, IPv4ACDState st
, bool reset_counter
) {
154 assert(st
< _IPV4ACD_STATE_MAX
);
156 if (st
== ll
->state
&& !reset_counter
)
164 static void ipv4acd_client_notify(sd_ipv4acd
*ll
, int event
) {
170 ll
->callback(ll
, event
, ll
->userdata
);
173 static void ipv4acd_stop(sd_ipv4acd
*ll
) {
176 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
177 ll
->fd
= safe_close(ll
->fd
);
179 ll
->timer
= sd_event_source_unref(ll
->timer
);
181 log_ipv4acd_debug(ll
, "STOPPED");
183 ipv4acd_set_state (ll
, IPV4ACD_STATE_INIT
, true);
186 int sd_ipv4acd_stop(sd_ipv4acd
*ll
) {
187 assert_return(ll
, -EINVAL
);
191 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_STOP
);
196 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
);
198 static int ipv4acd_set_next_wakeup(sd_ipv4acd
*ll
, int sec
, int random_sec
) {
199 _cleanup_(sd_event_source_unrefp
) sd_event_source
*timer
= NULL
;
205 assert(random_sec
>= 0);
208 next_timeout
= sec
* USEC_PER_SEC
;
211 next_timeout
+= random_u32() % (random_sec
* USEC_PER_SEC
);
213 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &time_now
) >= 0);
215 r
= sd_event_add_time(ll
->event
, &timer
, clock_boottime_or_monotonic(),
216 time_now
+ next_timeout
, 0, ipv4acd_on_timeout
, ll
);
220 r
= sd_event_source_set_priority(timer
, ll
->event_priority
);
224 r
= sd_event_source_set_description(timer
, "ipv4acd-timer");
228 ll
->timer
= sd_event_source_unref(ll
->timer
);
235 static bool ipv4acd_arp_conflict(sd_ipv4acd
*ll
, struct ether_arp
*arp
) {
240 if (memcmp(arp
->arp_spa
, &ll
->address
, sizeof(ll
->address
)) == 0)
243 /* the TPA matched instead of the SPA, this is not a conflict */
247 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
248 sd_ipv4acd
*ll
= userdata
;
254 case IPV4ACD_STATE_INIT
:
256 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_PROBE
, true);
258 if (ll
->conflict
>= MAX_CONFLICTS
) {
259 log_ipv4acd_notice(ll
, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL
);
260 r
= ipv4acd_set_next_wakeup(ll
, RATE_LIMIT_INTERVAL
, PROBE_WAIT
);
266 r
= ipv4acd_set_next_wakeup(ll
, 0, PROBE_WAIT
);
272 case IPV4ACD_STATE_WAITING_PROBE
:
273 case IPV4ACD_STATE_PROBING
:
275 r
= arp_send_probe(ll
->fd
, ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
277 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP probe: %m");
280 _cleanup_free_
char *address
= NULL
;
281 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
283 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
285 log_ipv4acd_debug(ll
, "Probing %s", address
);
288 if (ll
->iteration
< PROBE_NUM
- 2) {
289 ipv4acd_set_state(ll
, IPV4ACD_STATE_PROBING
, false);
291 r
= ipv4acd_set_next_wakeup(ll
, PROBE_MIN
, (PROBE_MAX
-PROBE_MIN
));
295 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_ANNOUNCE
, true);
297 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_WAIT
, 0);
304 case IPV4ACD_STATE_ANNOUNCING
:
305 if (ll
->iteration
>= ANNOUNCE_NUM
- 1) {
306 ipv4acd_set_state(ll
, IPV4ACD_STATE_RUNNING
, false);
310 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
311 /* Send announcement packet */
312 r
= arp_send_announcement(ll
->fd
, ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
314 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
317 log_ipv4acd_debug(ll
, "ANNOUNCE");
319 ipv4acd_set_state(ll
, IPV4ACD_STATE_ANNOUNCING
, false);
321 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_INTERVAL
, 0);
325 if (ll
->iteration
== 0) {
327 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_BIND
);
332 assert_not_reached("Invalid state.");
342 static void ipv4acd_on_conflict(sd_ipv4acd
*ll
) {
343 _cleanup_free_
char *address
= NULL
;
344 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
351 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
353 log_ipv4acd_debug(ll
, "Conflict on %s (%u)", address
, ll
->conflict
);
357 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_CONFLICT
);
360 static int ipv4acd_on_packet(
366 sd_ipv4acd
*ll
= userdata
;
367 struct ether_arp packet
;
375 n
= recv(fd
, &packet
, sizeof(struct ether_arp
), 0);
377 if (errno
== EAGAIN
|| errno
== EINTR
)
380 r
= log_ipv4acd_debug_errno(ll
, errno
, "Failed to read ARP packet: %m");
383 if ((size_t) n
!= sizeof(struct ether_arp
)) {
384 log_ipv4acd_debug(ll
, "Ignoring too short ARP packet.");
390 case IPV4ACD_STATE_ANNOUNCING
:
391 case IPV4ACD_STATE_RUNNING
:
393 if (ipv4acd_arp_conflict(ll
, &packet
)) {
396 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
399 if (ts
> ll
->defend_window
) {
400 ll
->defend_window
= ts
+ DEFEND_INTERVAL
* USEC_PER_SEC
;
401 r
= arp_send_announcement(ll
->fd
, ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
403 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
406 log_ipv4acd_debug(ll
, "DEFEND");
409 ipv4acd_on_conflict(ll
);
413 case IPV4ACD_STATE_WAITING_PROBE
:
414 case IPV4ACD_STATE_PROBING
:
415 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
416 /* BPF ensures this packet indicates a conflict */
417 ipv4acd_on_conflict(ll
);
421 assert_not_reached("Invalid state.");
431 int sd_ipv4acd_set_ifindex(sd_ipv4acd
*ll
, int ifindex
) {
432 assert_return(ll
, -EINVAL
);
433 assert_return(ifindex
> 0, -EINVAL
);
434 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
436 ll
->ifindex
= ifindex
;
441 int sd_ipv4acd_set_mac(sd_ipv4acd
*ll
, const struct ether_addr
*addr
) {
442 assert_return(ll
, -EINVAL
);
443 assert_return(addr
, -EINVAL
);
444 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
446 memcpy(&ll
->mac_addr
, addr
, ETH_ALEN
);
451 int sd_ipv4acd_detach_event(sd_ipv4acd
*ll
) {
452 assert_return(ll
, -EINVAL
);
454 ll
->event
= sd_event_unref(ll
->event
);
459 int sd_ipv4acd_attach_event(sd_ipv4acd
*ll
, sd_event
*event
, int64_t priority
) {
462 assert_return(ll
, -EINVAL
);
463 assert_return(!ll
->event
, -EBUSY
);
466 ll
->event
= sd_event_ref(event
);
468 r
= sd_event_default(&ll
->event
);
473 ll
->event_priority
= priority
;
478 int sd_ipv4acd_set_callback(sd_ipv4acd
*ll
, sd_ipv4acd_callback_t cb
, void *userdata
) {
479 assert_return(ll
, -EINVAL
);
482 ll
->userdata
= userdata
;
487 int sd_ipv4acd_set_address(sd_ipv4acd
*ll
, const struct in_addr
*address
) {
488 assert_return(ll
, -EINVAL
);
489 assert_return(address
, -EINVAL
);
490 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
492 ll
->address
= address
->s_addr
;
497 int sd_ipv4acd_is_running(sd_ipv4acd
*ll
) {
498 assert_return(ll
, false);
500 return ll
->state
!= IPV4ACD_STATE_INIT
;
503 int sd_ipv4acd_start(sd_ipv4acd
*ll
) {
506 assert_return(ll
, -EINVAL
);
507 assert_return(ll
->event
, -EINVAL
);
508 assert_return(ll
->ifindex
> 0, -EINVAL
);
509 assert_return(ll
->address
!= 0, -EINVAL
);
510 assert_return(!ether_addr_is_null(&ll
->mac_addr
), -EINVAL
);
511 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
513 ll
->defend_window
= 0;
515 r
= arp_network_bind_raw_socket(ll
->ifindex
, ll
->address
, &ll
->mac_addr
);
519 ll
->fd
= safe_close(ll
->fd
);
522 r
= sd_event_add_io(ll
->event
, &ll
->receive_message
, ll
->fd
,
523 EPOLLIN
, ipv4acd_on_packet
, ll
);
527 r
= sd_event_source_set_priority(ll
->receive_message
, ll
->event_priority
);
531 r
= sd_event_source_set_description(ll
->receive_message
, "ipv4acd-receive-message");
535 r
= ipv4acd_set_next_wakeup(ll
, 0, 0);