1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2014 Axis Communications AB. All rights reserved.
8 #include <netinet/if_ether.h>
12 #include "sd-ipv4acd.h"
14 #include "alloc-util.h"
16 #include "ether-addr-util.h"
17 #include "event-util.h"
19 #include "in-addr-util.h"
21 #include "network-common.h"
22 #include "random-util.h"
23 #include "siphash24.h"
24 #include "string-table.h"
25 #include "string-util.h"
26 #include "time-util.h"
28 /* Constants from the RFC */
29 #define PROBE_WAIT_USEC (1U * USEC_PER_SEC)
31 #define PROBE_MIN_USEC (1U * USEC_PER_SEC)
32 #define PROBE_MAX_USEC (2U * USEC_PER_SEC)
33 #define ANNOUNCE_WAIT_USEC (2U * USEC_PER_SEC)
34 #define ANNOUNCE_NUM 2U
35 #define ANNOUNCE_INTERVAL_USEC (2U * USEC_PER_SEC)
36 #define MAX_CONFLICTS 10U
37 #define RATE_LIMIT_INTERVAL_USEC (60U * USEC_PER_SEC)
38 #define DEFEND_INTERVAL_USEC (10U * USEC_PER_SEC)
40 typedef enum IPv4ACDState
{
42 IPV4ACD_STATE_STARTED
,
43 IPV4ACD_STATE_WAITING_PROBE
,
44 IPV4ACD_STATE_PROBING
,
45 IPV4ACD_STATE_WAITING_ANNOUNCE
,
46 IPV4ACD_STATE_ANNOUNCING
,
47 IPV4ACD_STATE_RUNNING
,
49 _IPV4ACD_STATE_INVALID
= -EINVAL
,
63 sd_event_source
*receive_message_event_source
;
64 sd_event_source
*timer_event_source
;
70 struct ether_addr mac_addr
;
74 sd_ipv4acd_callback_t callback
;
78 #define log_ipv4acd_errno(acd, error, fmt, ...) \
79 log_interface_prefix_full_errno( \
81 sd_ipv4acd_get_ifname(acd), \
82 error, fmt, ##__VA_ARGS__)
83 #define log_ipv4acd(acd, fmt, ...) \
84 log_interface_prefix_full_errno_zerook( \
86 sd_ipv4acd_get_ifname(acd), \
87 0, fmt, ##__VA_ARGS__)
89 static const char * const ipv4acd_state_table
[_IPV4ACD_STATE_MAX
] = {
90 [IPV4ACD_STATE_INIT
] = "init",
91 [IPV4ACD_STATE_STARTED
] = "started",
92 [IPV4ACD_STATE_WAITING_PROBE
] = "waiting-probe",
93 [IPV4ACD_STATE_PROBING
] = "probing",
94 [IPV4ACD_STATE_WAITING_ANNOUNCE
] = "waiting-announce",
95 [IPV4ACD_STATE_ANNOUNCING
] = "announcing",
96 [IPV4ACD_STATE_RUNNING
] = "running",
99 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(ipv4acd_state
, IPv4ACDState
);
101 static void ipv4acd_set_state(sd_ipv4acd
*acd
, IPv4ACDState st
, bool reset_counter
) {
103 assert(st
< _IPV4ACD_STATE_MAX
);
105 if (st
!= acd
->state
)
106 log_ipv4acd(acd
, "%s -> %s", ipv4acd_state_to_string(acd
->state
), ipv4acd_state_to_string(st
));
108 if (st
== acd
->state
&& !reset_counter
)
112 acd
->n_iteration
= 0;
116 static void ipv4acd_reset(sd_ipv4acd
*acd
) {
119 (void) event_source_disable(acd
->timer_event_source
);
120 acd
->receive_message_event_source
= sd_event_source_unref(acd
->receive_message_event_source
);
122 acd
->fd
= safe_close(acd
->fd
);
124 ipv4acd_set_state(acd
, IPV4ACD_STATE_INIT
, true);
127 static sd_ipv4acd
*ipv4acd_free(sd_ipv4acd
*acd
) {
130 acd
->timer_event_source
= sd_event_source_unref(acd
->timer_event_source
);
133 sd_ipv4acd_detach_event(acd
);
138 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4acd
, sd_ipv4acd
, ipv4acd_free
);
140 int sd_ipv4acd_new(sd_ipv4acd
**ret
) {
141 _cleanup_(sd_ipv4acd_unrefp
) sd_ipv4acd
*acd
= NULL
;
143 assert_return(ret
, -EINVAL
);
145 acd
= new(sd_ipv4acd
, 1);
149 *acd
= (sd_ipv4acd
) {
151 .state
= IPV4ACD_STATE_INIT
,
156 *ret
= TAKE_PTR(acd
);
161 static void ipv4acd_client_notify(sd_ipv4acd
*acd
, int event
) {
167 acd
->callback(acd
, event
, acd
->userdata
);
170 int sd_ipv4acd_stop(sd_ipv4acd
*acd
) {
171 IPv4ACDState old_state
;
176 old_state
= acd
->state
;
180 if (old_state
== IPV4ACD_STATE_INIT
)
183 log_ipv4acd(acd
, "STOPPED");
185 ipv4acd_client_notify(acd
, SD_IPV4ACD_EVENT_STOP
);
190 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
);
192 static int ipv4acd_set_next_wakeup(sd_ipv4acd
*acd
, usec_t usec
, usec_t random_usec
) {
193 usec_t next_timeout
, time_now
;
200 next_timeout
+= (usec_t
) random_u64() % random_usec
;
202 assert_se(sd_event_now(acd
->event
, clock_boottime_or_monotonic(), &time_now
) >= 0);
204 return event_reset_time(acd
->event
, &acd
->timer_event_source
,
205 clock_boottime_or_monotonic(),
206 time_now
+ next_timeout
, 0,
207 ipv4acd_on_timeout
, acd
,
208 acd
->event_priority
, "ipv4acd-timer", true);
211 static bool ipv4acd_arp_conflict(sd_ipv4acd
*acd
, struct ether_arp
*arp
) {
216 if (memcmp(arp
->arp_spa
, &acd
->address
, sizeof(acd
->address
)) == 0)
219 /* the TPA matched instead of the SPA, this is not a conflict */
223 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
224 sd_ipv4acd
*acd
= userdata
;
229 switch (acd
->state
) {
231 case IPV4ACD_STATE_STARTED
:
232 ipv4acd_set_state(acd
, IPV4ACD_STATE_WAITING_PROBE
, true);
234 if (acd
->n_conflict
>= MAX_CONFLICTS
) {
235 char ts
[FORMAT_TIMESPAN_MAX
];
236 log_ipv4acd(acd
, "Max conflicts reached, delaying by %s", format_timespan(ts
, sizeof(ts
), RATE_LIMIT_INTERVAL_USEC
, 0));
238 r
= ipv4acd_set_next_wakeup(acd
, RATE_LIMIT_INTERVAL_USEC
, PROBE_WAIT_USEC
);
242 r
= ipv4acd_set_next_wakeup(acd
, 0, PROBE_WAIT_USEC
);
249 case IPV4ACD_STATE_WAITING_PROBE
:
250 case IPV4ACD_STATE_PROBING
:
252 r
= arp_send_probe(acd
->fd
, acd
->ifindex
, acd
->address
, &acd
->mac_addr
);
254 log_ipv4acd_errno(acd
, r
, "Failed to send ARP probe: %m");
257 _cleanup_free_
char *address
= NULL
;
258 union in_addr_union addr
= { .in
.s_addr
= acd
->address
};
260 (void) in_addr_to_string(AF_INET
, &addr
, &address
);
261 log_ipv4acd(acd
, "Probing %s", strna(address
));
264 if (acd
->n_iteration
< PROBE_NUM
- 2) {
265 ipv4acd_set_state(acd
, IPV4ACD_STATE_PROBING
, false);
267 r
= ipv4acd_set_next_wakeup(acd
, PROBE_MIN_USEC
, (PROBE_MAX_USEC
-PROBE_MIN_USEC
));
271 ipv4acd_set_state(acd
, IPV4ACD_STATE_WAITING_ANNOUNCE
, true);
273 r
= ipv4acd_set_next_wakeup(acd
, ANNOUNCE_WAIT_USEC
, 0);
280 case IPV4ACD_STATE_ANNOUNCING
:
281 if (acd
->n_iteration
>= ANNOUNCE_NUM
- 1) {
282 ipv4acd_set_state(acd
, IPV4ACD_STATE_RUNNING
, false);
287 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
288 /* Send announcement packet */
289 r
= arp_send_announcement(acd
->fd
, acd
->ifindex
, acd
->address
, &acd
->mac_addr
);
291 log_ipv4acd_errno(acd
, r
, "Failed to send ARP announcement: %m");
294 log_ipv4acd(acd
, "ANNOUNCE");
296 ipv4acd_set_state(acd
, IPV4ACD_STATE_ANNOUNCING
, false);
298 r
= ipv4acd_set_next_wakeup(acd
, ANNOUNCE_INTERVAL_USEC
, 0);
302 if (acd
->n_iteration
== 0) {
304 ipv4acd_client_notify(acd
, SD_IPV4ACD_EVENT_BIND
);
310 assert_not_reached("Invalid state.");
316 sd_ipv4acd_stop(acd
);
320 static void ipv4acd_on_conflict(sd_ipv4acd
*acd
) {
321 _cleanup_free_
char *address
= NULL
;
322 union in_addr_union addr
= { .in
.s_addr
= acd
->address
};
328 (void) in_addr_to_string(AF_INET
, &addr
, &address
);
329 log_ipv4acd(acd
, "Conflict on %s (%u)", strna(address
), acd
->n_conflict
);
332 ipv4acd_client_notify(acd
, SD_IPV4ACD_EVENT_CONFLICT
);
335 static int ipv4acd_on_packet(
341 sd_ipv4acd
*acd
= userdata
;
342 struct ether_arp packet
;
350 n
= recv(fd
, &packet
, sizeof(struct ether_arp
), 0);
352 if (IN_SET(errno
, EAGAIN
, EINTR
))
355 log_ipv4acd_errno(acd
, errno
, "Failed to read ARP packet: %m");
358 if ((size_t) n
!= sizeof(struct ether_arp
)) {
359 log_ipv4acd(acd
, "Ignoring too short ARP packet.");
363 switch (acd
->state
) {
365 case IPV4ACD_STATE_ANNOUNCING
:
366 case IPV4ACD_STATE_RUNNING
:
368 if (ipv4acd_arp_conflict(acd
, &packet
)) {
371 assert_se(sd_event_now(acd
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
374 if (ts
> acd
->defend_window
) {
375 acd
->defend_window
= ts
+ DEFEND_INTERVAL_USEC
;
376 r
= arp_send_announcement(acd
->fd
, acd
->ifindex
, acd
->address
, &acd
->mac_addr
);
378 log_ipv4acd_errno(acd
, r
, "Failed to send ARP announcement: %m");
381 log_ipv4acd(acd
, "DEFEND");
384 ipv4acd_on_conflict(acd
);
388 case IPV4ACD_STATE_WAITING_PROBE
:
389 case IPV4ACD_STATE_PROBING
:
390 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
391 /* BPF ensures this packet indicates a conflict */
392 ipv4acd_on_conflict(acd
);
396 assert_not_reached("Invalid state.");
402 sd_ipv4acd_stop(acd
);
406 int sd_ipv4acd_set_ifindex(sd_ipv4acd
*acd
, int ifindex
) {
407 assert_return(acd
, -EINVAL
);
408 assert_return(ifindex
> 0, -EINVAL
);
409 assert_return(acd
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
411 acd
->ifindex
= ifindex
;
416 int sd_ipv4acd_get_ifindex(sd_ipv4acd
*acd
) {
423 int sd_ipv4acd_set_ifname(sd_ipv4acd
*acd
, const char *ifname
) {
424 assert_return(acd
, -EINVAL
);
425 assert_return(ifname
, -EINVAL
);
427 if (!ifname_valid_full(ifname
, IFNAME_VALID_ALTERNATIVE
))
430 return free_and_strdup(&acd
->ifname
, ifname
);
433 const char *sd_ipv4acd_get_ifname(sd_ipv4acd
*acd
) {
437 return get_ifname(acd
->ifindex
, &acd
->ifname
);
440 int sd_ipv4acd_set_mac(sd_ipv4acd
*acd
, const struct ether_addr
*addr
) {
441 assert_return(acd
, -EINVAL
);
442 assert_return(addr
, -EINVAL
);
443 assert_return(acd
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
445 acd
->mac_addr
= *addr
;
450 int sd_ipv4acd_detach_event(sd_ipv4acd
*acd
) {
451 assert_return(acd
, -EINVAL
);
453 acd
->event
= sd_event_unref(acd
->event
);
458 int sd_ipv4acd_attach_event(sd_ipv4acd
*acd
, sd_event
*event
, int64_t priority
) {
461 assert_return(acd
, -EINVAL
);
462 assert_return(!acd
->event
, -EBUSY
);
465 acd
->event
= sd_event_ref(event
);
467 r
= sd_event_default(&acd
->event
);
472 acd
->event_priority
= priority
;
477 int sd_ipv4acd_set_callback(sd_ipv4acd
*acd
, sd_ipv4acd_callback_t cb
, void *userdata
) {
478 assert_return(acd
, -EINVAL
);
481 acd
->userdata
= userdata
;
486 int sd_ipv4acd_set_address(sd_ipv4acd
*acd
, const struct in_addr
*address
) {
487 assert_return(acd
, -EINVAL
);
488 assert_return(address
, -EINVAL
);
489 assert_return(acd
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
491 acd
->address
= address
->s_addr
;
496 int sd_ipv4acd_get_address(sd_ipv4acd
*acd
, struct in_addr
*address
) {
497 assert_return(acd
, -EINVAL
);
498 assert_return(address
, -EINVAL
);
500 address
->s_addr
= acd
->address
;
505 int sd_ipv4acd_is_running(sd_ipv4acd
*acd
) {
506 assert_return(acd
, false);
508 return acd
->state
!= IPV4ACD_STATE_INIT
;
511 int sd_ipv4acd_start(sd_ipv4acd
*acd
, bool reset_conflicts
) {
514 assert_return(acd
, -EINVAL
);
515 assert_return(acd
->event
, -EINVAL
);
516 assert_return(acd
->ifindex
> 0, -EINVAL
);
517 assert_return(acd
->address
!= 0, -EINVAL
);
518 assert_return(!ether_addr_is_null(&acd
->mac_addr
), -EINVAL
);
519 assert_return(acd
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
521 r
= arp_network_bind_raw_socket(acd
->ifindex
, acd
->address
, &acd
->mac_addr
);
525 CLOSE_AND_REPLACE(acd
->fd
, r
);
526 acd
->defend_window
= 0;
531 r
= sd_event_add_io(acd
->event
, &acd
->receive_message_event_source
, acd
->fd
, EPOLLIN
, ipv4acd_on_packet
, acd
);
535 r
= sd_event_source_set_priority(acd
->receive_message_event_source
, acd
->event_priority
);
539 (void) sd_event_source_set_description(acd
->receive_message_event_source
, "ipv4acd-receive-message");
541 r
= ipv4acd_set_next_wakeup(acd
, 0, 0);
545 ipv4acd_set_state(acd
, IPV4ACD_STATE_STARTED
, true);