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 "event-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
;
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 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4acd
*, sd_ipv4acd_unref
);
124 #define _cleanup_ipv4acd_unref_ _cleanup_(sd_ipv4acd_unrefp)
126 int sd_ipv4acd_new(sd_ipv4acd
**ret
) {
127 _cleanup_ipv4acd_unref_ sd_ipv4acd
*ll
= NULL
;
129 assert_return(ret
, -EINVAL
);
131 ll
= new0(sd_ipv4acd
, 1);
135 ll
->n_ref
= REFCNT_INIT
;
136 ll
->state
= IPV4ACD_STATE_INIT
;
146 static void ipv4acd_set_state(sd_ipv4acd
*ll
, IPv4ACDState st
, bool reset_counter
) {
149 assert(st
< _IPV4ACD_STATE_MAX
);
151 if (st
== ll
->state
&& !reset_counter
)
159 static void ipv4acd_client_notify(sd_ipv4acd
*ll
, int event
) {
163 ll
->cb(ll
, event
, ll
->userdata
);
166 static void ipv4acd_stop(sd_ipv4acd
*ll
) {
169 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
170 ll
->fd
= safe_close(ll
->fd
);
172 ll
->timer
= sd_event_source_unref(ll
->timer
);
174 log_ipv4acd_debug(ll
, "STOPPED");
176 ipv4acd_set_state (ll
, IPV4ACD_STATE_INIT
, true);
179 int sd_ipv4acd_stop(sd_ipv4acd
*ll
) {
180 assert_return(ll
, -EINVAL
);
184 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_STOP
);
189 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
);
191 static int ipv4acd_set_next_wakeup(sd_ipv4acd
*ll
, int sec
, int random_sec
) {
192 _cleanup_event_source_unref_ sd_event_source
*timer
= NULL
;
198 assert(random_sec
>= 0);
201 next_timeout
= sec
* USEC_PER_SEC
;
204 next_timeout
+= random_u32() % (random_sec
* USEC_PER_SEC
);
206 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &time_now
) >= 0);
208 r
= sd_event_add_time(ll
->event
, &timer
, clock_boottime_or_monotonic(),
209 time_now
+ next_timeout
, 0, ipv4acd_on_timeout
, ll
);
213 r
= sd_event_source_set_priority(timer
, ll
->event_priority
);
217 r
= sd_event_source_set_description(timer
, "ipv4acd-timer");
221 ll
->timer
= sd_event_source_unref(ll
->timer
);
228 static bool ipv4acd_arp_conflict(sd_ipv4acd
*ll
, struct ether_arp
*arp
) {
233 if (memcmp(arp
->arp_spa
, &ll
->address
, sizeof(ll
->address
)) == 0)
236 /* the TPA matched instead of the SPA, this is not a conflict */
240 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
241 sd_ipv4acd
*ll
= userdata
;
247 case IPV4ACD_STATE_INIT
:
249 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_PROBE
, true);
251 if (ll
->conflict
>= MAX_CONFLICTS
) {
252 log_ipv4acd_notice(ll
, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL
);
253 r
= ipv4acd_set_next_wakeup(ll
, RATE_LIMIT_INTERVAL
, PROBE_WAIT
);
259 r
= ipv4acd_set_next_wakeup(ll
, 0, PROBE_WAIT
);
265 case IPV4ACD_STATE_WAITING_PROBE
:
266 case IPV4ACD_STATE_PROBING
:
268 r
= arp_send_probe(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
270 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP probe: %m");
273 _cleanup_free_
char *address
= NULL
;
274 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
276 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
278 log_ipv4acd_debug(ll
, "Probing %s", address
);
281 if (ll
->iteration
< PROBE_NUM
- 2) {
282 ipv4acd_set_state(ll
, IPV4ACD_STATE_PROBING
, false);
284 r
= ipv4acd_set_next_wakeup(ll
, PROBE_MIN
, (PROBE_MAX
-PROBE_MIN
));
288 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_ANNOUNCE
, true);
290 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_WAIT
, 0);
297 case IPV4ACD_STATE_ANNOUNCING
:
298 if (ll
->iteration
>= ANNOUNCE_NUM
- 1) {
299 ipv4acd_set_state(ll
, IPV4ACD_STATE_RUNNING
, false);
303 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
304 /* Send announcement packet */
305 r
= arp_send_announcement(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
307 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
310 log_ipv4acd_debug(ll
, "ANNOUNCE");
312 ipv4acd_set_state(ll
, IPV4ACD_STATE_ANNOUNCING
, false);
314 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_INTERVAL
, 0);
318 if (ll
->iteration
== 0) {
320 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_BIND
);
325 assert_not_reached("Invalid state.");
335 static void ipv4acd_on_conflict(sd_ipv4acd
*ll
) {
336 _cleanup_free_
char *address
= NULL
;
337 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
344 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
346 log_ipv4acd_debug(ll
, "Conflict on %s (%u)", address
, ll
->conflict
);
350 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_CONFLICT
);
353 static int ipv4acd_on_packet(sd_event_source
*s
, int fd
,
354 uint32_t revents
, void *userdata
) {
355 sd_ipv4acd
*ll
= userdata
;
356 struct ether_arp packet
;
362 r
= read(fd
, &packet
, sizeof(struct ether_arp
));
363 if (r
< (int) sizeof(struct ether_arp
))
367 case IPV4ACD_STATE_ANNOUNCING
:
368 case IPV4ACD_STATE_RUNNING
:
369 if (ipv4acd_arp_conflict(ll
, &packet
)) {
372 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
375 if (ts
> ll
->defend_window
) {
376 ll
->defend_window
= ts
+ DEFEND_INTERVAL
* USEC_PER_SEC
;
377 r
= arp_send_announcement(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
379 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
382 log_ipv4acd_debug(ll
, "DEFEND");
385 ipv4acd_on_conflict(ll
);
389 case IPV4ACD_STATE_WAITING_PROBE
:
390 case IPV4ACD_STATE_PROBING
:
391 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
392 /* BPF ensures this packet indicates a conflict */
393 ipv4acd_on_conflict(ll
);
397 assert_not_reached("Invalid state.");
407 int sd_ipv4acd_set_index(sd_ipv4acd
*ll
, int interface_index
) {
408 assert_return(ll
, -EINVAL
);
409 assert_return(interface_index
> 0, -EINVAL
);
410 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
412 ll
->index
= interface_index
;
417 int sd_ipv4acd_set_mac(sd_ipv4acd
*ll
, const struct ether_addr
*addr
) {
418 assert_return(ll
, -EINVAL
);
419 assert_return(addr
, -EINVAL
);
420 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
422 memcpy(&ll
->mac_addr
, addr
, ETH_ALEN
);
427 int sd_ipv4acd_detach_event(sd_ipv4acd
*ll
) {
428 assert_return(ll
, -EINVAL
);
430 ll
->event
= sd_event_unref(ll
->event
);
435 int sd_ipv4acd_attach_event(sd_ipv4acd
*ll
, sd_event
*event
, int priority
) {
438 assert_return(ll
, -EINVAL
);
439 assert_return(!ll
->event
, -EBUSY
);
442 ll
->event
= sd_event_ref(event
);
444 r
= sd_event_default(&ll
->event
);
449 ll
->event_priority
= priority
;
454 int sd_ipv4acd_set_callback(sd_ipv4acd
*ll
, sd_ipv4acd_cb_t cb
, void *userdata
) {
455 assert_return(ll
, -EINVAL
);
458 ll
->userdata
= userdata
;
463 int sd_ipv4acd_set_address(sd_ipv4acd
*ll
, const struct in_addr
*address
){
464 assert_return(ll
, -EINVAL
);
465 assert_return(address
, -EINVAL
);
466 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
468 ll
->address
= address
->s_addr
;
473 int sd_ipv4acd_is_running(sd_ipv4acd
*ll
) {
474 assert_return(ll
, false);
476 return ll
->state
!= IPV4ACD_STATE_INIT
;
479 static bool ether_addr_is_nul(const struct ether_addr
*addr
) {
480 const struct ether_addr nul_addr
= {};
484 return memcmp(addr
, &nul_addr
, sizeof(struct ether_addr
)) == 0;
487 #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
489 int sd_ipv4acd_start(sd_ipv4acd
*ll
) {
492 assert_return(ll
, -EINVAL
);
493 assert_return(ll
->event
, -EINVAL
);
494 assert_return(ll
->index
> 0, -EINVAL
);
495 assert_return(ll
->address
!= 0, -EINVAL
);
496 assert_return(!ether_addr_is_nul(&ll
->mac_addr
), -EINVAL
);
497 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
499 ll
->defend_window
= 0;
501 r
= arp_network_bind_raw_socket(ll
->index
, ll
->address
, &ll
->mac_addr
);
505 ll
->fd
= safe_close(ll
->fd
);
508 r
= sd_event_add_io(ll
->event
, &ll
->receive_message
, ll
->fd
,
509 EPOLLIN
, ipv4acd_on_packet
, ll
);
513 r
= sd_event_source_set_priority(ll
->receive_message
, ll
->event_priority
);
517 r
= sd_event_source_set_description(ll
->receive_message
, "ipv4acd-receive-message");
521 r
= ipv4acd_set_next_wakeup(ll
, 0, 0);