]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-ipv4acd.c
Merge pull request #1654 from poettering/util-lib
[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 "arp-util.h"
30 #include "event-util.h"
31 #include "fd-util.h"
32 #include "in-addr-util.h"
33 #include "list.h"
34 #include "random-util.h"
35 #include "refcnt.h"
36 #include "siphash24.h"
37 #include "util.h"
38
39 /* Constants from the RFC */
40 #define PROBE_WAIT 1
41 #define PROBE_NUM 3
42 #define PROBE_MIN 1
43 #define PROBE_MAX 2
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
50
51 #define IPV4ACD_NETWORK 0xA9FE0000L
52 #define IPV4ACD_NETMASK 0xFFFF0000L
53
54 #define log_ipv4acd_full(ll, level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "ACD: " fmt, ##__VA_ARGS__)
55
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__)
61
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__)
67
68 typedef enum IPv4ACDState {
69 IPV4ACD_STATE_INIT,
70 IPV4ACD_STATE_WAITING_PROBE,
71 IPV4ACD_STATE_PROBING,
72 IPV4ACD_STATE_WAITING_ANNOUNCE,
73 IPV4ACD_STATE_ANNOUNCING,
74 IPV4ACD_STATE_RUNNING,
75 _IPV4ACD_STATE_MAX,
76 _IPV4ACD_STATE_INVALID = -1
77 } IPv4ACDState;
78
79 struct sd_ipv4acd {
80 RefCount n_ref;
81
82 IPv4ACDState state;
83 int index;
84 int fd;
85 int iteration;
86 int conflict;
87 sd_event_source *receive_message;
88 sd_event_source *timer;
89 usec_t defend_window;
90 be32_t address;
91 /* External */
92 struct ether_addr mac_addr;
93 sd_event *event;
94 int event_priority;
95 sd_ipv4acd_cb_t cb;
96 void* userdata;
97 };
98
99 sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *ll) {
100 if (ll)
101 assert_se(REFCNT_INC(ll->n_ref) >= 2);
102
103 return ll;
104 }
105
106 sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll) {
107 if (!ll || REFCNT_DEC(ll->n_ref) > 0)
108 return NULL;
109
110 ll->receive_message = sd_event_source_unref(ll->receive_message);
111 ll->fd = safe_close(ll->fd);
112
113 ll->timer = sd_event_source_unref(ll->timer);
114
115 sd_ipv4acd_detach_event(ll);
116
117 free(ll);
118
119 return NULL;
120 }
121
122 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4acd*, sd_ipv4acd_unref);
123 #define _cleanup_ipv4acd_unref_ _cleanup_(sd_ipv4acd_unrefp)
124
125 int sd_ipv4acd_new(sd_ipv4acd **ret) {
126 _cleanup_ipv4acd_unref_ sd_ipv4acd *ll = NULL;
127
128 assert_return(ret, -EINVAL);
129
130 ll = new0(sd_ipv4acd, 1);
131 if (!ll)
132 return -ENOMEM;
133
134 ll->n_ref = REFCNT_INIT;
135 ll->state = IPV4ACD_STATE_INIT;
136 ll->index = -1;
137 ll->fd = -1;
138
139 *ret = ll;
140 ll = NULL;
141
142 return 0;
143 }
144
145 static void ipv4acd_set_state(sd_ipv4acd *ll, IPv4ACDState st, bool reset_counter) {
146
147 assert(ll);
148 assert(st < _IPV4ACD_STATE_MAX);
149
150 if (st == ll->state && !reset_counter)
151 ll->iteration++;
152 else {
153 ll->state = st;
154 ll->iteration = 0;
155 }
156 }
157
158 static void ipv4acd_client_notify(sd_ipv4acd *ll, int event) {
159 assert(ll);
160
161 if (ll->cb)
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_event_source_unref_ 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(sd_event_source *s, int fd,
353 uint32_t revents, void *userdata) {
354 sd_ipv4acd *ll = userdata;
355 struct ether_arp packet;
356 int r;
357
358 assert(ll);
359 assert(fd >= 0);
360
361 r = read(fd, &packet, sizeof(struct ether_arp));
362 if (r < (int) sizeof(struct ether_arp))
363 goto out;
364
365 switch (ll->state) {
366 case IPV4ACD_STATE_ANNOUNCING:
367 case IPV4ACD_STATE_RUNNING:
368 if (ipv4acd_arp_conflict(ll, &packet)) {
369 usec_t ts;
370
371 assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &ts) >= 0);
372
373 /* Defend address */
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);
377 if (r < 0) {
378 log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m");
379 goto out;
380 } else
381 log_ipv4acd_debug(ll, "DEFEND");
382
383 } else
384 ipv4acd_on_conflict(ll);
385 }
386
387 break;
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);
393
394 break;
395 default:
396 assert_not_reached("Invalid state.");
397 }
398
399 out:
400 if (r < 0)
401 sd_ipv4acd_stop(ll);
402
403 return 1;
404 }
405
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);
410
411 ll->index = interface_index;
412
413 return 0;
414 }
415
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);
420
421 memcpy(&ll->mac_addr, addr, ETH_ALEN);
422
423 return 0;
424 }
425
426 int sd_ipv4acd_detach_event(sd_ipv4acd *ll) {
427 assert_return(ll, -EINVAL);
428
429 ll->event = sd_event_unref(ll->event);
430
431 return 0;
432 }
433
434 int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority) {
435 int r;
436
437 assert_return(ll, -EINVAL);
438 assert_return(!ll->event, -EBUSY);
439
440 if (event)
441 ll->event = sd_event_ref(event);
442 else {
443 r = sd_event_default(&ll->event);
444 if (r < 0)
445 return r;
446 }
447
448 ll->event_priority = priority;
449
450 return 0;
451 }
452
453 int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata) {
454 assert_return(ll, -EINVAL);
455
456 ll->cb = cb;
457 ll->userdata = userdata;
458
459 return 0;
460 }
461
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);
466
467 ll->address = address->s_addr;
468
469 return 0;
470 }
471
472 int sd_ipv4acd_is_running(sd_ipv4acd *ll) {
473 assert_return(ll, false);
474
475 return ll->state != IPV4ACD_STATE_INIT;
476 }
477
478 static bool ether_addr_is_nul(const struct ether_addr *addr) {
479 const struct ether_addr nul_addr = {};
480
481 assert(addr);
482
483 return memcmp(addr, &nul_addr, sizeof(struct ether_addr)) == 0;
484 }
485
486 #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
487
488 int sd_ipv4acd_start(sd_ipv4acd *ll) {
489 int r;
490
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);
497
498 ll->defend_window = 0;
499
500 r = arp_network_bind_raw_socket(ll->index, ll->address, &ll->mac_addr);
501 if (r < 0)
502 goto out;
503
504 ll->fd = safe_close(ll->fd);
505 ll->fd = r;
506
507 r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,
508 EPOLLIN, ipv4acd_on_packet, ll);
509 if (r < 0)
510 goto out;
511
512 r = sd_event_source_set_priority(ll->receive_message, ll->event_priority);
513 if (r < 0)
514 goto out;
515
516 r = sd_event_source_set_description(ll->receive_message, "ipv4acd-receive-message");
517 if (r < 0)
518 goto out;
519
520 r = ipv4acd_set_next_wakeup(ll, 0, 0);
521 if (r < 0)
522 goto out;
523 out:
524 if (r < 0) {
525 ipv4acd_stop(ll);
526 return r;
527 }
528
529 return 0;
530 }