2 This file is part of systemd.
4 Copyright (C) 2014 Axis Communications AB. All rights reserved.
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <arpa/inet.h>
27 #include "siphash24.h"
29 #include "random-util.h"
31 #include "ipv4ll-internal.h"
32 #include "sd-ipv4ll.h"
34 /* Constants from the RFC */
39 #define ANNOUNCE_WAIT 2
40 #define ANNOUNCE_NUM 2
41 #define ANNOUNCE_INTERVAL 2
42 #define MAX_CONFLICTS 10
43 #define RATE_LIMIT_INTERVAL 60
44 #define DEFEND_INTERVAL 10
46 #define IPV4LL_NETWORK 0xA9FE0000L
47 #define IPV4LL_NETMASK 0xFFFF0000L
49 typedef enum IPv4LLTrigger
{
51 IPV4LL_TRIGGER_PACKET
,
52 IPV4LL_TRIGGER_TIMEOUT
,
54 _IPV4LL_TRIGGER_INVALID
= -1
57 typedef enum IPv4LLState
{
59 IPV4LL_STATE_WAITING_PROBE
,
61 IPV4LL_STATE_WAITING_ANNOUNCE
,
62 IPV4LL_STATE_ANNOUNCING
,
66 _IPV4LL_STATE_INVALID
= -1
75 union sockaddr_union link
;
78 sd_event_source
*receive_message
;
79 sd_event_source
*timer
;
82 int next_wakeup_valid
;
84 struct random_data
*random_data
;
85 char *random_data_state
;
87 be32_t claimed_address
;
88 struct ether_addr mac_addr
;
95 static void ipv4ll_run_state_machine(sd_ipv4ll
*ll
, IPv4LLTrigger trigger
, void *trigger_data
);
97 static void ipv4ll_set_state(sd_ipv4ll
*ll
, IPv4LLState st
, int reset_counter
) {
100 assert(st
< _IPV4LL_STATE_MAX
);
102 if (st
== ll
->state
&& !reset_counter
) {
110 static sd_ipv4ll
*ipv4ll_client_notify(sd_ipv4ll
*ll
, int event
) {
114 ll
= sd_ipv4ll_ref(ll
);
115 ll
->cb(ll
, event
, ll
->userdata
);
116 ll
= sd_ipv4ll_unref(ll
);
122 static sd_ipv4ll
*ipv4ll_stop(sd_ipv4ll
*ll
, int event
) {
125 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
126 ll
->fd
= safe_close(ll
->fd
);
128 ll
->timer
= sd_event_source_unref(ll
->timer
);
130 log_ipv4ll(ll
, "STOPPED");
132 ll
= ipv4ll_client_notify(ll
, event
);
135 ll
->claimed_address
= 0;
136 ipv4ll_set_state (ll
, IPV4LL_STATE_INIT
, 1);
142 static int ipv4ll_pick_address(sd_ipv4ll
*ll
, be32_t
*address
) {
149 assert(ll
->random_data
);
152 r
= random_r(ll
->random_data
, &random
);
155 addr
= htonl((random
& 0x0000FFFF) | IPV4LL_NETWORK
);
156 } while (addr
== ll
->address
||
157 (ntohl(addr
) & IPV4LL_NETMASK
) != IPV4LL_NETWORK
||
158 (ntohl(addr
) & 0x0000FF00) == 0x0000 ||
159 (ntohl(addr
) & 0x0000FF00) == 0xFF00);
165 static int ipv4ll_timer(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
166 sd_ipv4ll
*ll
= (sd_ipv4ll
*)userdata
;
170 ll
->next_wakeup_valid
= 0;
171 ipv4ll_run_state_machine(ll
, IPV4LL_TRIGGER_TIMEOUT
, NULL
);
176 static void ipv4ll_set_next_wakeup(sd_ipv4ll
*ll
, int sec
, int random_sec
) {
177 usec_t next_timeout
= 0;
181 assert(random_sec
>= 0);
184 next_timeout
= sec
* USEC_PER_SEC
;
187 next_timeout
+= random_u32() % (random_sec
* USEC_PER_SEC
);
189 assert_se(sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &time_now
) >= 0);
191 ll
->next_wakeup
= time_now
+ next_timeout
;
192 ll
->next_wakeup_valid
= 1;
195 static bool ipv4ll_arp_conflict (sd_ipv4ll
*ll
, struct ether_arp
*arp
) {
199 if (memcmp(arp
->arp_spa
, &ll
->address
, sizeof(ll
->address
)) == 0 &&
200 memcmp(arp
->arp_sha
, &ll
->mac_addr
, ETH_ALEN
) != 0)
206 static bool ipv4ll_arp_probe_conflict (sd_ipv4ll
*ll
, struct ether_arp
*arp
) {
210 if (ipv4ll_arp_conflict(ll
, arp
))
213 if (memcmp(arp
->arp_tpa
, &ll
->address
, sizeof(ll
->address
)) == 0 &&
214 memcmp(arp
->arp_sha
, &ll
->mac_addr
, ETH_ALEN
))
220 static void ipv4ll_run_state_machine(sd_ipv4ll
*ll
, IPv4LLTrigger trigger
, void *trigger_data
) {
221 struct ether_arp out_packet
;
222 int out_packet_ready
= 0;
226 assert(trigger
< _IPV4LL_TRIGGER_MAX
);
228 if (ll
->state
== IPV4LL_STATE_INIT
) {
230 log_ipv4ll(ll
, "PROBE");
231 ipv4ll_set_state(ll
, IPV4LL_STATE_WAITING_PROBE
, 1);
232 ipv4ll_set_next_wakeup(ll
, 0, PROBE_WAIT
);
234 } else if ((ll
->state
== IPV4LL_STATE_WAITING_PROBE
&& trigger
== IPV4LL_TRIGGER_TIMEOUT
) ||
235 (ll
->state
== IPV4LL_STATE_PROBING
&& trigger
== IPV4LL_TRIGGER_TIMEOUT
&& ll
->iteration
< PROBE_NUM
-2)) {
238 arp_packet_probe(&out_packet
, ll
->address
, &ll
->mac_addr
);
239 out_packet_ready
= 1;
240 ipv4ll_set_state(ll
, IPV4LL_STATE_PROBING
, 0);
242 ipv4ll_set_next_wakeup(ll
, PROBE_MIN
, (PROBE_MAX
-PROBE_MIN
));
244 } else if (ll
->state
== IPV4LL_STATE_PROBING
&& trigger
== IPV4LL_TRIGGER_TIMEOUT
&& ll
->iteration
>= PROBE_NUM
-2) {
246 /* Send the last probe */
247 arp_packet_probe(&out_packet
, ll
->address
, &ll
->mac_addr
);
248 out_packet_ready
= 1;
249 ipv4ll_set_state(ll
, IPV4LL_STATE_WAITING_ANNOUNCE
, 1);
251 ipv4ll_set_next_wakeup(ll
, ANNOUNCE_WAIT
, 0);
253 } else if ((ll
->state
== IPV4LL_STATE_WAITING_ANNOUNCE
&& trigger
== IPV4LL_TRIGGER_TIMEOUT
) ||
254 (ll
->state
== IPV4LL_STATE_ANNOUNCING
&& trigger
== IPV4LL_TRIGGER_TIMEOUT
&& ll
->iteration
< ANNOUNCE_NUM
-1)) {
256 /* Send announcement packet */
257 arp_packet_announcement(&out_packet
, ll
->address
, &ll
->mac_addr
);
258 out_packet_ready
= 1;
259 ipv4ll_set_state(ll
, IPV4LL_STATE_ANNOUNCING
, 0);
261 ipv4ll_set_next_wakeup(ll
, ANNOUNCE_INTERVAL
, 0);
263 if (ll
->iteration
== 0) {
264 log_ipv4ll(ll
, "ANNOUNCE");
265 ll
->claimed_address
= ll
->address
;
266 ll
= ipv4ll_client_notify(ll
, IPV4LL_EVENT_BIND
);
267 if (!ll
|| ll
->state
== IPV4LL_STATE_STOPPED
)
273 } else if ((ll
->state
== IPV4LL_STATE_ANNOUNCING
&& trigger
== IPV4LL_TRIGGER_TIMEOUT
&&
274 ll
->iteration
>= ANNOUNCE_NUM
-1)) {
276 ipv4ll_set_state(ll
, IPV4LL_STATE_RUNNING
, 0);
277 ll
->next_wakeup_valid
= 0;
279 } else if (trigger
== IPV4LL_TRIGGER_PACKET
) {
283 struct ether_arp
* in_packet
= (struct ether_arp
*)trigger_data
;
287 if (IN_SET(ll
->state
, IPV4LL_STATE_ANNOUNCING
, IPV4LL_STATE_RUNNING
)) {
289 if (ipv4ll_arp_conflict(ll
, in_packet
)) {
291 r
= sd_event_now(ll
->event
, clock_boottime_or_monotonic(), &time_now
);
296 if (time_now
> ll
->defend_window
) {
297 ll
->defend_window
= time_now
+ DEFEND_INTERVAL
* USEC_PER_SEC
;
298 arp_packet_announcement(&out_packet
, ll
->address
, &ll
->mac_addr
);
299 out_packet_ready
= 1;
304 } else if (IN_SET(ll
->state
, IPV4LL_STATE_WAITING_PROBE
,
305 IPV4LL_STATE_PROBING
,
306 IPV4LL_STATE_WAITING_ANNOUNCE
)) {
308 conflicted
= ipv4ll_arp_probe_conflict(ll
, in_packet
);
312 log_ipv4ll(ll
, "CONFLICT");
313 ll
= ipv4ll_client_notify(ll
, IPV4LL_EVENT_CONFLICT
);
314 if (!ll
|| ll
->state
== IPV4LL_STATE_STOPPED
)
317 ll
->claimed_address
= 0;
319 /* Pick a new address */
320 r
= ipv4ll_pick_address(ll
, &ll
->address
);
324 ll
->defend_window
= 0;
325 ipv4ll_set_state(ll
, IPV4LL_STATE_WAITING_PROBE
, 1);
327 if (ll
->conflict
>= MAX_CONFLICTS
) {
328 log_ipv4ll(ll
, "MAX_CONFLICTS");
329 ipv4ll_set_next_wakeup(ll
, RATE_LIMIT_INTERVAL
, PROBE_WAIT
);
331 ipv4ll_set_next_wakeup(ll
, 0, PROBE_WAIT
);
336 if (out_packet_ready
) {
337 r
= arp_network_send_raw_socket(ll
->fd
, &ll
->link
, &out_packet
);
339 log_ipv4ll(ll
, "failed to send arp packet out");
344 if (ll
->next_wakeup_valid
) {
345 ll
->timer
= sd_event_source_unref(ll
->timer
);
346 r
= sd_event_add_time(ll
->event
, &ll
->timer
, clock_boottime_or_monotonic(),
347 ll
->next_wakeup
, 0, ipv4ll_timer
, ll
);
351 r
= sd_event_source_set_priority(ll
->timer
, ll
->event_priority
);
355 r
= sd_event_source_set_description(ll
->timer
, "ipv4ll-timer");
365 static int ipv4ll_receive_message(sd_event_source
*s
, int fd
,
366 uint32_t revents
, void *userdata
) {
368 struct ether_arp arp
;
369 sd_ipv4ll
*ll
= (sd_ipv4ll
*)userdata
;
373 r
= read(fd
, &arp
, sizeof(struct ether_arp
));
374 if (r
< (int) sizeof(struct ether_arp
))
377 r
= arp_packet_verify_headers(&arp
);
381 ipv4ll_run_state_machine(ll
, IPV4LL_TRIGGER_PACKET
, &arp
);
386 int sd_ipv4ll_set_index(sd_ipv4ll
*ll
, int interface_index
) {
387 assert_return(ll
, -EINVAL
);
388 assert_return(interface_index
> 0, -EINVAL
);
389 assert_return(IN_SET(ll
->state
, IPV4LL_STATE_INIT
,
390 IPV4LL_STATE_STOPPED
), -EBUSY
);
392 ll
->index
= interface_index
;
397 int sd_ipv4ll_set_mac(sd_ipv4ll
*ll
, const struct ether_addr
*addr
) {
398 bool need_restart
= false;
400 assert_return(ll
, -EINVAL
);
401 assert_return(addr
, -EINVAL
);
403 if (memcmp(&ll
->mac_addr
, addr
, ETH_ALEN
) == 0)
406 if (!IN_SET(ll
->state
, IPV4LL_STATE_INIT
, IPV4LL_STATE_STOPPED
)) {
407 log_ipv4ll(ll
, "Changing MAC address on running IPv4LL "
408 "client, restarting");
409 ll
= ipv4ll_stop(ll
, IPV4LL_EVENT_STOP
);
416 memcpy(&ll
->mac_addr
, addr
, ETH_ALEN
);
424 int sd_ipv4ll_detach_event(sd_ipv4ll
*ll
) {
425 assert_return(ll
, -EINVAL
);
427 ll
->event
= sd_event_unref(ll
->event
);
432 int sd_ipv4ll_attach_event(sd_ipv4ll
*ll
, sd_event
*event
, int priority
) {
435 assert_return(ll
, -EINVAL
);
436 assert_return(!ll
->event
, -EBUSY
);
439 ll
->event
= sd_event_ref(event
);
441 r
= sd_event_default(&ll
->event
);
443 ipv4ll_stop(ll
, IPV4LL_EVENT_STOP
);
448 ll
->event_priority
= priority
;
453 int sd_ipv4ll_set_callback(sd_ipv4ll
*ll
, sd_ipv4ll_cb_t cb
, void *userdata
) {
454 assert_return(ll
, -EINVAL
);
457 ll
->userdata
= userdata
;
462 int sd_ipv4ll_get_address(sd_ipv4ll
*ll
, struct in_addr
*address
){
463 assert_return(ll
, -EINVAL
);
464 assert_return(address
, -EINVAL
);
466 if (ll
->claimed_address
== 0)
469 address
->s_addr
= ll
->claimed_address
;
473 int sd_ipv4ll_set_address_seed (sd_ipv4ll
*ll
, uint8_t seed
[8]) {
474 unsigned int entropy
;
477 assert_return(ll
, -EINVAL
);
478 assert_return(seed
, -EINVAL
);
482 free(ll
->random_data
);
483 free(ll
->random_data_state
);
485 ll
->random_data
= new0(struct random_data
, 1);
486 ll
->random_data_state
= new0(char, 128);
488 if (!ll
->random_data
|| !ll
->random_data_state
) {
493 r
= initstate_r((unsigned int)entropy
, ll
->random_data_state
, 128, ll
->random_data
);
499 free(ll
->random_data
);
500 free(ll
->random_data_state
);
501 ll
->random_data
= NULL
;
502 ll
->random_data_state
= NULL
;
507 bool sd_ipv4ll_is_running(sd_ipv4ll
*ll
) {
508 assert_return(ll
, false);
510 return !IN_SET(ll
->state
, IPV4LL_STATE_INIT
, IPV4LL_STATE_STOPPED
);
513 #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
515 int sd_ipv4ll_start (sd_ipv4ll
*ll
) {
518 assert_return(ll
, -EINVAL
);
519 assert_return(ll
->event
, -EINVAL
);
520 assert_return(ll
->index
> 0, -EINVAL
);
521 assert_return(IN_SET(ll
->state
, IPV4LL_STATE_INIT
,
522 IPV4LL_STATE_STOPPED
), -EBUSY
);
524 ll
->state
= IPV4LL_STATE_INIT
;
526 r
= arp_network_bind_raw_socket(ll
->index
, &ll
->link
);
533 ll
->defend_window
= 0;
534 ll
->claimed_address
= 0;
536 if (!ll
->random_data
) {
539 /* Fallback to mac */
540 siphash24(seed
, &ll
->mac_addr
.ether_addr_octet
,
541 ETH_ALEN
, HASH_KEY
.bytes
);
543 r
= sd_ipv4ll_set_address_seed(ll
, seed
);
548 if (ll
->address
== 0) {
549 r
= ipv4ll_pick_address(ll
, &ll
->address
);
554 ipv4ll_set_state (ll
, IPV4LL_STATE_INIT
, 1);
556 r
= sd_event_add_io(ll
->event
, &ll
->receive_message
, ll
->fd
,
557 EPOLLIN
, ipv4ll_receive_message
, ll
);
561 r
= sd_event_source_set_priority(ll
->receive_message
, ll
->event_priority
);
565 r
= sd_event_source_set_description(ll
->receive_message
, "ipv4ll-receive-message");
569 r
= sd_event_add_time(ll
->event
,
571 clock_boottime_or_monotonic(),
572 now(clock_boottime_or_monotonic()), 0,
578 r
= sd_event_source_set_priority(ll
->timer
, ll
->event_priority
);
582 r
= sd_event_source_set_description(ll
->timer
, "ipv4ll-timer");
585 ipv4ll_stop(ll
, IPV4LL_EVENT_STOP
);
590 int sd_ipv4ll_stop(sd_ipv4ll
*ll
) {
591 ipv4ll_stop(ll
, IPV4LL_EVENT_STOP
);
593 ipv4ll_set_state(ll
, IPV4LL_STATE_STOPPED
, 1);
598 sd_ipv4ll
*sd_ipv4ll_ref(sd_ipv4ll
*ll
) {
603 assert(ll
->n_ref
>= 1);
609 sd_ipv4ll
*sd_ipv4ll_unref(sd_ipv4ll
*ll
) {
614 assert(ll
->n_ref
>= 1);
620 ll
->receive_message
= sd_event_source_unref(ll
->receive_message
);
621 ll
->fd
= safe_close(ll
->fd
);
623 ll
->timer
= sd_event_source_unref(ll
->timer
);
625 sd_ipv4ll_detach_event(ll
);
627 free(ll
->random_data
);
628 free(ll
->random_data_state
);
634 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll
*, sd_ipv4ll_unref
);
635 #define _cleanup_ipv4ll_free_ _cleanup_(sd_ipv4ll_unrefp)
637 int sd_ipv4ll_new(sd_ipv4ll
**ret
) {
638 _cleanup_ipv4ll_free_ sd_ipv4ll
*ll
= NULL
;
640 assert_return(ret
, -EINVAL
);
642 ll
= new0(sd_ipv4ll
, 1);
647 ll
->state
= IPV4LL_STATE_INIT
;