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"
32 #include "in-addr-util.h"
34 #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 cb
;
99 sd_ipv4acd
*sd_ipv4acd_ref(sd_ipv4acd
*ll
) {
101 assert_se(REFCNT_INC(ll
->n_ref
) >= 2);
106 sd_ipv4acd
*sd_ipv4acd_unref(sd_ipv4acd
*ll
) {
107 if (!ll
|| REFCNT_DEC(ll
->n_ref
) > 0)
110 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
111 ll
->fd
= safe_close(ll
->fd
);
113 ll
->timer
= sd_event_source_unref(ll
->timer
);
115 sd_ipv4acd_detach_event(ll
);
122 int sd_ipv4acd_new(sd_ipv4acd
**ret
) {
123 _cleanup_(sd_ipv4acd_unrefp
) sd_ipv4acd
*ll
= NULL
;
125 assert_return(ret
, -EINVAL
);
127 ll
= new0(sd_ipv4acd
, 1);
131 ll
->n_ref
= REFCNT_INIT
;
132 ll
->state
= IPV4ACD_STATE_INIT
;
142 static void ipv4acd_set_state(sd_ipv4acd
*ll
, IPv4ACDState st
, bool reset_counter
) {
145 assert(st
< _IPV4ACD_STATE_MAX
);
147 if (st
== ll
->state
&& !reset_counter
)
155 static void ipv4acd_client_notify(sd_ipv4acd
*ll
, int event
) {
159 ll
->cb(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_debug(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_notice(ll
, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL
);
249 r
= ipv4acd_set_next_wakeup(ll
, RATE_LIMIT_INTERVAL
, PROBE_WAIT
);
255 r
= ipv4acd_set_next_wakeup(ll
, 0, PROBE_WAIT
);
261 case IPV4ACD_STATE_WAITING_PROBE
:
262 case IPV4ACD_STATE_PROBING
:
264 r
= arp_send_probe(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
266 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP probe: %m");
269 _cleanup_free_
char *address
= NULL
;
270 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
272 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
274 log_ipv4acd_debug(ll
, "Probing %s", address
);
277 if (ll
->iteration
< PROBE_NUM
- 2) {
278 ipv4acd_set_state(ll
, IPV4ACD_STATE_PROBING
, false);
280 r
= ipv4acd_set_next_wakeup(ll
, PROBE_MIN
, (PROBE_MAX
-PROBE_MIN
));
284 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_ANNOUNCE
, true);
286 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_WAIT
, 0);
293 case IPV4ACD_STATE_ANNOUNCING
:
294 if (ll
->iteration
>= ANNOUNCE_NUM
- 1) {
295 ipv4acd_set_state(ll
, IPV4ACD_STATE_RUNNING
, false);
299 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
300 /* Send announcement packet */
301 r
= arp_send_announcement(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
303 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
306 log_ipv4acd_debug(ll
, "ANNOUNCE");
308 ipv4acd_set_state(ll
, IPV4ACD_STATE_ANNOUNCING
, false);
310 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_INTERVAL
, 0);
314 if (ll
->iteration
== 0) {
316 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_BIND
);
321 assert_not_reached("Invalid state.");
331 static void ipv4acd_on_conflict(sd_ipv4acd
*ll
) {
332 _cleanup_free_
char *address
= NULL
;
333 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
340 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
342 log_ipv4acd_debug(ll
, "Conflict on %s (%u)", address
, ll
->conflict
);
346 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_CONFLICT
);
349 static int ipv4acd_on_packet(sd_event_source
*s
, int fd
,
350 uint32_t revents
, void *userdata
) {
351 sd_ipv4acd
*ll
= userdata
;
352 struct ether_arp packet
;
358 r
= read(fd
, &packet
, sizeof(struct ether_arp
));
359 if (r
< (int) sizeof(struct ether_arp
))
363 case IPV4ACD_STATE_ANNOUNCING
:
364 case IPV4ACD_STATE_RUNNING
:
365 if (ipv4acd_arp_conflict(ll
, &packet
)) {
368 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
371 if (ts
> ll
->defend_window
) {
372 ll
->defend_window
= ts
+ DEFEND_INTERVAL
* USEC_PER_SEC
;
373 r
= arp_send_announcement(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
375 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
378 log_ipv4acd_debug(ll
, "DEFEND");
381 ipv4acd_on_conflict(ll
);
385 case IPV4ACD_STATE_WAITING_PROBE
:
386 case IPV4ACD_STATE_PROBING
:
387 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
388 /* BPF ensures this packet indicates a conflict */
389 ipv4acd_on_conflict(ll
);
393 assert_not_reached("Invalid state.");
403 int sd_ipv4acd_set_index(sd_ipv4acd
*ll
, int interface_index
) {
404 assert_return(ll
, -EINVAL
);
405 assert_return(interface_index
> 0, -EINVAL
);
406 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
408 ll
->index
= interface_index
;
413 int sd_ipv4acd_set_mac(sd_ipv4acd
*ll
, const struct ether_addr
*addr
) {
414 assert_return(ll
, -EINVAL
);
415 assert_return(addr
, -EINVAL
);
416 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
418 memcpy(&ll
->mac_addr
, addr
, ETH_ALEN
);
423 int sd_ipv4acd_detach_event(sd_ipv4acd
*ll
) {
424 assert_return(ll
, -EINVAL
);
426 ll
->event
= sd_event_unref(ll
->event
);
431 int sd_ipv4acd_attach_event(sd_ipv4acd
*ll
, sd_event
*event
, int64_t priority
) {
434 assert_return(ll
, -EINVAL
);
435 assert_return(!ll
->event
, -EBUSY
);
438 ll
->event
= sd_event_ref(event
);
440 r
= sd_event_default(&ll
->event
);
445 ll
->event_priority
= priority
;
450 int sd_ipv4acd_set_callback(sd_ipv4acd
*ll
, sd_ipv4acd_callback_t cb
, void *userdata
) {
451 assert_return(ll
, -EINVAL
);
454 ll
->userdata
= userdata
;
459 int sd_ipv4acd_set_address(sd_ipv4acd
*ll
, const struct in_addr
*address
){
460 assert_return(ll
, -EINVAL
);
461 assert_return(address
, -EINVAL
);
462 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
464 ll
->address
= address
->s_addr
;
469 int sd_ipv4acd_is_running(sd_ipv4acd
*ll
) {
470 assert_return(ll
, false);
472 return ll
->state
!= IPV4ACD_STATE_INIT
;
475 static bool ether_addr_is_nul(const struct ether_addr
*addr
) {
476 const struct ether_addr nul_addr
= {};
480 return memcmp(addr
, &nul_addr
, sizeof(struct ether_addr
)) == 0;
483 #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
485 int sd_ipv4acd_start(sd_ipv4acd
*ll
) {
488 assert_return(ll
, -EINVAL
);
489 assert_return(ll
->event
, -EINVAL
);
490 assert_return(ll
->index
> 0, -EINVAL
);
491 assert_return(ll
->address
!= 0, -EINVAL
);
492 assert_return(!ether_addr_is_nul(&ll
->mac_addr
), -EINVAL
);
493 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
495 ll
->defend_window
= 0;
497 r
= arp_network_bind_raw_socket(ll
->index
, ll
->address
, &ll
->mac_addr
);
501 ll
->fd
= safe_close(ll
->fd
);
504 r
= sd_event_add_io(ll
->event
, &ll
->receive_message
, ll
->fd
,
505 EPOLLIN
, ipv4acd_on_packet
, ll
);
509 r
= sd_event_source_set_priority(ll
->receive_message
, ll
->event_priority
);
513 r
= sd_event_source_set_description(ll
->receive_message
, "ipv4acd-receive-message");
517 r
= ipv4acd_set_next_wakeup(ll
, 0, 0);