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"
30 #include "event-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
;
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 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4acd
*, sd_ipv4acd_unref
);
123 #define _cleanup_ipv4acd_unref_ _cleanup_(sd_ipv4acd_unrefp)
125 int sd_ipv4acd_new(sd_ipv4acd
**ret
) {
126 _cleanup_ipv4acd_unref_ sd_ipv4acd
*ll
= NULL
;
128 assert_return(ret
, -EINVAL
);
130 ll
= new0(sd_ipv4acd
, 1);
134 ll
->n_ref
= REFCNT_INIT
;
135 ll
->state
= IPV4ACD_STATE_INIT
;
145 static void ipv4acd_set_state(sd_ipv4acd
*ll
, IPv4ACDState st
, bool reset_counter
) {
148 assert(st
< _IPV4ACD_STATE_MAX
);
150 if (st
== ll
->state
&& !reset_counter
)
158 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_event_source_unref_ 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
->index
, 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
->index
, 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(sd_event_source
*s
, int fd
,
353 uint32_t revents
, void *userdata
) {
354 sd_ipv4acd
*ll
= userdata
;
355 struct ether_arp packet
;
361 r
= read(fd
, &packet
, sizeof(struct ether_arp
));
362 if (r
< (int) sizeof(struct ether_arp
))
366 case IPV4ACD_STATE_ANNOUNCING
:
367 case IPV4ACD_STATE_RUNNING
:
368 if (ipv4acd_arp_conflict(ll
, &packet
)) {
371 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
374 if (ts
> ll
->defend_window
) {
375 ll
->defend_window
= ts
+ DEFEND_INTERVAL
* USEC_PER_SEC
;
376 r
= arp_send_announcement(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
378 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
381 log_ipv4acd_debug(ll
, "DEFEND");
384 ipv4acd_on_conflict(ll
);
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(ll
);
396 assert_not_reached("Invalid state.");
406 int sd_ipv4acd_set_index(sd_ipv4acd
*ll
, int interface_index
) {
407 assert_return(ll
, -EINVAL
);
408 assert_return(interface_index
> 0, -EINVAL
);
409 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
411 ll
->index
= interface_index
;
416 int sd_ipv4acd_set_mac(sd_ipv4acd
*ll
, const struct ether_addr
*addr
) {
417 assert_return(ll
, -EINVAL
);
418 assert_return(addr
, -EINVAL
);
419 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
421 memcpy(&ll
->mac_addr
, addr
, ETH_ALEN
);
426 int sd_ipv4acd_detach_event(sd_ipv4acd
*ll
) {
427 assert_return(ll
, -EINVAL
);
429 ll
->event
= sd_event_unref(ll
->event
);
434 int sd_ipv4acd_attach_event(sd_ipv4acd
*ll
, sd_event
*event
, int priority
) {
437 assert_return(ll
, -EINVAL
);
438 assert_return(!ll
->event
, -EBUSY
);
441 ll
->event
= sd_event_ref(event
);
443 r
= sd_event_default(&ll
->event
);
448 ll
->event_priority
= priority
;
453 int sd_ipv4acd_set_callback(sd_ipv4acd
*ll
, sd_ipv4acd_cb_t cb
, void *userdata
) {
454 assert_return(ll
, -EINVAL
);
457 ll
->userdata
= userdata
;
462 int sd_ipv4acd_set_address(sd_ipv4acd
*ll
, const struct in_addr
*address
){
463 assert_return(ll
, -EINVAL
);
464 assert_return(address
, -EINVAL
);
465 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
467 ll
->address
= address
->s_addr
;
472 int sd_ipv4acd_is_running(sd_ipv4acd
*ll
) {
473 assert_return(ll
, false);
475 return ll
->state
!= IPV4ACD_STATE_INIT
;
478 static bool ether_addr_is_nul(const struct ether_addr
*addr
) {
479 const struct ether_addr nul_addr
= {};
483 return memcmp(addr
, &nul_addr
, sizeof(struct ether_addr
)) == 0;
486 #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
488 int sd_ipv4acd_start(sd_ipv4acd
*ll
) {
491 assert_return(ll
, -EINVAL
);
492 assert_return(ll
->event
, -EINVAL
);
493 assert_return(ll
->index
> 0, -EINVAL
);
494 assert_return(ll
->address
!= 0, -EINVAL
);
495 assert_return(!ether_addr_is_nul(&ll
->mac_addr
), -EINVAL
);
496 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
498 ll
->defend_window
= 0;
500 r
= arp_network_bind_raw_socket(ll
->index
, ll
->address
, &ll
->mac_addr
);
504 ll
->fd
= safe_close(ll
->fd
);
507 r
= sd_event_add_io(ll
->event
, &ll
->receive_message
, ll
->fd
,
508 EPOLLIN
, ipv4acd_on_packet
, ll
);
512 r
= sd_event_source_set_priority(ll
->receive_message
, ll
->event_priority
);
516 r
= sd_event_source_set_description(ll
->receive_message
, "ipv4acd-receive-message");
520 r
= ipv4acd_set_next_wakeup(ll
, 0, 0);