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"
31 #include "in-addr-util.h"
33 #include "random-util.h"
35 #include "siphash24.h"
38 /* Constants from the RFC */
43 #define ANNOUNCE_WAIT 2
44 #define ANNOUNCE_NUM 2
45 #define ANNOUNCE_INTERVAL 2
46 #define MAX_CONFLICTS 10
47 #define RATE_LIMIT_INTERVAL 60
48 #define DEFEND_INTERVAL 10
50 #define IPV4ACD_NETWORK 0xA9FE0000L
51 #define IPV4ACD_NETMASK 0xFFFF0000L
53 #define log_ipv4acd_full(ll, level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "ACD: " fmt, ##__VA_ARGS__)
55 #define log_ipv4acd_debug(ll, ...) log_ipv4acd_full(ll, LOG_DEBUG, 0, ##__VA_ARGS__)
56 #define log_ipv4acd_info(ll, ...) log_ipv4acd_full(ll, LOG_INFO, 0, ##__VA_ARGS__)
57 #define log_ipv4acd_notice(ll, ...) log_ipv4acd_full(ll, LOG_NOTICE, 0, ##__VA_ARGS__)
58 #define log_ipv4acd_warning(ll, ...) log_ipv4acd_full(ll, LOG_WARNING, 0, ##__VA_ARGS__)
59 #define log_ipv4acd_error(ll, ...) log_ipv4acd_full(ll, LOG_ERR, 0, ##__VA_ARGS__)
61 #define log_ipv4acd_debug_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_DEBUG, error, ##__VA_ARGS__)
62 #define log_ipv4acd_info_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_INFO, error, ##__VA_ARGS__)
63 #define log_ipv4acd_notice_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_NOTICE, error, ##__VA_ARGS__)
64 #define log_ipv4acd_warning_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_WARNING, error, ##__VA_ARGS__)
65 #define log_ipv4acd_error_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_ERR, error, ##__VA_ARGS__)
67 typedef enum IPv4ACDState
{
69 IPV4ACD_STATE_WAITING_PROBE
,
70 IPV4ACD_STATE_PROBING
,
71 IPV4ACD_STATE_WAITING_ANNOUNCE
,
72 IPV4ACD_STATE_ANNOUNCING
,
73 IPV4ACD_STATE_RUNNING
,
75 _IPV4ACD_STATE_INVALID
= -1
86 sd_event_source
*receive_message
;
87 sd_event_source
*timer
;
91 struct ether_addr mac_addr
;
98 sd_ipv4acd
*sd_ipv4acd_ref(sd_ipv4acd
*ll
) {
100 assert_se(REFCNT_INC(ll
->n_ref
) >= 2);
105 sd_ipv4acd
*sd_ipv4acd_unref(sd_ipv4acd
*ll
) {
106 if (!ll
|| REFCNT_DEC(ll
->n_ref
) > 0)
109 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
110 ll
->fd
= safe_close(ll
->fd
);
112 ll
->timer
= sd_event_source_unref(ll
->timer
);
114 sd_ipv4acd_detach_event(ll
);
121 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4acd
*, sd_ipv4acd_unref
);
122 #define _cleanup_ipv4acd_unref_ _cleanup_(sd_ipv4acd_unrefp)
124 int sd_ipv4acd_new(sd_ipv4acd
**ret
) {
125 _cleanup_ipv4acd_unref_ sd_ipv4acd
*ll
= NULL
;
127 assert_return(ret
, -EINVAL
);
129 ll
= new0(sd_ipv4acd
, 1);
133 ll
->n_ref
= REFCNT_INIT
;
134 ll
->state
= IPV4ACD_STATE_INIT
;
144 static void ipv4acd_set_state(sd_ipv4acd
*ll
, IPv4ACDState st
, bool reset_counter
) {
147 assert(st
< _IPV4ACD_STATE_MAX
);
149 if (st
== ll
->state
&& !reset_counter
)
157 static void ipv4acd_client_notify(sd_ipv4acd
*ll
, int event
) {
161 ll
->cb(ll
, event
, ll
->userdata
);
164 static void ipv4acd_stop(sd_ipv4acd
*ll
) {
167 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
168 ll
->fd
= safe_close(ll
->fd
);
170 ll
->timer
= sd_event_source_unref(ll
->timer
);
172 log_ipv4acd_debug(ll
, "STOPPED");
174 ipv4acd_set_state (ll
, IPV4ACD_STATE_INIT
, true);
177 int sd_ipv4acd_stop(sd_ipv4acd
*ll
) {
178 assert_return(ll
, -EINVAL
);
182 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_STOP
);
187 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
);
189 static int ipv4acd_set_next_wakeup(sd_ipv4acd
*ll
, int sec
, int random_sec
) {
190 _cleanup_event_source_unref_ sd_event_source
*timer
= NULL
;
196 assert(random_sec
>= 0);
199 next_timeout
= sec
* USEC_PER_SEC
;
202 next_timeout
+= random_u32() % (random_sec
* USEC_PER_SEC
);
204 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &time_now
) >= 0);
206 r
= sd_event_add_time(ll
->event
, &timer
, clock_boottime_or_monotonic(),
207 time_now
+ next_timeout
, 0, ipv4acd_on_timeout
, ll
);
211 r
= sd_event_source_set_priority(timer
, ll
->event_priority
);
215 r
= sd_event_source_set_description(timer
, "ipv4acd-timer");
219 ll
->timer
= sd_event_source_unref(ll
->timer
);
226 static bool ipv4acd_arp_conflict(sd_ipv4acd
*ll
, struct ether_arp
*arp
) {
231 if (memcmp(arp
->arp_spa
, &ll
->address
, sizeof(ll
->address
)) == 0)
234 /* the TPA matched instead of the SPA, this is not a conflict */
238 static int ipv4acd_on_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
239 sd_ipv4acd
*ll
= userdata
;
245 case IPV4ACD_STATE_INIT
:
247 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_PROBE
, true);
249 if (ll
->conflict
>= MAX_CONFLICTS
) {
250 log_ipv4acd_notice(ll
, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL
);
251 r
= ipv4acd_set_next_wakeup(ll
, RATE_LIMIT_INTERVAL
, PROBE_WAIT
);
257 r
= ipv4acd_set_next_wakeup(ll
, 0, PROBE_WAIT
);
263 case IPV4ACD_STATE_WAITING_PROBE
:
264 case IPV4ACD_STATE_PROBING
:
266 r
= arp_send_probe(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
268 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP probe: %m");
271 _cleanup_free_
char *address
= NULL
;
272 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
274 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
276 log_ipv4acd_debug(ll
, "Probing %s", address
);
279 if (ll
->iteration
< PROBE_NUM
- 2) {
280 ipv4acd_set_state(ll
, IPV4ACD_STATE_PROBING
, false);
282 r
= ipv4acd_set_next_wakeup(ll
, PROBE_MIN
, (PROBE_MAX
-PROBE_MIN
));
286 ipv4acd_set_state(ll
, IPV4ACD_STATE_WAITING_ANNOUNCE
, true);
288 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_WAIT
, 0);
295 case IPV4ACD_STATE_ANNOUNCING
:
296 if (ll
->iteration
>= ANNOUNCE_NUM
- 1) {
297 ipv4acd_set_state(ll
, IPV4ACD_STATE_RUNNING
, false);
301 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
302 /* Send announcement packet */
303 r
= arp_send_announcement(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
305 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
308 log_ipv4acd_debug(ll
, "ANNOUNCE");
310 ipv4acd_set_state(ll
, IPV4ACD_STATE_ANNOUNCING
, false);
312 r
= ipv4acd_set_next_wakeup(ll
, ANNOUNCE_INTERVAL
, 0);
316 if (ll
->iteration
== 0) {
318 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_BIND
);
323 assert_not_reached("Invalid state.");
333 static void ipv4acd_on_conflict(sd_ipv4acd
*ll
) {
334 _cleanup_free_
char *address
= NULL
;
335 union in_addr_union addr
= { .in
.s_addr
= ll
->address
};
342 r
= in_addr_to_string(AF_INET
, &addr
, &address
);
344 log_ipv4acd_debug(ll
, "Conflict on %s (%u)", address
, ll
->conflict
);
348 ipv4acd_client_notify(ll
, SD_IPV4ACD_EVENT_CONFLICT
);
351 static int ipv4acd_on_packet(sd_event_source
*s
, int fd
,
352 uint32_t revents
, void *userdata
) {
353 sd_ipv4acd
*ll
= userdata
;
354 struct ether_arp packet
;
360 r
= read(fd
, &packet
, sizeof(struct ether_arp
));
361 if (r
< (int) sizeof(struct ether_arp
))
365 case IPV4ACD_STATE_ANNOUNCING
:
366 case IPV4ACD_STATE_RUNNING
:
367 if (ipv4acd_arp_conflict(ll
, &packet
)) {
370 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
373 if (ts
> ll
->defend_window
) {
374 ll
->defend_window
= ts
+ DEFEND_INTERVAL
* USEC_PER_SEC
;
375 r
= arp_send_announcement(ll
->fd
, ll
->index
, ll
->address
, &ll
->mac_addr
);
377 log_ipv4acd_error_errno(ll
, r
, "Failed to send ARP announcement: %m");
380 log_ipv4acd_debug(ll
, "DEFEND");
383 ipv4acd_on_conflict(ll
);
387 case IPV4ACD_STATE_WAITING_PROBE
:
388 case IPV4ACD_STATE_PROBING
:
389 case IPV4ACD_STATE_WAITING_ANNOUNCE
:
390 /* BPF ensures this packet indicates a conflict */
391 ipv4acd_on_conflict(ll
);
395 assert_not_reached("Invalid state.");
405 int sd_ipv4acd_set_index(sd_ipv4acd
*ll
, int interface_index
) {
406 assert_return(ll
, -EINVAL
);
407 assert_return(interface_index
> 0, -EINVAL
);
408 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
410 ll
->index
= interface_index
;
415 int sd_ipv4acd_set_mac(sd_ipv4acd
*ll
, const struct ether_addr
*addr
) {
416 assert_return(ll
, -EINVAL
);
417 assert_return(addr
, -EINVAL
);
418 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
420 memcpy(&ll
->mac_addr
, addr
, ETH_ALEN
);
425 int sd_ipv4acd_detach_event(sd_ipv4acd
*ll
) {
426 assert_return(ll
, -EINVAL
);
428 ll
->event
= sd_event_unref(ll
->event
);
433 int sd_ipv4acd_attach_event(sd_ipv4acd
*ll
, sd_event
*event
, int priority
) {
436 assert_return(ll
, -EINVAL
);
437 assert_return(!ll
->event
, -EBUSY
);
440 ll
->event
= sd_event_ref(event
);
442 r
= sd_event_default(&ll
->event
);
447 ll
->event_priority
= priority
;
452 int sd_ipv4acd_set_callback(sd_ipv4acd
*ll
, sd_ipv4acd_cb_t cb
, void *userdata
) {
453 assert_return(ll
, -EINVAL
);
456 ll
->userdata
= userdata
;
461 int sd_ipv4acd_set_address(sd_ipv4acd
*ll
, const struct in_addr
*address
){
462 assert_return(ll
, -EINVAL
);
463 assert_return(address
, -EINVAL
);
464 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
466 ll
->address
= address
->s_addr
;
471 int sd_ipv4acd_is_running(sd_ipv4acd
*ll
) {
472 assert_return(ll
, false);
474 return ll
->state
!= IPV4ACD_STATE_INIT
;
477 static bool ether_addr_is_nul(const struct ether_addr
*addr
) {
478 const struct ether_addr nul_addr
= {};
482 return memcmp(addr
, &nul_addr
, sizeof(struct ether_addr
)) == 0;
485 #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
487 int sd_ipv4acd_start(sd_ipv4acd
*ll
) {
490 assert_return(ll
, -EINVAL
);
491 assert_return(ll
->event
, -EINVAL
);
492 assert_return(ll
->index
> 0, -EINVAL
);
493 assert_return(ll
->address
!= 0, -EINVAL
);
494 assert_return(!ether_addr_is_nul(&ll
->mac_addr
), -EINVAL
);
495 assert_return(ll
->state
== IPV4ACD_STATE_INIT
, -EBUSY
);
497 ll
->defend_window
= 0;
499 r
= arp_network_bind_raw_socket(ll
->index
, ll
->address
, &ll
->mac_addr
);
503 ll
->fd
= safe_close(ll
->fd
);
506 r
= sd_event_add_io(ll
->event
, &ll
->receive_message
, ll
->fd
,
507 EPOLLIN
, ipv4acd_on_packet
, ll
);
511 r
= sd_event_source_set_priority(ll
->receive_message
, ll
->event_priority
);
515 r
= sd_event_source_set_description(ll
->receive_message
, "ipv4acd-receive-message");
519 r
= ipv4acd_set_next_wakeup(ll
, 0, 0);