]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-ipv4acd.c
util-lib: split out allocation calls into alloc-util.[ch]
[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 "event-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_cb_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 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4acd*, sd_ipv4acd_unref);
124 #define _cleanup_ipv4acd_unref_ _cleanup_(sd_ipv4acd_unrefp)
125
126 int sd_ipv4acd_new(sd_ipv4acd **ret) {
127 _cleanup_ipv4acd_unref_ sd_ipv4acd *ll = NULL;
128
129 assert_return(ret, -EINVAL);
130
131 ll = new0(sd_ipv4acd, 1);
132 if (!ll)
133 return -ENOMEM;
134
135 ll->n_ref = REFCNT_INIT;
136 ll->state = IPV4ACD_STATE_INIT;
137 ll->index = -1;
138 ll->fd = -1;
139
140 *ret = ll;
141 ll = NULL;
142
143 return 0;
144 }
145
146 static void ipv4acd_set_state(sd_ipv4acd *ll, IPv4ACDState st, bool reset_counter) {
147
148 assert(ll);
149 assert(st < _IPV4ACD_STATE_MAX);
150
151 if (st == ll->state && !reset_counter)
152 ll->iteration++;
153 else {
154 ll->state = st;
155 ll->iteration = 0;
156 }
157 }
158
159 static void ipv4acd_client_notify(sd_ipv4acd *ll, int event) {
160 assert(ll);
161
162 if (ll->cb)
163 ll->cb(ll, event, ll->userdata);
164 }
165
166 static void ipv4acd_stop(sd_ipv4acd *ll) {
167 assert(ll);
168
169 ll->receive_message = sd_event_source_unref(ll->receive_message);
170 ll->fd = safe_close(ll->fd);
171
172 ll->timer = sd_event_source_unref(ll->timer);
173
174 log_ipv4acd_debug(ll, "STOPPED");
175
176 ipv4acd_set_state (ll, IPV4ACD_STATE_INIT, true);
177 }
178
179 int sd_ipv4acd_stop(sd_ipv4acd *ll) {
180 assert_return(ll, -EINVAL);
181
182 ipv4acd_stop(ll);
183
184 ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_STOP);
185
186 return 0;
187 }
188
189 static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata);
190
191 static int ipv4acd_set_next_wakeup(sd_ipv4acd *ll, int sec, int random_sec) {
192 _cleanup_event_source_unref_ sd_event_source *timer = NULL;
193 usec_t next_timeout;
194 usec_t time_now;
195 int r;
196
197 assert(sec >= 0);
198 assert(random_sec >= 0);
199 assert(ll);
200
201 next_timeout = sec * USEC_PER_SEC;
202
203 if (random_sec)
204 next_timeout += random_u32() % (random_sec * USEC_PER_SEC);
205
206 assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now) >= 0);
207
208 r = sd_event_add_time(ll->event, &timer, clock_boottime_or_monotonic(),
209 time_now + next_timeout, 0, ipv4acd_on_timeout, ll);
210 if (r < 0)
211 return r;
212
213 r = sd_event_source_set_priority(timer, ll->event_priority);
214 if (r < 0)
215 return r;
216
217 r = sd_event_source_set_description(timer, "ipv4acd-timer");
218 if (r < 0)
219 return r;
220
221 ll->timer = sd_event_source_unref(ll->timer);
222 ll->timer = timer;
223 timer = NULL;
224
225 return 0;
226 }
227
228 static bool ipv4acd_arp_conflict(sd_ipv4acd *ll, struct ether_arp *arp) {
229 assert(ll);
230 assert(arp);
231
232 /* see the BPF */
233 if (memcmp(arp->arp_spa, &ll->address, sizeof(ll->address)) == 0)
234 return true;
235
236 /* the TPA matched instead of the SPA, this is not a conflict */
237 return false;
238 }
239
240 static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
241 sd_ipv4acd *ll = userdata;
242 int r = 0;
243
244 assert(ll);
245
246 switch (ll->state) {
247 case IPV4ACD_STATE_INIT:
248
249 ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_PROBE, true);
250
251 if (ll->conflict >= MAX_CONFLICTS) {
252 log_ipv4acd_notice(ll, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL);
253 r = ipv4acd_set_next_wakeup(ll, RATE_LIMIT_INTERVAL, PROBE_WAIT);
254 if (r < 0)
255 goto out;
256
257 ll->conflict = 0;
258 } else {
259 r = ipv4acd_set_next_wakeup(ll, 0, PROBE_WAIT);
260 if (r < 0)
261 goto out;
262 }
263
264 break;
265 case IPV4ACD_STATE_WAITING_PROBE:
266 case IPV4ACD_STATE_PROBING:
267 /* Send a probe */
268 r = arp_send_probe(ll->fd, ll->index, ll->address, &ll->mac_addr);
269 if (r < 0) {
270 log_ipv4acd_error_errno(ll, r, "Failed to send ARP probe: %m");
271 goto out;
272 } else {
273 _cleanup_free_ char *address = NULL;
274 union in_addr_union addr = { .in.s_addr = ll->address };
275
276 r = in_addr_to_string(AF_INET, &addr, &address);
277 if (r >= 0)
278 log_ipv4acd_debug(ll, "Probing %s", address);
279 }
280
281 if (ll->iteration < PROBE_NUM - 2) {
282 ipv4acd_set_state(ll, IPV4ACD_STATE_PROBING, false);
283
284 r = ipv4acd_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN));
285 if (r < 0)
286 goto out;
287 } else {
288 ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_ANNOUNCE, true);
289
290 r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_WAIT, 0);
291 if (r < 0)
292 goto out;
293 }
294
295 break;
296
297 case IPV4ACD_STATE_ANNOUNCING:
298 if (ll->iteration >= ANNOUNCE_NUM - 1) {
299 ipv4acd_set_state(ll, IPV4ACD_STATE_RUNNING, false);
300
301 break;
302 }
303 case IPV4ACD_STATE_WAITING_ANNOUNCE:
304 /* Send announcement packet */
305 r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
306 if (r < 0) {
307 log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m");
308 goto out;
309 } else
310 log_ipv4acd_debug(ll, "ANNOUNCE");
311
312 ipv4acd_set_state(ll, IPV4ACD_STATE_ANNOUNCING, false);
313
314 r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0);
315 if (r < 0)
316 goto out;
317
318 if (ll->iteration == 0) {
319 ll->conflict = 0;
320 ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_BIND);
321 }
322
323 break;
324 default:
325 assert_not_reached("Invalid state.");
326 }
327
328 out:
329 if (r < 0)
330 sd_ipv4acd_stop(ll);
331
332 return 1;
333 }
334
335 static void ipv4acd_on_conflict(sd_ipv4acd *ll) {
336 _cleanup_free_ char *address = NULL;
337 union in_addr_union addr = { .in.s_addr = ll->address };
338 int r;
339
340 assert(ll);
341
342 ll->conflict++;
343
344 r = in_addr_to_string(AF_INET, &addr, &address);
345 if (r >= 0)
346 log_ipv4acd_debug(ll, "Conflict on %s (%u)", address, ll->conflict);
347
348 ipv4acd_stop(ll);
349
350 ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_CONFLICT);
351 }
352
353 static int ipv4acd_on_packet(sd_event_source *s, int fd,
354 uint32_t revents, void *userdata) {
355 sd_ipv4acd *ll = userdata;
356 struct ether_arp packet;
357 int r;
358
359 assert(ll);
360 assert(fd >= 0);
361
362 r = read(fd, &packet, sizeof(struct ether_arp));
363 if (r < (int) sizeof(struct ether_arp))
364 goto out;
365
366 switch (ll->state) {
367 case IPV4ACD_STATE_ANNOUNCING:
368 case IPV4ACD_STATE_RUNNING:
369 if (ipv4acd_arp_conflict(ll, &packet)) {
370 usec_t ts;
371
372 assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &ts) >= 0);
373
374 /* Defend address */
375 if (ts > ll->defend_window) {
376 ll->defend_window = ts + DEFEND_INTERVAL * USEC_PER_SEC;
377 r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
378 if (r < 0) {
379 log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m");
380 goto out;
381 } else
382 log_ipv4acd_debug(ll, "DEFEND");
383
384 } else
385 ipv4acd_on_conflict(ll);
386 }
387
388 break;
389 case IPV4ACD_STATE_WAITING_PROBE:
390 case IPV4ACD_STATE_PROBING:
391 case IPV4ACD_STATE_WAITING_ANNOUNCE:
392 /* BPF ensures this packet indicates a conflict */
393 ipv4acd_on_conflict(ll);
394
395 break;
396 default:
397 assert_not_reached("Invalid state.");
398 }
399
400 out:
401 if (r < 0)
402 sd_ipv4acd_stop(ll);
403
404 return 1;
405 }
406
407 int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index) {
408 assert_return(ll, -EINVAL);
409 assert_return(interface_index > 0, -EINVAL);
410 assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
411
412 ll->index = interface_index;
413
414 return 0;
415 }
416
417 int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr) {
418 assert_return(ll, -EINVAL);
419 assert_return(addr, -EINVAL);
420 assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
421
422 memcpy(&ll->mac_addr, addr, ETH_ALEN);
423
424 return 0;
425 }
426
427 int sd_ipv4acd_detach_event(sd_ipv4acd *ll) {
428 assert_return(ll, -EINVAL);
429
430 ll->event = sd_event_unref(ll->event);
431
432 return 0;
433 }
434
435 int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority) {
436 int r;
437
438 assert_return(ll, -EINVAL);
439 assert_return(!ll->event, -EBUSY);
440
441 if (event)
442 ll->event = sd_event_ref(event);
443 else {
444 r = sd_event_default(&ll->event);
445 if (r < 0)
446 return r;
447 }
448
449 ll->event_priority = priority;
450
451 return 0;
452 }
453
454 int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata) {
455 assert_return(ll, -EINVAL);
456
457 ll->cb = cb;
458 ll->userdata = userdata;
459
460 return 0;
461 }
462
463 int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address){
464 assert_return(ll, -EINVAL);
465 assert_return(address, -EINVAL);
466 assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
467
468 ll->address = address->s_addr;
469
470 return 0;
471 }
472
473 int sd_ipv4acd_is_running(sd_ipv4acd *ll) {
474 assert_return(ll, false);
475
476 return ll->state != IPV4ACD_STATE_INIT;
477 }
478
479 static bool ether_addr_is_nul(const struct ether_addr *addr) {
480 const struct ether_addr nul_addr = {};
481
482 assert(addr);
483
484 return memcmp(addr, &nul_addr, sizeof(struct ether_addr)) == 0;
485 }
486
487 #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
488
489 int sd_ipv4acd_start(sd_ipv4acd *ll) {
490 int r;
491
492 assert_return(ll, -EINVAL);
493 assert_return(ll->event, -EINVAL);
494 assert_return(ll->index > 0, -EINVAL);
495 assert_return(ll->address != 0, -EINVAL);
496 assert_return(!ether_addr_is_nul(&ll->mac_addr), -EINVAL);
497 assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
498
499 ll->defend_window = 0;
500
501 r = arp_network_bind_raw_socket(ll->index, ll->address, &ll->mac_addr);
502 if (r < 0)
503 goto out;
504
505 ll->fd = safe_close(ll->fd);
506 ll->fd = r;
507
508 r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,
509 EPOLLIN, ipv4acd_on_packet, ll);
510 if (r < 0)
511 goto out;
512
513 r = sd_event_source_set_priority(ll->receive_message, ll->event_priority);
514 if (r < 0)
515 goto out;
516
517 r = sd_event_source_set_description(ll->receive_message, "ipv4acd-receive-message");
518 if (r < 0)
519 goto out;
520
521 r = ipv4acd_set_next_wakeup(ll, 0, 0);
522 if (r < 0)
523 goto out;
524 out:
525 if (r < 0) {
526 ipv4acd_stop(ll);
527 return r;
528 }
529
530 return 0;
531 }