]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/network/networkd-route.c
Move missing_xyz.h for glibc headers to src/basic/include/ (#37960)
[thirdparty/systemd.git] / src / network / networkd-route.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include <linux/ipv6_route.h>
4#include <net/if.h>
5#include <stdio.h>
6
7#include "sd-ndisc-protocol.h"
8#include "sd-netlink.h"
9
10#include "alloc-util.h"
11#include "conf-parser.h"
12#include "errno-util.h"
13#include "event-util.h"
14#include "netlink-util.h"
15#include "networkd-address.h"
16#include "networkd-ipv4ll.h"
17#include "networkd-link.h"
18#include "networkd-manager.h"
19#include "networkd-network.h"
20#include "networkd-nexthop.h"
21#include "networkd-queue.h"
22#include "networkd-route.h"
23#include "networkd-route-util.h"
24#include "ordered-set.h"
25#include "parse-util.h"
26#include "set.h"
27#include "siphash24.h"
28#include "string-util.h"
29#include "vrf.h"
30#include "wireguard.h"
31
32static Route* route_detach_impl(Route *route) {
33 assert(route);
34 assert(!!route->network + !!route->manager + !!route->wireguard <= 1);
35
36 if (route->network) {
37 assert(route->section);
38 hashmap_remove(route->network->routes_by_section, route->section);
39 route->network = NULL;
40 return route;
41 }
42
43 if (route->manager) {
44 route_detach_from_nexthop(route);
45 set_remove(route->manager->routes, route);
46 route->manager = NULL;
47 return route;
48 }
49
50 if (route->wireguard) {
51 set_remove(route->wireguard->routes, route);
52 route->wireguard = NULL;
53 return route;
54 }
55
56 return NULL;
57}
58
59void route_detach(Route *route) {
60 route_unref(route_detach_impl(route));
61}
62
63static Route* route_free(Route *route) {
64 if (!route)
65 return NULL;
66
67 route_detach_impl(route);
68
69 config_section_free(route->section);
70 route_nexthops_done(route);
71 route_metric_done(&route->metric);
72 sd_event_source_disable_unref(route->expire);
73
74 return mfree(route);
75}
76
77DEFINE_TRIVIAL_REF_UNREF_FUNC(Route, route, route_free);
78
79static void route_hash_func(const Route *route, struct siphash *state) {
80 assert(route);
81
82 siphash24_compress_typesafe(route->family, state);
83
84 switch (route->family) {
85 case AF_INET:
86 /* First, the table, destination prefix, priority, and tos (dscp), are used to find routes.
87 * See fib_table_insert(), fib_find_node(), and fib_find_alias() in net/ipv4/fib_trie.c of the kernel. */
88 siphash24_compress_typesafe(route->table, state);
89 in_addr_hash_func(&route->dst, route->family, state);
90 siphash24_compress_typesafe(route->dst_prefixlen, state);
91 siphash24_compress_typesafe(route->priority, state);
92 siphash24_compress_typesafe(route->tos, state);
93
94 /* Then, protocol, scope, type, flags, prefsrc, metrics (RTAX_* attributes), and nexthops (gateways)
95 * are used to find routes. See fib_find_info() in net/ipv4/fib_semantics.c of the kernel. */
96 siphash24_compress_typesafe(route->protocol, state);
97 siphash24_compress_typesafe(route->scope, state);
98 siphash24_compress_typesafe(route->type, state);
99 unsigned flags = route->flags & ~RTNH_COMPARE_MASK;
100 siphash24_compress_typesafe(flags, state);
101 in_addr_hash_func(&route->prefsrc, route->family, state);
102
103 /* nexthops (id, number of nexthops, nexthop) */
104 route_nexthops_hash_func(route, state);
105
106 /* metrics */
107 route_metric_hash_func(&route->metric, state);
108 break;
109
110 case AF_INET6:
111 /* First, table and destination prefix are used for classifying routes.
112 * See fib6_add() and fib6_add_1() in net/ipv6/ip6_fib.c of the kernel. */
113 siphash24_compress_typesafe(route->table, state);
114 in_addr_hash_func(&route->dst, route->family, state);
115 siphash24_compress_typesafe(route->dst_prefixlen, state);
116
117 /* Then, source prefix is used. See fib6_add(). */
118 in_addr_hash_func(&route->src, route->family, state);
119 siphash24_compress_typesafe(route->src_prefixlen, state);
120
121 /* See fib6_add_rt2node(). */
122 siphash24_compress_typesafe(route->priority, state);
123
124 /* See rt6_duplicate_nexthop() in include/net/ip6_route.h of the kernel.
125 * Here, we hash nexthop in a similar way as the one for IPv4. */
126 route_nexthops_hash_func(route, state);
127
128 /* Unlike IPv4 routes, metrics are not taken into account. */
129 break;
130
131 default:
132 assert_not_reached();
133 }
134}
135
136static int route_compare_func(const Route *a, const Route *b) {
137 int r;
138
139 r = CMP(a->family, b->family);
140 if (r != 0)
141 return r;
142
143 switch (a->family) {
144 case AF_INET:
145 r = CMP(a->table, b->table);
146 if (r != 0)
147 return r;
148
149 r = memcmp(&a->dst, &b->dst, FAMILY_ADDRESS_SIZE(a->family));
150 if (r != 0)
151 return r;
152
153 r = CMP(a->dst_prefixlen, b->dst_prefixlen);
154 if (r != 0)
155 return r;
156
157 r = CMP(a->priority, b->priority);
158 if (r != 0)
159 return r;
160
161 r = CMP(a->tos, b->tos);
162 if (r != 0)
163 return r;
164
165 r = CMP(a->protocol, b->protocol);
166 if (r != 0)
167 return r;
168
169 r = CMP(a->scope, b->scope);
170 if (r != 0)
171 return r;
172
173 r = CMP(a->type, b->type);
174 if (r != 0)
175 return r;
176
177 r = CMP(a->flags & ~RTNH_COMPARE_MASK, b->flags & ~RTNH_COMPARE_MASK);
178 if (r != 0)
179 return r;
180
181 r = memcmp(&a->prefsrc, &b->prefsrc, FAMILY_ADDRESS_SIZE(a->family));
182 if (r != 0)
183 return r;
184
185 r = route_nexthops_compare_func(a, b);
186 if (r != 0)
187 return r;
188
189 return route_metric_compare_func(&a->metric, &b->metric);
190
191 case AF_INET6:
192 r = CMP(a->table, b->table);
193 if (r != 0)
194 return r;
195
196 r = memcmp(&a->dst, &b->dst, FAMILY_ADDRESS_SIZE(a->family));
197 if (r != 0)
198 return r;
199
200 r = CMP(a->dst_prefixlen, b->dst_prefixlen);
201 if (r != 0)
202 return r;
203
204 r = memcmp(&a->src, &b->src, FAMILY_ADDRESS_SIZE(a->family));
205 if (r != 0)
206 return r;
207
208 r = CMP(a->src_prefixlen, b->src_prefixlen);
209 if (r != 0)
210 return r;
211
212 r = CMP(a->priority, b->priority);
213 if (r != 0)
214 return r;
215
216 return route_nexthops_compare_func(a, b);
217
218 default:
219 assert_not_reached();
220 }
221}
222
223DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
224 route_hash_ops,
225 Route,
226 route_hash_func,
227 route_compare_func,
228 route_detach);
229
230DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
231 route_hash_ops_unref,
232 Route,
233 route_hash_func,
234 route_compare_func,
235 route_unref);
236
237DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
238 route_section_hash_ops,
239 ConfigSection,
240 config_section_hash_func,
241 config_section_compare_func,
242 Route,
243 route_detach);
244
245int route_new(Route **ret) {
246 _cleanup_(route_unrefp) Route *route = NULL;
247
248 route = new(Route, 1);
249 if (!route)
250 return -ENOMEM;
251
252 *route = (Route) {
253 .n_ref = 1,
254 .family = AF_UNSPEC,
255 .scope = RT_SCOPE_UNIVERSE,
256 .protocol = RTPROT_UNSPEC,
257 .type = RTN_UNICAST,
258 .table = RT_TABLE_MAIN,
259 .lifetime_usec = USEC_INFINITY,
260 .gateway_onlink = -1,
261 };
262
263 *ret = TAKE_PTR(route);
264
265 return 0;
266}
267
268int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
269 _cleanup_(config_section_freep) ConfigSection *n = NULL;
270 _cleanup_(route_unrefp) Route *route = NULL;
271 int r;
272
273 assert(network);
274 assert(ret);
275 assert(filename);
276 assert(section_line > 0);
277
278 r = config_section_new(filename, section_line, &n);
279 if (r < 0)
280 return r;
281
282 route = hashmap_get(network->routes_by_section, n);
283 if (route) {
284 *ret = TAKE_PTR(route);
285 return 0;
286 }
287
288 if (hashmap_size(network->routes_by_section) >= routes_max())
289 return -E2BIG;
290
291 r = route_new(&route);
292 if (r < 0)
293 return r;
294
295 route->protocol = RTPROT_STATIC;
296 route->network = network;
297 route->section = TAKE_PTR(n);
298 route->source = NETWORK_CONFIG_SOURCE_STATIC;
299
300 r = hashmap_ensure_put(&network->routes_by_section, &route_section_hash_ops, route->section, route);
301 if (r < 0)
302 return r;
303
304 *ret = TAKE_PTR(route);
305 return 0;
306}
307
308static int route_attach(Manager *manager, Route *route) {
309 int r;
310
311 assert(manager);
312 assert(route);
313 assert(!route->network);
314 assert(!route->wireguard);
315
316 r = set_ensure_put(&manager->routes, &route_hash_ops, route);
317 if (r < 0)
318 return r;
319 if (r == 0)
320 return -EEXIST;
321
322 route->manager = manager;
323 return 0;
324}
325
326int route_get(Manager *manager, const Route *route, Route **ret) {
327 Route *existing;
328
329 assert(manager);
330 assert(route);
331
332 existing = set_get(manager->routes, route);
333 if (!existing)
334 return -ENOENT;
335
336 if (ret)
337 *ret = existing;
338
339 return 0;
340}
341
342static int route_get_link(Manager *manager, const Route *route, Link **ret) {
343 int r;
344
345 assert(manager);
346 assert(route);
347
348 if (route->nexthop_id != 0) {
349 NextHop *nh;
350
351 r = nexthop_get_by_id(manager, route->nexthop_id, &nh);
352 if (r < 0)
353 return r;
354
355 return link_get_by_index(manager, nh->ifindex, ret);
356 }
357
358 return route_nexthop_get_link(manager, &route->nexthop, ret);
359}
360
361bool route_is_bound_to_link(const Route *route, Link *link) {
362 assert(route);
363 assert(link);
364 assert(link->manager);
365
366 Link *route_link;
367 if (route_get_link(link->manager, route, &route_link) < 0)
368 return false;
369
370 return route_link->ifindex == link->ifindex;
371}
372
373int route_get_request(Manager *manager, const Route *route, Request **ret) {
374 Request *req;
375
376 assert(manager);
377 assert(route);
378
379 req = ordered_set_get(manager->request_queue,
380 &(const Request) {
381 .type = REQUEST_TYPE_ROUTE,
382 .userdata = (void*) route,
383 .hash_func = (hash_func_t) route_hash_func,
384 .compare_func = (compare_func_t) route_compare_func,
385 });
386 if (!req)
387 return -ENOENT;
388
389 if (ret)
390 *ret = req;
391 return 0;
392}
393
394int route_dup(const Route *src, const RouteNextHop *nh, Route **ret) {
395 _cleanup_(route_unrefp) Route *dest = NULL;
396 int r;
397
398 assert(src);
399 assert(ret);
400
401 dest = newdup(Route, src, 1);
402 if (!dest)
403 return -ENOMEM;
404
405 /* Unset number of reference and all pointers */
406 dest->n_ref = 1;
407 dest->manager = NULL;
408 dest->network = NULL;
409 dest->wireguard = NULL;
410 dest->section = NULL;
411 dest->nexthop = ROUTE_NEXTHOP_NULL;
412 dest->nexthops = NULL;
413 dest->metric = ROUTE_METRIC_NULL;
414 dest->expire = NULL;
415
416 r = route_nexthops_copy(src, nh, dest);
417 if (r < 0)
418 return r;
419
420 r = route_metric_copy(&src->metric, &dest->metric);
421 if (r < 0)
422 return r;
423
424 *ret = TAKE_PTR(dest);
425 return 0;
426}
427
428static int route_to_string(const Route *route, Manager *manager, char **ret) {
429 _cleanup_free_ char *nexthop = NULL, *prefsrc = NULL,
430 *table = NULL, *scope = NULL, *proto = NULL, *flags = NULL;
431 const char *dst, *src;
432
433 assert(route);
434 assert(manager);
435 assert(ret);
436
437 dst = in_addr_is_set(route->family, &route->dst) || route->dst_prefixlen > 0 ?
438 IN_ADDR_PREFIX_TO_STRING(route->family, &route->dst, route->dst_prefixlen) : NULL;
439 src = in_addr_is_set(route->family, &route->src) || route->src_prefixlen > 0 ?
440 IN_ADDR_PREFIX_TO_STRING(route->family, &route->src, route->src_prefixlen) : NULL;
441
442 (void) route_nexthops_to_string(route, &nexthop);
443
444 if (in_addr_is_set(route->family, &route->prefsrc))
445 (void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
446 (void) route_scope_to_string_alloc(route->scope, &scope);
447 (void) manager_get_route_table_to_string(manager, route->table, /* append_num = */ true, &table);
448 (void) route_protocol_full_to_string_alloc(route->protocol, &proto);
449 (void) route_flags_to_string_alloc(route->flags, &flags);
450
451 if (asprintf(ret,
452 "dst: %s, src: %s, %s, prefsrc: %s, "
453 "table: %s, priority: %"PRIu32", "
454 "proto: %s, scope: %s, "
455 "type: %s, flags: %s",
456 strna(dst), strna(src), strna(nexthop), strna(prefsrc),
457 strna(table), route->priority,
458 strna(proto), strna(scope),
459 strna(route_type_to_string(route->type)), strna(flags)) < 0)
460 return -ENOMEM;
461
462 return 0;
463}
464
465void log_route_debug(const Route *route, const char *str, Manager *manager) {
466 _cleanup_free_ char *state = NULL, *route_str = NULL;
467 Link *link = NULL;
468
469 assert(route);
470 assert(str);
471 assert(manager);
472
473 if (!DEBUG_LOGGING)
474 return;
475
476 (void) route_get_link(manager, route, &link);
477 (void) network_config_state_to_string_alloc(route->state, &state);
478 (void) route_to_string(route, manager, &route_str);
479
480 log_link_debug(link, "%s %s route (%s): %s",
481 str, strna(network_config_source_to_string(route->source)), strna(state), strna(route_str));
482}
483
484static void route_forget(Manager *manager, Route *route, const char *msg) {
485 assert(manager);
486 assert(route);
487 assert(msg);
488
489 Request *req;
490 if (route_get_request(manager, route, &req) >= 0)
491 route_enter_removed(req->userdata);
492
493 if (!route->manager && route_get(manager, route, &route) < 0)
494 return;
495
496 route_enter_removed(route);
497 log_route_debug(route, msg, manager);
498 route_detach(route);
499}
500
501static int route_set_netlink_message(const Route *route, sd_netlink_message *m) {
502 int r;
503
504 assert(route);
505 assert(m);
506
507 /* rtmsg header (and relevant attributes) */
508 if (route->dst_prefixlen > 0) {
509 r = netlink_message_append_in_addr_union(m, RTA_DST, route->family, &route->dst);
510 if (r < 0)
511 return r;
512
513 r = sd_rtnl_message_route_set_dst_prefixlen(m, route->dst_prefixlen);
514 if (r < 0)
515 return r;
516 }
517
518 if (route->src_prefixlen > 0) {
519 r = netlink_message_append_in_addr_union(m, RTA_SRC, route->family, &route->src);
520 if (r < 0)
521 return r;
522
523 r = sd_rtnl_message_route_set_src_prefixlen(m, route->src_prefixlen);
524 if (r < 0)
525 return r;
526 }
527
528 r = sd_rtnl_message_route_set_tos(m, route->tos);
529 if (r < 0)
530 return r;
531
532 r = sd_rtnl_message_route_set_scope(m, route->scope);
533 if (r < 0)
534 return r;
535
536 r = sd_rtnl_message_route_set_type(m, route->type);
537 if (r < 0)
538 return r;
539
540 r = sd_rtnl_message_route_set_flags(m, route->flags & ~RTNH_COMPARE_MASK);
541 if (r < 0)
542 return r;
543
544 /* attributes */
545 r = sd_netlink_message_append_u32(m, RTA_PRIORITY, route->priority);
546 if (r < 0)
547 return r;
548
549 if (in_addr_is_set(route->family, &route->prefsrc)) {
550 r = netlink_message_append_in_addr_union(m, RTA_PREFSRC, route->family, &route->prefsrc);
551 if (r < 0)
552 return r;
553 }
554
555 if (route->table < 256) {
556 r = sd_rtnl_message_route_set_table(m, route->table);
557 if (r < 0)
558 return r;
559 } else {
560 r = sd_rtnl_message_route_set_table(m, RT_TABLE_UNSPEC);
561 if (r < 0)
562 return r;
563
564 /* Table attribute to allow more than 256. */
565 r = sd_netlink_message_append_u32(m, RTA_TABLE, route->table);
566 if (r < 0)
567 return r;
568 }
569
570 r = sd_netlink_message_append_u8(m, RTA_PREF, route->pref);
571 if (r < 0)
572 return r;
573
574 /* nexthops */
575 r = route_nexthops_set_netlink_message(route, m);
576 if (r < 0)
577 return r;
578
579 /* metrics */
580 r = route_metric_set_netlink_message(&route->metric, m);
581 if (r < 0)
582 return r;
583
584 return 0;
585}
586
587static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, RemoveRequest *rreq) {
588 int r;
589
590 assert(m);
591 assert(rreq);
592
593 Manager *manager = ASSERT_PTR(rreq->manager);
594 Route *route = ASSERT_PTR(rreq->userdata);
595
596 r = sd_netlink_message_get_errno(m);
597 if (r < 0) {
598 log_message_full_errno(m,
599 (r == -ESRCH || /* the route is already removed? */
600 (r == -EINVAL && route->nexthop_id != 0) || /* The nexthop is already removed? */
601 !route->manager) ? /* already detached? */
602 LOG_DEBUG : LOG_WARNING,
603 r, "Could not drop route, ignoring");
604
605 /* If the route cannot be removed, then assume the route is already removed. */
606 route_forget(manager, route, "Forgetting");
607 }
608
609 return 1;
610}
611
612int route_remove(Route *route, Manager *manager) {
613 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
614 Link *link = NULL;
615 int r;
616
617 assert(route);
618 assert(manager);
619
620 if (manager->state == MANAGER_STOPPED)
621 return 0; /* The remove request will not be queued anyway. Suppress logging below. */
622
623 /* If the route is remembered, then use the remembered object. */
624 (void) route_get(manager, route, &route);
625
626 log_route_debug(route, "Removing", manager);
627
628 /* For logging. */
629 (void) route_get_link(manager, route, &link);
630
631 r = sd_rtnl_message_new_route(manager->rtnl, &m, RTM_DELROUTE, route->family, route->protocol);
632 if (r < 0)
633 return log_link_warning_errno(link, r, "Could not create netlink message: %m");
634
635 r = route_set_netlink_message(route, m);
636 if (r < 0)
637 return log_link_warning_errno(link, r, "Could not fill netlink message: %m");
638
639 r = manager_remove_request_add(manager, route, route, manager->rtnl, m, route_remove_handler);
640 if (r < 0)
641 return log_link_warning_errno(link, r, "Could not queue rtnetlink message: %m");
642
643 route_enter_removing(route);
644 return 0;
645}
646
647int route_remove_and_cancel(Route *route, Manager *manager) {
648 _cleanup_(request_unrefp) Request *req = NULL;
649 bool waiting = false;
650
651 assert(route);
652 assert(manager);
653
654 /* If the route is remembered by the manager, then use the remembered object. */
655 (void) route_get(manager, route, &route);
656
657 /* Cancel the request for the route. If the request is already called but we have not received the
658 * notification about the request, then explicitly remove the route. */
659 if (route_get_request(manager, route, &req) >= 0) {
660 request_ref(req); /* avoid the request freed by request_detach() */
661 waiting = req->waiting_reply;
662 request_detach(req);
663 route_cancel_requesting(route);
664 }
665
666 /* If we know that the route will come or already exists, remove it. */
667 if (waiting || (route->manager && route_exists(route)))
668 return route_remove(route, manager);
669
670 return 0;
671}
672
673static int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
674 Route *route = ASSERT_PTR(userdata);
675 int r;
676
677 if (!route->manager)
678 return 0; /* already detached. */
679
680 r = route_remove(route, route->manager);
681 if (r < 0) {
682 Link *link = NULL;
683 (void) route_get_link(route->manager, route, &link);
684 log_link_warning_errno(link, r, "Could not remove route: %m");
685 if (link)
686 link_enter_failed(link);
687 }
688
689 return 1;
690}
691
692static int route_setup_timer(Route *route, const struct rta_cacheinfo *cacheinfo) {
693 int r;
694
695 assert(route);
696
697 if (cacheinfo && cacheinfo->rta_expires != 0)
698 route->expiration_managed_by_kernel = true;
699
700 if (route->lifetime_usec == USEC_INFINITY || /* We do not request expiration for the route. */
701 route->expiration_managed_by_kernel) { /* We have received nonzero expiration previously. The expiration is managed by the kernel. */
702 route->expire = sd_event_source_disable_unref(route->expire);
703 return 0;
704 }
705
706 Manager *manager = ASSERT_PTR(route->manager);
707 r = event_reset_time(manager->event, &route->expire, CLOCK_BOOTTIME,
708 route->lifetime_usec, 0, route_expire_handler, route, 0, "route-expiration", true);
709 if (r < 0) {
710 Link *link = NULL;
711 (void) route_get_link(manager, route, &link);
712 return log_link_warning_errno(link, r, "Failed to configure expiration timer for route, ignoring: %m");
713 }
714
715 log_route_debug(route, "Configured expiration timer for", manager);
716 return 1;
717}
718
719static int route_update_by_request(Route *route, Request *req) {
720 assert(route);
721 assert(req);
722
723 Route *rt = ASSERT_PTR(req->userdata);
724
725 route->provider = rt->provider;
726 route->source = rt->source;
727 route->lifetime_usec = rt->lifetime_usec;
728
729 return 0;
730}
731
732static int route_update_on_existing_one(Request *req, Route *requested) {
733 Manager *manager = ASSERT_PTR(ASSERT_PTR(req)->manager);
734 Route *existing;
735 int r;
736
737 assert(requested);
738
739 if (route_get(manager, requested, &existing) < 0)
740 return 0;
741
742 r = route_update_by_request(existing, req);
743 if (r < 0)
744 return r;
745
746 r = route_setup_timer(existing, NULL);
747 if (r < 0)
748 return r;
749
750 /* This may be a bug in the kernel, but the MTU of an IPv6 route can be updated only when the
751 * route has an expiration timer managed by the kernel (not by us). See fib6_add_rt2node() in
752 * net/ipv6/ip6_fib.c of the kernel. */
753 if (existing->family == AF_INET6 &&
754 existing->expiration_managed_by_kernel) {
755 r = route_metric_set(&existing->metric, RTAX_MTU, route_metric_get(&requested->metric, RTAX_MTU));
756 if (r < 0)
757 return r;
758 }
759
760 route_enter_configured(existing);
761 return 0;
762}
763
764static int route_update_on_existing(Request *req) {
765 Route *rt = ASSERT_PTR(ASSERT_PTR(req)->userdata);
766 int r;
767
768 if (!req->manager)
769 /* Already detached? At least there are two possibilities then.
770 * 1) The interface is removed, and all queued requests for the interface are cancelled.
771 * 2) networkd is now stopping, hence all queued requests are cancelled.
772 * Anyway, we can ignore the request, and there is nothing we can do. */
773 return 0;
774
775 if (rt->family == AF_INET || ordered_set_isempty(rt->nexthops))
776 return route_update_on_existing_one(req, rt);
777
778 RouteNextHop *nh;
779 ORDERED_SET_FOREACH(nh, rt->nexthops) {
780 _cleanup_(route_unrefp) Route *dup = NULL;
781
782 r = route_dup(rt, nh, &dup);
783 if (r < 0)
784 return r;
785
786 r = route_update_on_existing_one(req, dup);
787 if (r < 0)
788 return r;
789 }
790
791 return 0;
792}
793
794int route_configure_handler_internal(sd_netlink_message *m, Request *req, Route *route) {
795 int r;
796
797 assert(m);
798 assert(req);
799 assert(route);
800
801 Link *link = ASSERT_PTR(req->link);
802
803 r = sd_netlink_message_get_errno(m);
804 if (r == -EEXIST) {
805 /* When re-configuring an existing route, kernel does not send RTM_NEWROUTE notification, so
806 * here we need to update the state, provider, source, timer, and so on. */
807 r = route_update_on_existing(req);
808 if (r < 0) {
809 log_link_warning_errno(link, r, "Failed to update existing route: %m");
810 link_enter_failed(link);
811 return 0;
812 }
813
814 return 1;
815 }
816 if (r < 0) {
817 _cleanup_free_ char *str = NULL;
818 (void) route_to_string(route, link->manager, &str);
819 log_link_message_warning_errno(link, m, r, "Failed to configure %s route (%s)",
820 network_config_source_to_string(route->source), strna(str));
821 link_enter_failed(link);
822 return 0;
823 }
824
825 return 1;
826}
827
828static int route_configure(const Route *route, uint32_t lifetime_sec, Link *link, Request *req) {
829 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
830 int r;
831
832 assert(route);
833 assert(link);
834 assert(link->manager);
835 assert(req);
836
837 log_route_debug(route, "Configuring", link->manager);
838
839 r = sd_rtnl_message_new_route(link->manager->rtnl, &m, RTM_NEWROUTE, route->family, route->protocol);
840 if (r < 0)
841 return r;
842
843 r = route_set_netlink_message(route, m);
844 if (r < 0)
845 return r;
846
847 if (lifetime_sec != UINT32_MAX) {
848 r = sd_netlink_message_append_u32(m, RTA_EXPIRES, lifetime_sec);
849 if (r < 0)
850 return r;
851 }
852
853 return request_call_netlink_async(link->manager->rtnl, m, req);
854}
855
856static int route_requeue_request(Request *req, Link *link, const Route *route) {
857 _unused_ _cleanup_(request_unrefp) Request *req_unref = NULL;
858 _cleanup_(route_unrefp) Route *tmp = NULL;
859 int r;
860
861 assert(req);
862 assert(link);
863 assert(link->manager);
864 assert(route);
865
866 /* It is not possible to adjust the Route object owned by Request, as it is used as a key to manage
867 * Request objects in the queue. Hence, we need to re-request with the updated Route object. */
868
869 if (!route_nexthops_needs_adjust(route))
870 return 0; /* The Route object does not need the adjustment. Continue with it. */
871
872 r = route_dup(route, NULL, &tmp);
873 if (r < 0)
874 return r;
875
876 r = route_adjust_nexthops(tmp, link);
877 if (r <= 0)
878 return r;
879
880 if (route_compare_func(route, tmp) == 0 && route->type == tmp->type)
881 return 0; /* No effective change?? That's OK. */
882
883 /* Avoid the request to be freed by request_detach(). */
884 req_unref = request_ref(req);
885
886 /* Detach the request from the queue, to make not the new request is deduped.
887 * Why this is necessary? IPv6 routes with different type may be handled as the same,
888 * As commented in route_adjust_nexthops(), we need to configure the adjusted type,
889 * otherwise we cannot remove the route on reconfigure or so. If we request the new Route object
890 * without detaching the current request, the new request is deduped, and the route is configured
891 * with unmodified type. */
892 request_detach(req);
893
894 /* Request the route with the adjusted Route object combined with the same other parameters. */
895 r = link_requeue_request(link, req, tmp, NULL);
896 if (r < 0)
897 return r;
898 if (r == 0)
899 return 1; /* Already queued?? That's OK. Maybe, [Route] section is effectively duplicated. */
900
901 TAKE_PTR(tmp);
902 return 1; /* New request is queued. Finish to process this request. */
903}
904
905static int route_is_ready_to_configure(const Route *route, Link *link) {
906 assert(route);
907 assert(link);
908
909 if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false))
910 return false;
911
912 if (in_addr_is_set(route->family, &route->prefsrc) > 0) {
913 Address *a;
914
915 if (manager_get_address(link->manager, route->family, &route->prefsrc, &a) < 0)
916 return false;
917
918 if (!address_is_ready(a))
919 return false;
920 }
921
922 return route_nexthops_is_ready_to_configure(route, link->manager);
923}
924
925static int route_process_request(Request *req, Link *link, Route *route) {
926 Route *existing;
927 int r;
928
929 assert(req);
930 assert(link);
931 assert(link->manager);
932 assert(route);
933
934 r = route_is_ready_to_configure(route, link);
935 if (r < 0)
936 return log_link_warning_errno(link, r, "Failed to check if route is ready to configure: %m");
937 if (r == 0)
938 return 0;
939
940 usec_t now_usec;
941 assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
942 uint32_t sec = usec_to_sec(route->lifetime_usec, now_usec);
943 if (sec == 0) {
944 log_link_debug(link, "Refuse to configure %s route with zero lifetime.",
945 network_config_source_to_string(route->source));
946
947 route_cancel_requesting(route);
948 if (route_get(link->manager, route, &existing) >= 0)
949 route_cancel_requesting(existing);
950 return 1;
951 }
952
953 r = route_requeue_request(req, link, route);
954 if (r != 0)
955 return r;
956
957 r = route_configure(route, sec, link, req);
958 if (r < 0)
959 return log_link_warning_errno(link, r, "Failed to configure route: %m");
960
961 route_enter_configuring(route);
962 if (route_get(link->manager, route, &existing) >= 0)
963 route_enter_configuring(existing);
964 return 1;
965}
966
967static int link_request_route_one(
968 Link *link,
969 const Route *route,
970 const RouteNextHop *nh,
971 unsigned *message_counter,
972 route_netlink_handler_t netlink_handler) {
973
974 _cleanup_(route_unrefp) Route *tmp = NULL;
975 Route *existing = NULL;
976 int r;
977
978 assert(link);
979 assert(link->manager);
980 assert(route);
981
982 r = route_dup(route, nh, &tmp);
983 if (r < 0)
984 return r;
985
986 r = route_adjust_nexthops(tmp, link);
987 if (r < 0)
988 return r;
989
990 if (route_get(link->manager, tmp, &existing) >= 0)
991 /* Copy state for logging below. */
992 tmp->state = existing->state;
993
994 log_route_debug(tmp, "Requesting", link->manager);
995 r = link_queue_request_safe(link, REQUEST_TYPE_ROUTE,
996 tmp,
997 route_unref,
998 route_hash_func,
999 route_compare_func,
1000 route_process_request,
1001 message_counter,
1002 netlink_handler,
1003 NULL);
1004 if (r <= 0)
1005 return r;
1006
1007 route_enter_requesting(tmp);
1008 if (existing)
1009 route_enter_requesting(existing);
1010
1011 TAKE_PTR(tmp);
1012 return 1;
1013}
1014
1015int link_request_route(
1016 Link *link,
1017 const Route *route,
1018 unsigned *message_counter,
1019 route_netlink_handler_t netlink_handler) {
1020
1021 int r;
1022
1023 assert(link);
1024 assert(link->manager);
1025 assert(route);
1026 assert(route->source != NETWORK_CONFIG_SOURCE_FOREIGN);
1027
1028 if (route->family == AF_INET || route_is_reject(route) || ordered_set_isempty(route->nexthops))
1029 return link_request_route_one(link, route, NULL, message_counter, netlink_handler);
1030
1031 RouteNextHop *nh;
1032 ORDERED_SET_FOREACH(nh, route->nexthops) {
1033 r = link_request_route_one(link, route, nh, message_counter, netlink_handler);
1034 if (r < 0)
1035 return r;
1036 }
1037
1038 return 0;
1039}
1040
1041static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
1042 int r;
1043
1044 assert(req);
1045 assert(link);
1046 assert(route);
1047
1048 r = route_configure_handler_internal(m, req, route);
1049 if (r <= 0)
1050 return r;
1051
1052 if (link->static_route_messages == 0) {
1053 log_link_debug(link, "Routes set");
1054 link->static_routes_configured = true;
1055 link_check_ready(link);
1056 }
1057
1058 return 1;
1059}
1060
1061static int link_request_wireguard_routes(Link *link, bool only_ipv4) {
1062 Route *route;
1063 int r;
1064
1065 assert(link);
1066
1067 if (!link->netdev || link->netdev->kind != NETDEV_KIND_WIREGUARD)
1068 return 0;
1069
1070 Wireguard *w = WIREGUARD(link->netdev);
1071
1072 SET_FOREACH(route, w->routes) {
1073 if (only_ipv4 && route->family != AF_INET)
1074 continue;
1075
1076 r = link_request_route(link, route, &link->static_route_messages, static_route_handler);
1077 if (r < 0)
1078 return r;
1079 }
1080
1081 return 0;
1082}
1083
1084int link_request_static_routes(Link *link, bool only_ipv4) {
1085 Route *route;
1086 int r;
1087
1088 assert(link);
1089 assert(link->network);
1090
1091 link->static_routes_configured = false;
1092
1093 HASHMAP_FOREACH(route, link->network->routes_by_section) {
1094 if (route->source != NETWORK_CONFIG_SOURCE_STATIC)
1095 continue;
1096
1097 if (only_ipv4 && route->family != AF_INET)
1098 continue;
1099
1100 r = link_request_route(link, route, &link->static_route_messages, static_route_handler);
1101 if (r < 0)
1102 return r;
1103 }
1104
1105 r = link_request_wireguard_routes(link, only_ipv4);
1106 if (r < 0)
1107 return r;
1108
1109 if (link->static_route_messages == 0) {
1110 link->static_routes_configured = true;
1111 link_check_ready(link);
1112 } else {
1113 log_link_debug(link, "Requesting routes");
1114 link_set_state(link, LINK_STATE_CONFIGURING);
1115 }
1116
1117 return 0;
1118}
1119
1120static int process_route_one(
1121 Manager *manager,
1122 uint16_t type,
1123 Route *tmp,
1124 const struct rta_cacheinfo *cacheinfo) {
1125
1126 Route *route = NULL;
1127 Link *link = NULL;
1128 bool is_new = false, update_dhcp4;
1129 int r;
1130
1131 assert(manager);
1132 assert(tmp);
1133 assert(IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE));
1134
1135 (void) route_get(manager, tmp, &route);
1136 (void) route_get_link(manager, tmp, &link);
1137
1138 update_dhcp4 = link && tmp->family == AF_INET6 && tmp->dst_prefixlen == 0;
1139
1140 switch (type) {
1141 case RTM_NEWROUTE: {
1142 Request *req = NULL;
1143 (void) route_get_request(manager, tmp, &req);
1144
1145 if (!route) {
1146 if (!manager->manage_foreign_routes && !(req && req->waiting_reply)) {
1147 route_enter_configured(tmp);
1148 log_route_debug(tmp, "Ignoring received", manager);
1149 return 0;
1150 }
1151
1152 /* If we do not know the route, then save it. */
1153 r = route_attach(manager, tmp);
1154 if (r < 0) {
1155 log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m");
1156 return 0;
1157 }
1158
1159 route = route_ref(tmp);
1160 is_new = true;
1161
1162 } else {
1163 /* Update remembered route with the received notification. */
1164
1165 /* Here, update weight only when a non-zero weight is received. As the kernel does
1166 * not provide the weight of a single-path route. In such case, tmp->nexthop.weight
1167 * is zero, hence we should not overwrite the known weight of the route. */
1168 if (tmp->nexthop.weight != 0)
1169 route->nexthop.weight = tmp->nexthop.weight;
1170 }
1171
1172 /* Also update information that cannot be obtained through netlink notification. */
1173 if (req && req->waiting_reply) {
1174 r = route_update_by_request(route, req);
1175 if (r < 0) {
1176 log_link_warning_errno(link, r, "Failed to update route by request: %m");
1177 link_enter_failed(link);
1178 return 0;
1179 }
1180
1181 /* We configure IPv6 multipath route separately. When the first path is configured,
1182 * the kernel does not provide the weight of the path. So, we need to adjust it here.
1183 * Hopefully, the weight is assigned correctly. */
1184 if (route->nexthop.weight == 0) {
1185 Route *rt = ASSERT_PTR(req->userdata);
1186 route->nexthop.weight = rt->nexthop.weight;
1187 }
1188 }
1189
1190 route_attach_to_nexthop(route);
1191
1192 route_enter_configured(route);
1193 log_route_debug(route, is_new ? "Received new" : "Received remembered", manager);
1194
1195 (void) route_setup_timer(route, cacheinfo);
1196
1197 break;
1198 }
1199 case RTM_DELROUTE:
1200 if (route)
1201 route_forget(manager, route, "Forgetting removed");
1202 else
1203 log_route_debug(tmp,
1204 manager->manage_foreign_routes ? "Kernel removed unknown" : "Ignoring received",
1205 manager);
1206 break;
1207
1208 default:
1209 assert_not_reached();
1210 }
1211
1212 if (update_dhcp4) {
1213 r = dhcp4_update_ipv6_connectivity(link);
1214 if (r < 0) {
1215 log_link_warning_errno(link, r, "Failed to notify IPv6 connectivity to DHCPv4 client: %m");
1216 link_enter_failed(link);
1217 }
1218 }
1219
1220 return 1;
1221}
1222
1223int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
1224 _cleanup_(route_unrefp) Route *tmp = NULL;
1225 int r;
1226
1227 assert(rtnl);
1228 assert(message);
1229 assert(m);
1230
1231 if (sd_netlink_message_is_error(message)) {
1232 r = sd_netlink_message_get_errno(message);
1233 if (r < 0)
1234 log_message_warning_errno(message, r, "rtnl: failed to receive route message, ignoring");
1235
1236 return 0;
1237 }
1238
1239 uint16_t type;
1240 r = sd_netlink_message_get_type(message, &type);
1241 if (r < 0) {
1242 log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
1243 return 0;
1244 } else if (!IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE)) {
1245 log_warning("rtnl: received unexpected message type %u when processing route, ignoring.", type);
1246 return 0;
1247 }
1248
1249 r = route_new(&tmp);
1250 if (r < 0)
1251 return log_oom();
1252
1253 /* rtmsg header */
1254 r = sd_rtnl_message_route_get_family(message, &tmp->family);
1255 if (r < 0) {
1256 log_warning_errno(r, "rtnl: received route message without family, ignoring: %m");
1257 return 0;
1258 } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
1259 log_debug("rtnl: received route message with invalid family '%i', ignoring.", tmp->family);
1260 return 0;
1261 }
1262
1263 r = sd_rtnl_message_route_get_dst_prefixlen(message, &tmp->dst_prefixlen);
1264 if (r < 0) {
1265 log_warning_errno(r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m");
1266 return 0;
1267 }
1268
1269 r = sd_rtnl_message_route_get_src_prefixlen(message, &tmp->src_prefixlen);
1270 if (r < 0) {
1271 log_warning_errno(r, "rtnl: received route message with invalid source prefixlen, ignoring: %m");
1272 return 0;
1273 }
1274
1275 r = sd_rtnl_message_route_get_tos(message, &tmp->tos);
1276 if (r < 0) {
1277 log_warning_errno(r, "rtnl: received route message with invalid tos, ignoring: %m");
1278 return 0;
1279 }
1280
1281 r = sd_rtnl_message_route_get_protocol(message, &tmp->protocol);
1282 if (r < 0) {
1283 log_warning_errno(r, "rtnl: received route message without route protocol, ignoring: %m");
1284 return 0;
1285 }
1286
1287 r = sd_rtnl_message_route_get_scope(message, &tmp->scope);
1288 if (r < 0) {
1289 log_warning_errno(r, "rtnl: received route message with invalid scope, ignoring: %m");
1290 return 0;
1291 }
1292
1293 r = sd_rtnl_message_route_get_type(message, &tmp->type);
1294 if (r < 0) {
1295 log_warning_errno(r, "rtnl: received route message with invalid type, ignoring: %m");
1296 return 0;
1297 }
1298
1299 r = sd_rtnl_message_route_get_flags(message, &tmp->flags);
1300 if (r < 0) {
1301 log_warning_errno(r, "rtnl: received route message without route flags, ignoring: %m");
1302 return 0;
1303 }
1304
1305 /* attributes */
1306 r = netlink_message_read_in_addr_union(message, RTA_DST, tmp->family, &tmp->dst);
1307 if (r < 0 && r != -ENODATA) {
1308 log_warning_errno(r, "rtnl: received route message without valid destination, ignoring: %m");
1309 return 0;
1310 }
1311
1312 r = netlink_message_read_in_addr_union(message, RTA_SRC, tmp->family, &tmp->src);
1313 if (r < 0 && r != -ENODATA) {
1314 log_warning_errno(r, "rtnl: received route message without valid source, ignoring: %m");
1315 return 0;
1316 }
1317
1318 r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority);
1319 if (r < 0 && r != -ENODATA) {
1320 log_warning_errno(r, "rtnl: received route message with invalid priority, ignoring: %m");
1321 return 0;
1322 }
1323
1324 r = netlink_message_read_in_addr_union(message, RTA_PREFSRC, tmp->family, &tmp->prefsrc);
1325 if (r < 0 && r != -ENODATA) {
1326 log_warning_errno(r, "rtnl: received route message without valid preferred source, ignoring: %m");
1327 return 0;
1328 }
1329
1330 r = sd_netlink_message_read_u32(message, RTA_TABLE, &tmp->table);
1331 if (r == -ENODATA) {
1332 unsigned char table;
1333
1334 r = sd_rtnl_message_route_get_table(message, &table);
1335 if (r >= 0)
1336 tmp->table = table;
1337 }
1338 if (r < 0) {
1339 log_warning_errno(r, "rtnl: received route message with invalid table, ignoring: %m");
1340 return 0;
1341 }
1342
1343 r = sd_netlink_message_read_u8(message, RTA_PREF, &tmp->pref);
1344 if (r < 0 && r != -ENODATA) {
1345 log_warning_errno(r, "rtnl: received route message with invalid preference, ignoring: %m");
1346 return 0;
1347 }
1348
1349 /* nexthops */
1350 if (route_nexthops_read_netlink_message(tmp, message) < 0)
1351 return 0;
1352
1353 /* metrics */
1354 if (route_metric_read_netlink_message(&tmp->metric, message) < 0)
1355 return 0;
1356
1357 bool has_cacheinfo;
1358 struct rta_cacheinfo cacheinfo;
1359 r = sd_netlink_message_read(message, RTA_CACHEINFO, sizeof(cacheinfo), &cacheinfo);
1360 if (r < 0 && r != -ENODATA) {
1361 log_warning_errno(r, "rtnl: failed to read RTA_CACHEINFO attribute, ignoring: %m");
1362 return 0;
1363 }
1364 has_cacheinfo = r >= 0;
1365
1366 if (tmp->family == AF_INET || ordered_set_isempty(tmp->nexthops))
1367 return process_route_one(m, type, tmp, has_cacheinfo ? &cacheinfo : NULL);
1368
1369 RouteNextHop *nh;
1370 ORDERED_SET_FOREACH(nh, tmp->nexthops) {
1371 _cleanup_(route_unrefp) Route *dup = NULL;
1372
1373 r = route_dup(tmp, nh, &dup);
1374 if (r < 0)
1375 return log_oom();
1376
1377 r = process_route_one(m, type, dup, has_cacheinfo ? &cacheinfo : NULL);
1378 if (r < 0)
1379 return r;
1380 }
1381
1382 return 1;
1383}
1384
1385void manager_mark_routes(Manager *manager, Link *link, NetworkConfigSource source) {
1386 Route *route;
1387
1388 assert(manager);
1389
1390 SET_FOREACH(route, manager->routes) {
1391 if (route->source != source)
1392 continue;
1393
1394 if (link) {
1395 Link *route_link;
1396
1397 if (route_get_link(manager, route, &route_link) < 0)
1398 continue;
1399 if (route_link != link)
1400 continue;
1401 }
1402
1403 route_mark(route);
1404 }
1405}
1406
1407static bool route_by_kernel(const Route *route) {
1408 assert(route);
1409
1410 if (route->protocol == RTPROT_KERNEL)
1411 return true;
1412
1413 /* The kernels older than a826b04303a40d52439aa141035fca5654ccaccd (v5.11) create the IPv6
1414 * multicast with RTPROT_BOOT. Do not touch it. */
1415 if (route->protocol == RTPROT_BOOT &&
1416 route->family == AF_INET6 &&
1417 route->dst_prefixlen == 8 &&
1418 in6_addr_equal(&route->dst.in6, & (struct in6_addr) {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}}))
1419 return true;
1420
1421 return false;
1422}
1423
1424bool route_can_update(Manager *manager, const Route *existing, const Route *requesting) {
1425 int r;
1426
1427 assert(manager);
1428 assert(existing);
1429 assert(requesting);
1430
1431 if (route_compare_func(existing, requesting) != 0) {
1432 log_route_debug(existing, "Cannot update route, as the existing route is different", manager);
1433 return false;
1434 }
1435
1436 switch (existing->family) {
1437 case AF_INET:
1438 if (existing->nexthop.weight != requesting->nexthop.weight) {
1439 log_debug("Cannot update route: existing weight: %u, requesting weight: %u",
1440 existing->nexthop.weight, requesting->nexthop.weight);
1441 return false;
1442 }
1443 return true;
1444
1445 case AF_INET6:
1446 if (existing->protocol != requesting->protocol) {
1447 if (DEBUG_LOGGING) {
1448 _cleanup_free_ char *ex = NULL, *req = NULL;
1449
1450 r = route_protocol_to_string_alloc(existing->protocol, &ex);
1451 if (r < 0)
1452 return false;
1453
1454 r = route_protocol_to_string_alloc(requesting->protocol, &req);
1455 if (r < 0)
1456 return false;
1457
1458 log_debug("Cannot update route: existing protocol: %s, requesting protocol: %s", ex, req);
1459 }
1460
1461 return false;
1462 }
1463 if (existing->type != requesting->type) {
1464 log_debug("Cannot update route: existing type: %s, requesting type: %s",
1465 route_type_to_string(existing->type),
1466 route_type_to_string(requesting->type));
1467
1468 return false;
1469 }
1470 if ((existing->flags & ~RTNH_COMPARE_MASK) != (requesting->flags & ~RTNH_COMPARE_MASK)) {
1471 if (DEBUG_LOGGING) {
1472 _cleanup_free_ char *ex = NULL, *req = NULL;
1473
1474 r = route_flags_to_string_alloc(existing->flags, &ex);
1475 if (r < 0)
1476 return false;
1477
1478 r = route_flags_to_string_alloc(requesting->flags, &req);
1479 if (r < 0)
1480 return false;
1481
1482 log_debug("Cannot update route: existing flags: %s, requesting flags: %s", ex, req);
1483 }
1484
1485 return false;
1486 }
1487 if (!in6_addr_equal(&existing->prefsrc.in6, &requesting->prefsrc.in6)) {
1488 log_debug("Cannot update route: existing preferred source: %s, requesting preferred source: %s",
1489 IN6_ADDR_TO_STRING(&existing->prefsrc.in6),
1490 IN6_ADDR_TO_STRING(&requesting->prefsrc.in6));
1491 return false;
1492 }
1493 if (existing->pref != requesting->pref) {
1494 log_debug("Cannot update route: existing preference: %u, requesting preference: %u",
1495 existing->pref, requesting->pref);
1496 return false;
1497 }
1498 if (existing->expiration_managed_by_kernel && requesting->lifetime_usec == USEC_INFINITY) {
1499 log_route_debug(existing,
1500 "Cannot update route: the expiration is managed by the kernel and requested lifetime is infinite",
1501 manager);
1502 return false; /* We cannot disable expiration timer in the kernel. */
1503 }
1504 if (!route_metric_can_update(&existing->metric, &requesting->metric, existing->expiration_managed_by_kernel)) {
1505 log_route_debug(existing,
1506 "Cannot update route: expiration is managed by the kernel or metrics differ",
1507 manager);
1508 return false;
1509 }
1510 if (existing->nexthop.weight != requesting->nexthop.weight) {
1511 log_debug("Cannot update route: existing weight: %u, requesting weight: %u",
1512 existing->nexthop.weight, requesting->nexthop.weight);
1513 return false;
1514 }
1515 return true;
1516
1517 default:
1518 assert_not_reached();
1519 }
1520}
1521
1522static int link_unmark_route(Link *link, const Route *route, const RouteNextHop *nh) {
1523 _cleanup_(route_unrefp) Route *tmp = NULL;
1524 Route *existing;
1525 int r;
1526
1527 assert(link);
1528 assert(route);
1529
1530 r = route_dup(route, nh, &tmp);
1531 if (r < 0)
1532 return r;
1533
1534 r = route_adjust_nexthops(tmp, link);
1535 if (r < 0)
1536 return r;
1537
1538 if (route_get(link->manager, tmp, &existing) < 0)
1539 return 0;
1540
1541 if (!route_can_update(link->manager, existing, tmp))
1542 return 0;
1543
1544 route_unmark(existing);
1545 return 1;
1546}
1547
1548int link_drop_routes(Link *link, bool only_static) {
1549 Route *route;
1550 Link *other;
1551 int r = 0;
1552
1553 assert(link);
1554 assert(link->manager);
1555
1556 /* First, mark all routes. */
1557 SET_FOREACH(route, link->manager->routes) {
1558 /* Do not touch routes managed by the kernel. */
1559 if (route_by_kernel(route))
1560 continue;
1561
1562 /* Ignore routes not assigned yet or already removed. */
1563 if (!route_exists(route))
1564 continue;
1565
1566 if (!link_should_mark_config(link, only_static, route->source, route->protocol))
1567 continue;
1568
1569 Link *route_link = NULL;
1570 if (route_get_link(link->manager, route, &route_link) >= 0 && route_link != link) {
1571 /* When we also mark foreign routes, do not mark routes assigned to other interfaces.
1572 * Otherwise, routes assigned to unmanaged interfaces will be dropped.
1573 * Note, route_get_link() does not provide assigned link for routes with an
1574 * unreachable type or IPv4 multipath routes. So, the current implementation does not
1575 * support managing such routes by other daemon or so, unless ManageForeignRoutes=no. */
1576 if (!only_static)
1577 continue;
1578
1579 /* When we mark only static routes, do not mark routes assigned to links that we do
1580 * not know the assignment of .network files to the interfaces. Otherwise, if an
1581 * interface is in the pending state, even if the .network file to be assigned to the
1582 * interface has KeepConfiguration=yes, routes on the interface will be removed.
1583 * This is especially important when systemd-networkd is restarted. */
1584 if (!IN_SET(route_link->state, LINK_STATE_UNMANAGED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
1585 continue;
1586 }
1587
1588 route_mark(route);
1589 }
1590
1591 /* Then, unmark all routes requested by active links. */
1592 HASHMAP_FOREACH(other, link->manager->links_by_index) {
1593 if (only_static && other == link)
1594 continue;
1595
1596 if (!IN_SET(other->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
1597 continue;
1598
1599 HASHMAP_FOREACH(route, other->network->routes_by_section) {
1600 if (route->source != NETWORK_CONFIG_SOURCE_STATIC)
1601 continue;
1602
1603 if (route->family == AF_INET || ordered_set_isempty(route->nexthops)) {
1604 r = link_unmark_route(other, route, NULL);
1605 if (r < 0)
1606 return r;
1607
1608 } else {
1609 RouteNextHop *nh;
1610 ORDERED_SET_FOREACH(nh, route->nexthops) {
1611 r = link_unmark_route(other, route, nh);
1612 if (r < 0)
1613 return r;
1614 }
1615 }
1616 }
1617
1618 /* Also unmark routes requested in .netdev file. */
1619 if (other->netdev && other->netdev->kind == NETDEV_KIND_WIREGUARD) {
1620 Wireguard *w = WIREGUARD(other->netdev);
1621
1622 SET_FOREACH(route, w->routes) {
1623 r = link_unmark_route(other, route, NULL);
1624 if (r < 0)
1625 return r;
1626 }
1627 }
1628 }
1629
1630 /* Finally, remove all marked routes. */
1631 SET_FOREACH(route, link->manager->routes) {
1632 if (!route_is_marked(route))
1633 continue;
1634
1635 RET_GATHER(r, route_remove(route, link->manager));
1636 }
1637
1638 return r;
1639}
1640
1641void link_forget_routes(Link *link) {
1642 assert(link);
1643 assert(link->ifindex > 0);
1644 assert(!FLAGS_SET(link->flags, IFF_UP));
1645
1646 /* When an interface went down, IPv4 non-local routes bound to the interface are silently removed by
1647 * the kernel, without any notifications. Let's forget them in that case. Otherwise, when the link
1648 * goes up later, the configuration order of routes may be confused by the nonexistent routes.
1649 * See issue #35047. */
1650
1651 Route *route;
1652 SET_FOREACH(route, link->manager->routes) {
1653 // TODO: handle multipath routes
1654 if (route->nexthop.ifindex != link->ifindex)
1655 continue;
1656 if (route->family != AF_INET)
1657 continue;
1658 // TODO: check RTN_NAT and RTN_XRESOLVE
1659 if (!IN_SET(route->type, RTN_UNICAST, RTN_BROADCAST, RTN_ANYCAST, RTN_MULTICAST))
1660 continue;
1661
1662 route_forget(link->manager, route, "Forgetting silently removed");
1663 }
1664}
1665
1666int network_add_ipv4ll_route(Network *network) {
1667 _cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
1668 unsigned section_line;
1669 int r;
1670
1671 assert(network);
1672
1673 if (!network->ipv4ll_route)
1674 return 0;
1675
1676 r = hashmap_by_section_find_unused_line(network->routes_by_section, network->filename, &section_line);
1677 if (r < 0)
1678 return r;
1679
1680 /* IPv4LLRoute= is in [Network] section. */
1681 r = route_new_static(network, network->filename, section_line, &route);
1682 if (r < 0)
1683 return r;
1684
1685 r = in_addr_from_string(AF_INET, "169.254.0.0", &route->dst);
1686 if (r < 0)
1687 return r;
1688
1689 route->family = AF_INET;
1690 route->dst_prefixlen = 16;
1691 route->scope = RT_SCOPE_LINK;
1692 route->scope_set = true;
1693 route->table_set = true;
1694 route->priority = IPV4LL_ROUTE_METRIC;
1695 route->protocol = RTPROT_STATIC;
1696
1697 TAKE_PTR(route);
1698 return 0;
1699}
1700
1701int network_add_default_route_on_device(Network *network) {
1702 _cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
1703 unsigned section_line;
1704 int r;
1705
1706 assert(network);
1707
1708 if (!network->default_route_on_device)
1709 return 0;
1710
1711 r = hashmap_by_section_find_unused_line(network->routes_by_section, network->filename, &section_line);
1712 if (r < 0)
1713 return r;
1714
1715 /* DefaultRouteOnDevice= is in [Network] section. */
1716 r = route_new_static(network, network->filename, section_line, &route);
1717 if (r < 0)
1718 return r;
1719
1720 route->family = AF_INET;
1721 route->scope = RT_SCOPE_LINK;
1722 route->scope_set = true;
1723 route->protocol = RTPROT_STATIC;
1724
1725 TAKE_PTR(route);
1726 return 0;
1727}
1728
1729static int config_parse_preferred_src(
1730 const char *unit,
1731 const char *filename,
1732 unsigned line,
1733 const char *section,
1734 unsigned section_line,
1735 const char *lvalue,
1736 int ltype,
1737 const char *rvalue,
1738 void *data,
1739 void *userdata) {
1740
1741 Route *route = ASSERT_PTR(userdata);
1742 int r;
1743
1744 if (isempty(rvalue)) {
1745 route->prefsrc_set = false;
1746 route->prefsrc = IN_ADDR_NULL;
1747 return 1;
1748 }
1749
1750 r = parse_boolean(rvalue);
1751 if (r == 0) {
1752 /* Accepts only no. That prohibits prefsrc set by DHCP lease. */
1753 route->prefsrc_set = true;
1754 route->prefsrc = IN_ADDR_NULL;
1755 return 1;
1756 }
1757
1758 if (route->family == AF_UNSPEC)
1759 r = in_addr_from_string_auto(rvalue, &route->family, &route->prefsrc);
1760 else
1761 r = in_addr_from_string(route->family, rvalue, &route->prefsrc);
1762 if (r < 0)
1763 return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
1764
1765 route->prefsrc_set = true;
1766 return 1;
1767}
1768
1769static int config_parse_route_destination(
1770 const char *unit,
1771 const char *filename,
1772 unsigned line,
1773 const char *section,
1774 unsigned section_line,
1775 const char *lvalue,
1776 int ltype,
1777 const char *rvalue,
1778 void *data,
1779 void *userdata) {
1780
1781 Route *route = ASSERT_PTR(userdata);
1782 union in_addr_union *buffer;
1783 unsigned char *prefixlen;
1784 int r;
1785
1786 assert(lvalue);
1787 assert(rvalue);
1788
1789 if (streq(lvalue, "Destination")) {
1790 buffer = &route->dst;
1791 prefixlen = &route->dst_prefixlen;
1792 } else if (streq(lvalue, "Source")) {
1793 buffer = &route->src;
1794 prefixlen = &route->src_prefixlen;
1795 } else
1796 assert_not_reached();
1797
1798 if (route->family == AF_UNSPEC)
1799 r = in_addr_prefix_from_string_auto(rvalue, &route->family, buffer, prefixlen);
1800 else
1801 r = in_addr_prefix_from_string(rvalue, route->family, buffer, prefixlen);
1802 if (r < 0)
1803 return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
1804
1805 (void) in_addr_mask(route->family, buffer, *prefixlen);
1806 return 1;
1807}
1808
1809static int config_parse_route_priority(
1810 const char *unit,
1811 const char *filename,
1812 unsigned line,
1813 const char *section,
1814 unsigned section_line,
1815 const char *lvalue,
1816 int ltype,
1817 const char *rvalue,
1818 void *data,
1819 void *userdata) {
1820
1821 Route *route = ASSERT_PTR(userdata);
1822 int r;
1823
1824 assert(rvalue);
1825
1826 r = safe_atou32(rvalue, &route->priority);
1827 if (r < 0)
1828 return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
1829
1830 route->priority_set = true;
1831 return 1;
1832}
1833
1834static int config_parse_route_scope(
1835 const char *unit,
1836 const char *filename,
1837 unsigned line,
1838 const char *section,
1839 unsigned section_line,
1840 const char *lvalue,
1841 int ltype,
1842 const char *rvalue,
1843 void *data,
1844 void *userdata) {
1845
1846 Route *route = ASSERT_PTR(userdata);
1847 int r;
1848
1849 assert(rvalue);
1850
1851 r = route_scope_from_string(rvalue);
1852 if (r < 0)
1853 return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
1854
1855 route->scope = r;
1856 route->scope_set = true;
1857 return 1;
1858}
1859
1860static int config_parse_route_table(
1861 const char *unit,
1862 const char *filename,
1863 unsigned line,
1864 const char *section,
1865 unsigned section_line,
1866 const char *lvalue,
1867 int ltype,
1868 const char *rvalue,
1869 void *data,
1870 void *userdata) {
1871
1872 Route *route = ASSERT_PTR(userdata);
1873 Manager *manager = ASSERT_PTR(ASSERT_PTR(route->network)->manager);
1874 int r;
1875
1876 assert(rvalue);
1877
1878 r = manager_get_route_table_from_string(manager, rvalue, &route->table);
1879 if (r < 0)
1880 return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
1881
1882 route->table_set = true;
1883 return 1;
1884}
1885
1886static int config_parse_route_preference(
1887 const char *unit,
1888 const char *filename,
1889 unsigned line,
1890 const char *section,
1891 unsigned section_line,
1892 const char *lvalue,
1893 int ltype,
1894 const char *rvalue,
1895 void *data,
1896 void *userdata) {
1897
1898 Route *route = ASSERT_PTR(userdata);
1899
1900 assert(rvalue);
1901
1902 if (streq(rvalue, "low"))
1903 route->pref = SD_NDISC_PREFERENCE_LOW;
1904 else if (streq(rvalue, "medium"))
1905 route->pref = SD_NDISC_PREFERENCE_MEDIUM;
1906 else if (streq(rvalue, "high"))
1907 route->pref = SD_NDISC_PREFERENCE_HIGH;
1908 else
1909 return log_syntax_parse_error(unit, filename, line, 0, lvalue, rvalue);
1910
1911 route->pref_set = true;
1912 return 1;
1913}
1914
1915static int config_parse_route_protocol(
1916 const char *unit,
1917 const char *filename,
1918 unsigned line,
1919 const char *section,
1920 unsigned section_line,
1921 const char *lvalue,
1922 int ltype,
1923 const char *rvalue,
1924 void *data,
1925 void *userdata) {
1926
1927 unsigned char *p = ASSERT_PTR(data);
1928 int r;
1929
1930 assert(rvalue);
1931
1932 r = route_protocol_from_string(rvalue);
1933 if (r < 0)
1934 return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
1935
1936 *p = (unsigned char) r;
1937 return 1;
1938}
1939
1940static int config_parse_route_type(
1941 const char *unit,
1942 const char *filename,
1943 unsigned line,
1944 const char *section,
1945 unsigned section_line,
1946 const char *lvalue,
1947 int ltype,
1948 const char *rvalue,
1949 void *data,
1950 void *userdata) {
1951
1952 unsigned char *p = ASSERT_PTR(data);
1953 int r;
1954
1955 assert(rvalue);
1956
1957 r = route_type_from_string(rvalue);
1958 if (r < 0)
1959 return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
1960
1961 *p = (unsigned char) r;
1962 return 1;
1963}
1964
1965int config_parse_route_section(
1966 const char *unit,
1967 const char *filename,
1968 unsigned line,
1969 const char *section,
1970 unsigned section_line,
1971 const char *lvalue,
1972 int ltype,
1973 const char *rvalue,
1974 void *data,
1975 void *userdata) {
1976
1977 static const ConfigSectionParser table[_ROUTE_CONF_PARSER_MAX] = {
1978 [ROUTE_DESTINATION] = { .parser = config_parse_route_destination, .ltype = 0, .offset = 0, },
1979 [ROUTE_PREFERRED_SOURCE] = { .parser = config_parse_preferred_src, .ltype = 0, .offset = 0, },
1980 [ROUTE_PRIORITY] = { .parser = config_parse_route_priority, .ltype = 0, .offset = 0, },
1981 [ROUTE_SCOPE] = { .parser = config_parse_route_scope, .ltype = 0, .offset = 0, },
1982 [ROUTE_TABLE] = { .parser = config_parse_route_table, .ltype = 0, .offset = 0, },
1983 [ROUTE_PREFERENCE] = { .parser = config_parse_route_preference, .ltype = 0, .offset = 0, },
1984 [ROUTE_PROTOCOL] = { .parser = config_parse_route_protocol, .ltype = 0, .offset = offsetof(Route, protocol), },
1985 [ROUTE_TYPE] = { .parser = config_parse_route_type, .ltype = 0, .offset = offsetof(Route, type), },
1986 [ROUTE_GATEWAY_NETWORK] = { .parser = config_parse_gateway, .ltype = 0, .offset = 0, },
1987 [ROUTE_GATEWAY] = { .parser = config_parse_gateway, .ltype = 1, .offset = 0, },
1988 [ROUTE_GATEWAY_ONLINK] = { .parser = config_parse_tristate, .ltype = 0, .offset = offsetof(Route, gateway_onlink), },
1989 [ROUTE_MULTIPATH] = { .parser = config_parse_multipath_route, .ltype = 0, .offset = offsetof(Route, nexthops), },
1990 [ROUTE_NEXTHOP] = { .parser = config_parse_route_nexthop, .ltype = 0, .offset = offsetof(Route, nexthop_id), },
1991 [ROUTE_METRIC_MTU] = { .parser = config_parse_route_metric, .ltype = RTAX_MTU, .offset = 0, },
1992 [ROUTE_METRIC_ADVMSS] = { .parser = config_parse_route_metric, .ltype = RTAX_ADVMSS, .offset = 0, },
1993 [ROUTE_METRIC_HOPLIMIT] = { .parser = config_parse_route_metric, .ltype = RTAX_HOPLIMIT, .offset = 0, },
1994 [ROUTE_METRIC_INITCWND] = { .parser = config_parse_route_metric, .ltype = RTAX_INITCWND, .offset = 0, },
1995 [ROUTE_METRIC_RTO_MIN] = { .parser = config_parse_route_metric, .ltype = RTAX_RTO_MIN, .offset = 0, },
1996 [ROUTE_METRIC_INITRWND] = { .parser = config_parse_route_metric, .ltype = RTAX_INITRWND, .offset = 0, },
1997 [ROUTE_METRIC_QUICKACK] = { .parser = config_parse_route_metric, .ltype = RTAX_QUICKACK, .offset = 0, },
1998 [ROUTE_METRIC_CC_ALGO] = { .parser = config_parse_string, .ltype = 0, .offset = offsetof(Route, metric.tcp_congestion_control_algo), },
1999 [ROUTE_METRIC_FASTOPEN_NO_COOKIE] = { .parser = config_parse_route_metric, .ltype = RTAX_FASTOPEN_NO_COOKIE, .offset = 0, },
2000 };
2001
2002 _cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
2003 Network *network = ASSERT_PTR(userdata);
2004 int r;
2005
2006 assert(filename);
2007
2008 if (streq(section, "Network")) {
2009 assert(streq_ptr(lvalue, "Gateway"));
2010
2011 /* we are not in an Route section, so use line number instead */
2012 r = route_new_static(network, filename, line, &route);
2013 } else
2014 r = route_new_static(network, filename, section_line, &route);
2015 if (r == -ENOMEM)
2016 return log_oom();
2017 if (r < 0) {
2018 log_syntax(unit, LOG_WARNING, filename, line, r,
2019 "Failed to allocate route, ignoring assignment: %m");
2020 return 0;
2021 }
2022
2023 r = config_section_parse(table, ELEMENTSOF(table),
2024 unit, filename, line, section, section_line, lvalue, ltype, rvalue, route);
2025 if (r <= 0)
2026 return r;
2027
2028 TAKE_PTR(route);
2029 return 0;
2030}
2031
2032int route_section_verify(Route *route) {
2033 int r;
2034
2035 assert(route);
2036 assert(route->section);
2037
2038 if (section_is_invalid(route->section))
2039 return -EINVAL;
2040
2041 /* Currently, we do not support static route with finite lifetime. */
2042 assert(route->lifetime_usec == USEC_INFINITY);
2043
2044 r = route_section_verify_nexthops(route);
2045 if (r < 0)
2046 return r;
2047
2048 /* table */
2049 if (!route->table_set && route->network && route->network->vrf) {
2050 route->table = VRF(route->network->vrf)->table;
2051 route->table_set = true;
2052 }
2053
2054 if (!route->table_set && IN_SET(route->type, RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, RTN_NAT))
2055 route->table = RT_TABLE_LOCAL;
2056
2057 /* scope */
2058 if (!route->scope_set && route->family == AF_INET) {
2059 if (IN_SET(route->type, RTN_LOCAL, RTN_NAT))
2060 route->scope = RT_SCOPE_HOST;
2061 else if (IN_SET(route->type, RTN_BROADCAST, RTN_ANYCAST, RTN_MULTICAST))
2062 route->scope = RT_SCOPE_LINK;
2063 else if (IN_SET(route->type, RTN_UNICAST, RTN_UNSPEC) &&
2064 !route->gateway_from_dhcp_or_ra &&
2065 !in_addr_is_set(route->nexthop.family, &route->nexthop.gw) &&
2066 ordered_set_isempty(route->nexthops) &&
2067 route->nexthop_id == 0)
2068 route->scope = RT_SCOPE_LINK;
2069 }
2070
2071 /* IPv6 route */
2072 if (route->family == AF_INET6) {
2073 if (route->scope != RT_SCOPE_UNIVERSE) {
2074 log_section_warning(route->section, "Scope= is specified for IPv6 route. It will be ignored.");
2075 route->scope = RT_SCOPE_UNIVERSE;
2076 }
2077
2078 if (route->priority == 0)
2079 route->priority = IP6_RT_PRIO_USER;
2080 }
2081
2082 return 0;
2083}
2084
2085void network_drop_invalid_routes(Network *network) {
2086 Route *route;
2087
2088 assert(network);
2089
2090 HASHMAP_FOREACH(route, network->routes_by_section)
2091 if (route_section_verify(route) < 0)
2092 route_detach(route);
2093}