]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-ipv4acd.c
Merge pull request #3247 from fbuihuu/ask-passowrd-on-all-consoles
[thirdparty/systemd.git] / src / libsystemd-network / sd-ipv4acd.c
1 /***
2 This file is part of systemd.
3
4 Copyright (C) 2014 Axis Communications AB. All rights reserved.
5 Copyright (C) 2015 Tom Gundersen
6
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.
11
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.
16
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/>.
19 ***/
20
21 #include <arpa/inet.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "sd-ipv4acd.h"
28
29 #include "alloc-util.h"
30 #include "arp-util.h"
31 #include "ether-addr-util.h"
32 #include "fd-util.h"
33 #include "in-addr-util.h"
34 #include "list.h"
35 #include "random-util.h"
36 #include "refcnt.h"
37 #include "siphash24.h"
38 #include "util.h"
39
40 /* Constants from the RFC */
41 #define PROBE_WAIT 1
42 #define PROBE_NUM 3
43 #define PROBE_MIN 1
44 #define PROBE_MAX 2
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
51
52 #define IPV4ACD_NETWORK 0xA9FE0000L
53 #define IPV4ACD_NETMASK 0xFFFF0000L
54
55 #define log_ipv4acd_full(ll, level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "ACD: " fmt, ##__VA_ARGS__)
56
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__)
62
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__)
68
69 typedef enum IPv4ACDState {
70 IPV4ACD_STATE_INIT,
71 IPV4ACD_STATE_WAITING_PROBE,
72 IPV4ACD_STATE_PROBING,
73 IPV4ACD_STATE_WAITING_ANNOUNCE,
74 IPV4ACD_STATE_ANNOUNCING,
75 IPV4ACD_STATE_RUNNING,
76 _IPV4ACD_STATE_MAX,
77 _IPV4ACD_STATE_INVALID = -1
78 } IPv4ACDState;
79
80 struct sd_ipv4acd {
81 RefCount n_ref;
82
83 IPv4ACDState state;
84 int index;
85 int fd;
86 int iteration;
87 int conflict;
88 sd_event_source *receive_message;
89 sd_event_source *timer;
90 usec_t defend_window;
91 be32_t address;
92 /* External */
93 struct ether_addr mac_addr;
94 sd_event *event;
95 int event_priority;
96 sd_ipv4acd_callback_t cb;
97 void* userdata;
98 };
99
100 sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *ll) {
101 if (ll)
102 assert_se(REFCNT_INC(ll->n_ref) >= 2);
103
104 return ll;
105 }
106
107 sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll) {
108 if (!ll || REFCNT_DEC(ll->n_ref) > 0)
109 return NULL;
110
111 ll->receive_message = sd_event_source_unref(ll->receive_message);
112 ll->fd = safe_close(ll->fd);
113
114 ll->timer = sd_event_source_unref(ll->timer);
115
116 sd_ipv4acd_detach_event(ll);
117
118 free(ll);
119
120 return NULL;
121 }
122
123 int sd_ipv4acd_new(sd_ipv4acd **ret) {
124 _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *ll = NULL;
125
126 assert_return(ret, -EINVAL);
127
128 ll = new0(sd_ipv4acd, 1);
129 if (!ll)
130 return -ENOMEM;
131
132 ll->n_ref = REFCNT_INIT;
133 ll->state = IPV4ACD_STATE_INIT;
134 ll->index = -1;
135 ll->fd = -1;
136
137 *ret = ll;
138 ll = NULL;
139
140 return 0;
141 }
142
143 static void ipv4acd_set_state(sd_ipv4acd *ll, IPv4ACDState st, bool reset_counter) {
144
145 assert(ll);
146 assert(st < _IPV4ACD_STATE_MAX);
147
148 if (st == ll->state && !reset_counter)
149 ll->iteration++;
150 else {
151 ll->state = st;
152 ll->iteration = 0;
153 }
154 }
155
156 static void ipv4acd_client_notify(sd_ipv4acd *ll, int event) {
157 assert(ll);
158
159 if (!ll->cb)
160 return;
161
162 ll->cb(ll, event, ll->userdata);
163 }
164
165 static void ipv4acd_stop(sd_ipv4acd *ll) {
166 assert(ll);
167
168 ll->receive_message = sd_event_source_unref(ll->receive_message);
169 ll->fd = safe_close(ll->fd);
170
171 ll->timer = sd_event_source_unref(ll->timer);
172
173 log_ipv4acd_debug(ll, "STOPPED");
174
175 ipv4acd_set_state (ll, IPV4ACD_STATE_INIT, true);
176 }
177
178 int sd_ipv4acd_stop(sd_ipv4acd *ll) {
179 assert_return(ll, -EINVAL);
180
181 ipv4acd_stop(ll);
182
183 ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_STOP);
184
185 return 0;
186 }
187
188 static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata);
189
190 static int ipv4acd_set_next_wakeup(sd_ipv4acd *ll, int sec, int random_sec) {
191 _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL;
192 usec_t next_timeout;
193 usec_t time_now;
194 int r;
195
196 assert(sec >= 0);
197 assert(random_sec >= 0);
198 assert(ll);
199
200 next_timeout = sec * USEC_PER_SEC;
201
202 if (random_sec)
203 next_timeout += random_u32() % (random_sec * USEC_PER_SEC);
204
205 assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now) >= 0);
206
207 r = sd_event_add_time(ll->event, &timer, clock_boottime_or_monotonic(),
208 time_now + next_timeout, 0, ipv4acd_on_timeout, ll);
209 if (r < 0)
210 return r;
211
212 r = sd_event_source_set_priority(timer, ll->event_priority);
213 if (r < 0)
214 return r;
215
216 r = sd_event_source_set_description(timer, "ipv4acd-timer");
217 if (r < 0)
218 return r;
219
220 ll->timer = sd_event_source_unref(ll->timer);
221 ll->timer = timer;
222 timer = NULL;
223
224 return 0;
225 }
226
227 static bool ipv4acd_arp_conflict(sd_ipv4acd *ll, struct ether_arp *arp) {
228 assert(ll);
229 assert(arp);
230
231 /* see the BPF */
232 if (memcmp(arp->arp_spa, &ll->address, sizeof(ll->address)) == 0)
233 return true;
234
235 /* the TPA matched instead of the SPA, this is not a conflict */
236 return false;
237 }
238
239 static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
240 sd_ipv4acd *ll = userdata;
241 int r = 0;
242
243 assert(ll);
244
245 switch (ll->state) {
246 case IPV4ACD_STATE_INIT:
247
248 ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_PROBE, true);
249
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);
253 if (r < 0)
254 goto out;
255
256 ll->conflict = 0;
257 } else {
258 r = ipv4acd_set_next_wakeup(ll, 0, PROBE_WAIT);
259 if (r < 0)
260 goto out;
261 }
262
263 break;
264 case IPV4ACD_STATE_WAITING_PROBE:
265 case IPV4ACD_STATE_PROBING:
266 /* Send a probe */
267 r = arp_send_probe(ll->fd, ll->index, ll->address, &ll->mac_addr);
268 if (r < 0) {
269 log_ipv4acd_error_errno(ll, r, "Failed to send ARP probe: %m");
270 goto out;
271 } else {
272 _cleanup_free_ char *address = NULL;
273 union in_addr_union addr = { .in.s_addr = ll->address };
274
275 r = in_addr_to_string(AF_INET, &addr, &address);
276 if (r >= 0)
277 log_ipv4acd_debug(ll, "Probing %s", address);
278 }
279
280 if (ll->iteration < PROBE_NUM - 2) {
281 ipv4acd_set_state(ll, IPV4ACD_STATE_PROBING, false);
282
283 r = ipv4acd_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN));
284 if (r < 0)
285 goto out;
286 } else {
287 ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_ANNOUNCE, true);
288
289 r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_WAIT, 0);
290 if (r < 0)
291 goto out;
292 }
293
294 break;
295
296 case IPV4ACD_STATE_ANNOUNCING:
297 if (ll->iteration >= ANNOUNCE_NUM - 1) {
298 ipv4acd_set_state(ll, IPV4ACD_STATE_RUNNING, false);
299
300 break;
301 }
302 case IPV4ACD_STATE_WAITING_ANNOUNCE:
303 /* Send announcement packet */
304 r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
305 if (r < 0) {
306 log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m");
307 goto out;
308 } else
309 log_ipv4acd_debug(ll, "ANNOUNCE");
310
311 ipv4acd_set_state(ll, IPV4ACD_STATE_ANNOUNCING, false);
312
313 r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0);
314 if (r < 0)
315 goto out;
316
317 if (ll->iteration == 0) {
318 ll->conflict = 0;
319 ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_BIND);
320 }
321
322 break;
323 default:
324 assert_not_reached("Invalid state.");
325 }
326
327 out:
328 if (r < 0)
329 sd_ipv4acd_stop(ll);
330
331 return 1;
332 }
333
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 };
337 int r;
338
339 assert(ll);
340
341 ll->conflict++;
342
343 r = in_addr_to_string(AF_INET, &addr, &address);
344 if (r >= 0)
345 log_ipv4acd_debug(ll, "Conflict on %s (%u)", address, ll->conflict);
346
347 ipv4acd_stop(ll);
348
349 ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_CONFLICT);
350 }
351
352 static int ipv4acd_on_packet(
353 sd_event_source *s,
354 int fd,
355 uint32_t revents,
356 void *userdata) {
357
358 sd_ipv4acd *ll = userdata;
359 struct ether_arp packet;
360 ssize_t n;
361 int r;
362
363 assert(s);
364 assert(ll);
365 assert(fd >= 0);
366
367 n = recv(fd, &packet, sizeof(struct ether_arp), 0);
368 if (n < 0) {
369 r = log_ipv4acd_debug_errno(ll, errno, "Failed to read ARP packet: %m");
370 goto out;
371 }
372 if ((size_t) n != sizeof(struct ether_arp)) {
373 log_ipv4acd_debug(ll, "Ignoring too short ARP packet.");
374 return 0;
375 }
376
377 switch (ll->state) {
378
379 case IPV4ACD_STATE_ANNOUNCING:
380 case IPV4ACD_STATE_RUNNING:
381
382 if (ipv4acd_arp_conflict(ll, &packet)) {
383 usec_t ts;
384
385 assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &ts) >= 0);
386
387 /* Defend address */
388 if (ts > ll->defend_window) {
389 ll->defend_window = ts + DEFEND_INTERVAL * USEC_PER_SEC;
390 r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
391 if (r < 0) {
392 log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m");
393 goto out;
394 } else
395 log_ipv4acd_debug(ll, "DEFEND");
396
397 } else
398 ipv4acd_on_conflict(ll);
399 }
400 break;
401
402 case IPV4ACD_STATE_WAITING_PROBE:
403 case IPV4ACD_STATE_PROBING:
404 case IPV4ACD_STATE_WAITING_ANNOUNCE:
405 /* BPF ensures this packet indicates a conflict */
406 ipv4acd_on_conflict(ll);
407 break;
408
409 default:
410 assert_not_reached("Invalid state.");
411 }
412
413 out:
414 if (r < 0)
415 sd_ipv4acd_stop(ll);
416
417 return 1;
418 }
419
420 int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index) {
421 assert_return(ll, -EINVAL);
422 assert_return(interface_index > 0, -EINVAL);
423 assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
424
425 ll->index = interface_index;
426
427 return 0;
428 }
429
430 int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr) {
431 assert_return(ll, -EINVAL);
432 assert_return(addr, -EINVAL);
433 assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
434
435 memcpy(&ll->mac_addr, addr, ETH_ALEN);
436
437 return 0;
438 }
439
440 int sd_ipv4acd_detach_event(sd_ipv4acd *ll) {
441 assert_return(ll, -EINVAL);
442
443 ll->event = sd_event_unref(ll->event);
444
445 return 0;
446 }
447
448 int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int64_t priority) {
449 int r;
450
451 assert_return(ll, -EINVAL);
452 assert_return(!ll->event, -EBUSY);
453
454 if (event)
455 ll->event = sd_event_ref(event);
456 else {
457 r = sd_event_default(&ll->event);
458 if (r < 0)
459 return r;
460 }
461
462 ll->event_priority = priority;
463
464 return 0;
465 }
466
467 int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_callback_t cb, void *userdata) {
468 assert_return(ll, -EINVAL);
469
470 ll->cb = cb;
471 ll->userdata = userdata;
472
473 return 0;
474 }
475
476 int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address) {
477 assert_return(ll, -EINVAL);
478 assert_return(address, -EINVAL);
479 assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
480
481 ll->address = address->s_addr;
482
483 return 0;
484 }
485
486 int sd_ipv4acd_is_running(sd_ipv4acd *ll) {
487 assert_return(ll, false);
488
489 return ll->state != IPV4ACD_STATE_INIT;
490 }
491
492 int sd_ipv4acd_start(sd_ipv4acd *ll) {
493 int r;
494
495 assert_return(ll, -EINVAL);
496 assert_return(ll->event, -EINVAL);
497 assert_return(ll->index > 0, -EINVAL);
498 assert_return(ll->address != 0, -EINVAL);
499 assert_return(!ether_addr_is_null(&ll->mac_addr), -EINVAL);
500 assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
501
502 ll->defend_window = 0;
503
504 r = arp_network_bind_raw_socket(ll->index, ll->address, &ll->mac_addr);
505 if (r < 0)
506 goto out;
507
508 ll->fd = safe_close(ll->fd);
509 ll->fd = r;
510
511 r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,
512 EPOLLIN, ipv4acd_on_packet, ll);
513 if (r < 0)
514 goto out;
515
516 r = sd_event_source_set_priority(ll->receive_message, ll->event_priority);
517 if (r < 0)
518 goto out;
519
520 r = sd_event_source_set_description(ll->receive_message, "ipv4acd-receive-message");
521 if (r < 0)
522 goto out;
523
524 r = ipv4acd_set_next_wakeup(ll, 0, 0);
525 if (r < 0)
526 goto out;
527 out:
528 if (r < 0) {
529 ipv4acd_stop(ll);
530 return r;
531 }
532
533 return 0;
534 }