1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <linux/icmpv6.h>
4 #include <linux/ipv6_route.h>
5 #include <linux/nexthop.h>
7 #include "alloc-util.h"
8 #include "event-util.h"
9 #include "netlink-util.h"
10 #include "networkd-address.h"
11 #include "networkd-ipv4ll.h"
12 #include "networkd-manager.h"
13 #include "networkd-network.h"
14 #include "networkd-nexthop.h"
15 #include "networkd-queue.h"
16 #include "networkd-route-util.h"
17 #include "networkd-route.h"
18 #include "parse-util.h"
19 #include "string-util.h"
22 #include "wireguard.h"
24 static Route
* route_detach_impl(Route
*route
) {
26 assert(!!route
->network
+ !!route
->manager
+ !!route
->wireguard
<= 1);
29 assert(route
->section
);
30 hashmap_remove(route
->network
->routes_by_section
, route
->section
);
31 route
->network
= NULL
;
36 route_detach_from_nexthop(route
);
37 set_remove(route
->manager
->routes
, route
);
38 route
->manager
= NULL
;
42 if (route
->wireguard
) {
43 set_remove(route
->wireguard
->routes
, route
);
44 route
->wireguard
= NULL
;
51 static void route_detach(Route
*route
) {
52 route_unref(route_detach_impl(route
));
55 static Route
* route_free(Route
*route
) {
59 route_detach_impl(route
);
61 config_section_free(route
->section
);
62 route_nexthops_done(route
);
63 route_metric_done(&route
->metric
);
64 sd_event_source_disable_unref(route
->expire
);
69 DEFINE_TRIVIAL_REF_UNREF_FUNC(Route
, route
, route_free
);
71 static void route_hash_func(const Route
*route
, struct siphash
*state
) {
74 siphash24_compress_typesafe(route
->family
, state
);
76 switch (route
->family
) {
78 /* First, the table, destination prefix, priority, and tos (dscp), are used to find routes.
79 * See fib_table_insert(), fib_find_node(), and fib_find_alias() in net/ipv4/fib_trie.c of the kernel. */
80 siphash24_compress_typesafe(route
->table
, state
);
81 in_addr_hash_func(&route
->dst
, route
->family
, state
);
82 siphash24_compress_typesafe(route
->dst_prefixlen
, state
);
83 siphash24_compress_typesafe(route
->priority
, state
);
84 siphash24_compress_typesafe(route
->tos
, state
);
86 /* Then, protocol, scope, type, flags, prefsrc, metrics (RTAX_* attributes), and nexthops (gateways)
87 * are used to find routes. See fib_find_info() in net/ipv4/fib_semantics.c of the kernel. */
88 siphash24_compress_typesafe(route
->protocol
, state
);
89 siphash24_compress_typesafe(route
->scope
, state
);
90 siphash24_compress_typesafe(route
->type
, state
);
91 unsigned flags
= route
->flags
& ~RTNH_COMPARE_MASK
;
92 siphash24_compress_typesafe(flags
, state
);
93 in_addr_hash_func(&route
->prefsrc
, route
->family
, state
);
95 /* nexthops (id, number of nexthops, nexthop) */
96 route_nexthops_hash_func(route
, state
);
99 route_metric_hash_func(&route
->metric
, state
);
103 /* First, table and destination prefix are used for classifying routes.
104 * See fib6_add() and fib6_add_1() in net/ipv6/ip6_fib.c of the kernel. */
105 siphash24_compress_typesafe(route
->table
, state
);
106 in_addr_hash_func(&route
->dst
, route
->family
, state
);
107 siphash24_compress_typesafe(route
->dst_prefixlen
, state
);
109 /* Then, source prefix is used. See fib6_add(). */
110 in_addr_hash_func(&route
->src
, route
->family
, state
);
111 siphash24_compress_typesafe(route
->src_prefixlen
, state
);
113 /* See fib6_add_rt2node(). */
114 siphash24_compress_typesafe(route
->priority
, state
);
116 /* See rt6_duplicate_nexthop() in include/net/ip6_route.h of the kernel.
117 * Here, we hash nexthop in a similar way as the one for IPv4. */
118 route_nexthops_hash_func(route
, state
);
120 /* Unlike IPv4 routes, metrics are not taken into account. */
124 /* treat any other address family as AF_UNSPEC */
129 static int route_compare_func(const Route
*a
, const Route
*b
) {
132 r
= CMP(a
->family
, b
->family
);
138 r
= CMP(a
->table
, b
->table
);
142 r
= memcmp(&a
->dst
, &b
->dst
, FAMILY_ADDRESS_SIZE(a
->family
));
146 r
= CMP(a
->dst_prefixlen
, b
->dst_prefixlen
);
150 r
= CMP(a
->priority
, b
->priority
);
154 r
= CMP(a
->tos
, b
->tos
);
158 r
= CMP(a
->protocol
, b
->protocol
);
162 r
= CMP(a
->scope
, b
->scope
);
166 r
= CMP(a
->type
, b
->type
);
170 r
= CMP(a
->flags
& ~RTNH_COMPARE_MASK
, b
->flags
& ~RTNH_COMPARE_MASK
);
174 r
= memcmp(&a
->prefsrc
, &b
->prefsrc
, FAMILY_ADDRESS_SIZE(a
->family
));
178 r
= route_nexthops_compare_func(a
, b
);
182 return route_metric_compare_func(&a
->metric
, &b
->metric
);
185 r
= CMP(a
->table
, b
->table
);
189 r
= memcmp(&a
->dst
, &b
->dst
, FAMILY_ADDRESS_SIZE(a
->family
));
193 r
= CMP(a
->dst_prefixlen
, b
->dst_prefixlen
);
197 r
= memcmp(&a
->src
, &b
->src
, FAMILY_ADDRESS_SIZE(a
->family
));
201 r
= CMP(a
->src_prefixlen
, b
->src_prefixlen
);
205 r
= CMP(a
->priority
, b
->priority
);
209 return route_nexthops_compare_func(a
, b
);
212 /* treat any other address family as AF_UNSPEC */
217 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
224 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
225 route_hash_ops_unref
,
231 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
232 route_section_hash_ops
,
234 config_section_hash_func
,
235 config_section_compare_func
,
239 int route_new(Route
**ret
) {
240 _cleanup_(route_unrefp
) Route
*route
= NULL
;
242 route
= new(Route
, 1);
249 .scope
= RT_SCOPE_UNIVERSE
,
250 .protocol
= RTPROT_UNSPEC
,
252 .table
= RT_TABLE_MAIN
,
253 .lifetime_usec
= USEC_INFINITY
,
254 .gateway_onlink
= -1,
257 *ret
= TAKE_PTR(route
);
262 int route_new_static(Network
*network
, const char *filename
, unsigned section_line
, Route
**ret
) {
263 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
264 _cleanup_(route_unrefp
) Route
*route
= NULL
;
270 assert(section_line
> 0);
272 r
= config_section_new(filename
, section_line
, &n
);
276 route
= hashmap_get(network
->routes_by_section
, n
);
278 *ret
= TAKE_PTR(route
);
282 if (hashmap_size(network
->routes_by_section
) >= routes_max())
285 r
= route_new(&route
);
289 route
->protocol
= RTPROT_STATIC
;
290 route
->network
= network
;
291 route
->section
= TAKE_PTR(n
);
292 route
->source
= NETWORK_CONFIG_SOURCE_STATIC
;
294 r
= hashmap_ensure_put(&network
->routes_by_section
, &route_section_hash_ops
, route
->section
, route
);
298 *ret
= TAKE_PTR(route
);
302 static int route_attach(Manager
*manager
, Route
*route
) {
307 assert(!route
->network
);
308 assert(!route
->wireguard
);
310 r
= set_ensure_put(&manager
->routes
, &route_hash_ops
, route
);
316 route
->manager
= manager
;
320 int route_get(Manager
*manager
, const Route
*route
, Route
**ret
) {
326 existing
= set_get(manager
->routes
, route
);
336 static int route_get_link(Manager
*manager
, const Route
*route
, Link
**ret
) {
342 if (route
->nexthop_id
!= 0) {
345 r
= nexthop_get_by_id(manager
, route
->nexthop_id
, &nh
);
349 return link_get_by_index(manager
, nh
->ifindex
, ret
);
352 return route_nexthop_get_link(manager
, &route
->nexthop
, ret
);
355 int route_get_request(Manager
*manager
, const Route
*route
, Request
**ret
) {
361 req
= ordered_set_get(manager
->request_queue
,
363 .type
= REQUEST_TYPE_ROUTE
,
364 .userdata
= (void*) route
,
365 .hash_func
= (hash_func_t
) route_hash_func
,
366 .compare_func
= (compare_func_t
) route_compare_func
,
376 int route_dup(const Route
*src
, const RouteNextHop
*nh
, Route
**ret
) {
377 _cleanup_(route_unrefp
) Route
*dest
= NULL
;
383 dest
= newdup(Route
, src
, 1);
387 /* Unset number of reference and all pointers */
389 dest
->manager
= NULL
;
390 dest
->network
= NULL
;
391 dest
->wireguard
= NULL
;
392 dest
->section
= NULL
;
393 dest
->nexthop
= ROUTE_NEXTHOP_NULL
;
394 dest
->nexthops
= NULL
;
395 dest
->metric
= ROUTE_METRIC_NULL
;
398 r
= route_nexthops_copy(src
, nh
, dest
);
402 r
= route_metric_copy(&src
->metric
, &dest
->metric
);
406 *ret
= TAKE_PTR(dest
);
410 static void log_route_debug(const Route
*route
, const char *str
, Manager
*manager
) {
411 _cleanup_free_
char *state
= NULL
, *nexthop
= NULL
, *prefsrc
= NULL
,
412 *table
= NULL
, *scope
= NULL
, *proto
= NULL
, *flags
= NULL
;
413 const char *dst
, *src
;
423 (void) route_get_link(manager
, route
, &link
);
425 (void) network_config_state_to_string_alloc(route
->state
, &state
);
427 dst
= in_addr_is_set(route
->family
, &route
->dst
) || route
->dst_prefixlen
> 0 ?
428 IN_ADDR_PREFIX_TO_STRING(route
->family
, &route
->dst
, route
->dst_prefixlen
) : NULL
;
429 src
= in_addr_is_set(route
->family
, &route
->src
) || route
->src_prefixlen
> 0 ?
430 IN_ADDR_PREFIX_TO_STRING(route
->family
, &route
->src
, route
->src_prefixlen
) : NULL
;
432 (void) route_nexthops_to_string(route
, &nexthop
);
434 if (in_addr_is_set(route
->family
, &route
->prefsrc
))
435 (void) in_addr_to_string(route
->family
, &route
->prefsrc
, &prefsrc
);
436 (void) route_scope_to_string_alloc(route
->scope
, &scope
);
437 (void) manager_get_route_table_to_string(manager
, route
->table
, /* append_num = */ true, &table
);
438 (void) route_protocol_full_to_string_alloc(route
->protocol
, &proto
);
439 (void) route_flags_to_string_alloc(route
->flags
, &flags
);
442 "%s %s route (%s): dst: %s, src: %s, %s, prefsrc: %s, "
443 "table: %s, priority: %"PRIu32
", "
444 "proto: %s, scope: %s, type: %s, flags: %s",
445 str
, strna(network_config_source_to_string(route
->source
)), strna(state
),
446 strna(dst
), strna(src
), strna(nexthop
), strna(prefsrc
),
447 strna(table
), route
->priority
,
448 strna(proto
), strna(scope
), strna(route_type_to_string(route
->type
)), strna(flags
));
451 static int route_set_netlink_message(const Route
*route
, sd_netlink_message
*m
) {
457 /* rtmsg header (and relevant attributes) */
458 if (route
->dst_prefixlen
> 0) {
459 r
= netlink_message_append_in_addr_union(m
, RTA_DST
, route
->family
, &route
->dst
);
463 r
= sd_rtnl_message_route_set_dst_prefixlen(m
, route
->dst_prefixlen
);
468 if (route
->src_prefixlen
> 0) {
469 r
= netlink_message_append_in_addr_union(m
, RTA_SRC
, route
->family
, &route
->src
);
473 r
= sd_rtnl_message_route_set_src_prefixlen(m
, route
->src_prefixlen
);
478 r
= sd_rtnl_message_route_set_tos(m
, route
->tos
);
482 r
= sd_rtnl_message_route_set_scope(m
, route
->scope
);
486 r
= sd_rtnl_message_route_set_type(m
, route
->type
);
490 r
= sd_rtnl_message_route_set_flags(m
, route
->flags
& ~RTNH_COMPARE_MASK
);
495 r
= sd_netlink_message_append_u32(m
, RTA_PRIORITY
, route
->priority
);
499 if (in_addr_is_set(route
->family
, &route
->prefsrc
)) {
500 r
= netlink_message_append_in_addr_union(m
, RTA_PREFSRC
, route
->family
, &route
->prefsrc
);
505 if (route
->table
< 256) {
506 r
= sd_rtnl_message_route_set_table(m
, route
->table
);
510 r
= sd_rtnl_message_route_set_table(m
, RT_TABLE_UNSPEC
);
514 /* Table attribute to allow more than 256. */
515 r
= sd_netlink_message_append_u32(m
, RTA_TABLE
, route
->table
);
520 r
= sd_netlink_message_append_u8(m
, RTA_PREF
, route
->pref
);
525 r
= route_nexthops_set_netlink_message(route
, m
);
530 r
= route_metric_set_netlink_message(&route
->metric
, m
);
537 static int route_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, RemoveRequest
*rreq
) {
543 Manager
*manager
= ASSERT_PTR(rreq
->manager
);
544 Route
*route
= ASSERT_PTR(rreq
->userdata
);
546 r
= sd_netlink_message_get_errno(m
);
548 log_message_full_errno(m
,
549 (r
== -ESRCH
|| /* the route is already removed? */
550 (r
== -EINVAL
&& route
->nexthop_id
!= 0) || /* The nexthop is already removed? */
551 !route
->manager
) ? /* already detached? */
552 LOG_DEBUG
: LOG_WARNING
,
553 r
, "Could not drop route, ignoring");
555 if (route
->manager
) {
556 /* If the route cannot be removed, then assume the route is already removed. */
557 log_route_debug(route
, "Forgetting", manager
);
560 if (route_get_request(manager
, route
, &req
) >= 0)
561 route_enter_removed(req
->userdata
);
570 int route_remove(Route
*route
, Manager
*manager
) {
571 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
578 /* If the route is remembered, then use the remembered object. */
579 (void) route_get(manager
, route
, &route
);
581 log_route_debug(route
, "Removing", manager
);
584 (void) route_get_link(manager
, route
, &link
);
586 r
= sd_rtnl_message_new_route(manager
->rtnl
, &m
, RTM_DELROUTE
, route
->family
, route
->protocol
);
588 return log_link_warning_errno(link
, r
, "Could not create netlink message: %m");
590 r
= route_set_netlink_message(route
, m
);
592 return log_link_warning_errno(link
, r
, "Could not fill netlink message: %m");
594 r
= manager_remove_request_add(manager
, route
, route
, manager
->rtnl
, m
, route_remove_handler
);
596 return log_link_warning_errno(link
, r
, "Could not queue rtnetlink message: %m");
598 route_enter_removing(route
);
602 int route_remove_and_cancel(Route
*route
, Manager
*manager
) {
603 _cleanup_(request_unrefp
) Request
*req
= NULL
;
604 bool waiting
= false;
609 /* If the route is remembered by the manager, then use the remembered object. */
610 (void) route_get(manager
, route
, &route
);
612 /* Cancel the request for the route. If the request is already called but we have not received the
613 * notification about the request, then explicitly remove the route. */
614 if (route_get_request(manager
, route
, &req
) >= 0) {
615 request_ref(req
); /* avoid the request freed by request_detach() */
616 waiting
= req
->waiting_reply
;
618 route_cancel_requesting(route
);
621 /* If we know that the route will come or already exists, remove it. */
622 if (waiting
|| (route
->manager
&& route_exists(route
)))
623 return route_remove(route
, manager
);
628 static int route_expire_handler(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
629 Route
*route
= ASSERT_PTR(userdata
);
633 return 0; /* already detached. */
635 r
= route_remove(route
, route
->manager
);
638 (void) route_get_link(route
->manager
, route
, &link
);
639 log_link_warning_errno(link
, r
, "Could not remove route: %m");
641 link_enter_failed(link
);
647 static int route_setup_timer(Route
*route
, const struct rta_cacheinfo
*cacheinfo
) {
652 if (cacheinfo
&& cacheinfo
->rta_expires
!= 0)
653 route
->expiration_managed_by_kernel
= true;
655 if (route
->lifetime_usec
== USEC_INFINITY
|| /* We do not request expiration for the route. */
656 route
->expiration_managed_by_kernel
) { /* We have received nonzero expiration previously. The expiration is managed by the kernel. */
657 route
->expire
= sd_event_source_disable_unref(route
->expire
);
661 Manager
*manager
= ASSERT_PTR(route
->manager
);
662 r
= event_reset_time(manager
->event
, &route
->expire
, CLOCK_BOOTTIME
,
663 route
->lifetime_usec
, 0, route_expire_handler
, route
, 0, "route-expiration", true);
666 (void) route_get_link(manager
, route
, &link
);
667 return log_link_warning_errno(link
, r
, "Failed to configure expiration timer for route, ignoring: %m");
670 log_route_debug(route
, "Configured expiration timer for", manager
);
674 int route_configure_handler_internal(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
, Route
*route
, const char *error_msg
) {
679 assert(link
->manager
);
683 r
= sd_netlink_message_get_errno(m
);
687 if (route_get(link
->manager
, route
, &existing
) >= 0) {
688 /* When re-configuring an existing route, kernel does not send RTM_NEWROUTE
689 * notification, so we need to update the timer here. */
690 existing
->lifetime_usec
= route
->lifetime_usec
;
691 (void) route_setup_timer(existing
, NULL
);
693 /* This may be a bug in the kernel, but the MTU of an IPv6 route can be updated only
694 * when the route has an expiration timer managed by the kernel (not by us).
695 * See fib6_add_rt2node() in net/ipv6/ip6_fib.c of the kernel. */
696 if (existing
->family
== AF_INET6
&&
697 existing
->expiration_managed_by_kernel
) {
698 r
= route_metric_set(&existing
->metric
, RTAX_MTU
, route_metric_get(&route
->metric
, RTAX_MTU
));
701 link_enter_failed(link
);
708 log_link_message_warning_errno(link
, m
, r
, error_msg
);
709 link_enter_failed(link
);
716 static int route_configure(const Route
*route
, uint32_t lifetime_sec
, Link
*link
, Request
*req
) {
717 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
722 assert(link
->manager
);
725 log_route_debug(route
, "Configuring", link
->manager
);
727 r
= sd_rtnl_message_new_route(link
->manager
->rtnl
, &m
, RTM_NEWROUTE
, route
->family
, route
->protocol
);
731 r
= route_set_netlink_message(route
, m
);
735 if (lifetime_sec
!= UINT32_MAX
) {
736 r
= sd_netlink_message_append_u32(m
, RTA_EXPIRES
, lifetime_sec
);
741 return request_call_netlink_async(link
->manager
->rtnl
, m
, req
);
744 static int route_requeue_request(Request
*req
, Link
*link
, const Route
*route
) {
745 _unused_
_cleanup_(request_unrefp
) Request
*req_unref
= NULL
;
746 _cleanup_(route_unrefp
) Route
*tmp
= NULL
;
751 assert(link
->manager
);
754 /* It is not possible to adjust the Route object owned by Request, as it is used as a key to manage
755 * Request objects in the queue. Hence, we need to re-request with the updated Route object. */
757 if (!route_nexthops_needs_adjust(route
))
758 return 0; /* The Route object does not need the adjustment. Continue with it. */
760 r
= route_dup(route
, NULL
, &tmp
);
764 r
= route_adjust_nexthops(tmp
, link
);
768 if (route_compare_func(route
, tmp
) == 0 && route
->type
== tmp
->type
)
769 return 0; /* No effective change?? That's OK. */
771 /* Avoid the request to be freed by request_detach(). */
772 req_unref
= request_ref(req
);
774 /* Detach the request from the queue, to make not the new request is deduped.
775 * Why this is necessary? IPv6 routes with different type may be handled as the same,
776 * As commented in route_adjust_nexthops(), we need to configure the adjusted type,
777 * otherwise we cannot remove the route on reconfigure or so. If we request the new Route object
778 * without detaching the current request, the new request is deduped, and the route is configured
779 * with unmodified type. */
782 /* Request the route with the adjusted Route object combined with the same other parameters. */
783 r
= link_requeue_request(link
, req
, tmp
, NULL
);
787 return 1; /* Already queued?? That's OK. Maybe, [Route] section is effectively duplicated. */
790 return 1; /* New request is queued. Finish to process this request. */
793 static int route_is_ready_to_configure(const Route
*route
, Link
*link
) {
799 if (!link_is_ready_to_configure(link
, /* allow_unmanaged = */ false))
802 if (in_addr_is_set(route
->family
, &route
->prefsrc
) > 0) {
803 r
= manager_has_address(link
->manager
, route
->family
, &route
->prefsrc
);
808 return route_nexthops_is_ready_to_configure(route
, link
->manager
);
811 static int route_process_request(Request
*req
, Link
*link
, Route
*route
) {
817 assert(link
->manager
);
820 r
= route_is_ready_to_configure(route
, link
);
822 return log_link_warning_errno(link
, r
, "Failed to check if route is ready to configure: %m");
827 assert_se(sd_event_now(link
->manager
->event
, CLOCK_BOOTTIME
, &now_usec
) >= 0);
828 uint32_t sec
= usec_to_sec(route
->lifetime_usec
, now_usec
);
830 log_link_debug(link
, "Refuse to configure %s route with zero lifetime.",
831 network_config_source_to_string(route
->source
));
833 route_cancel_requesting(route
);
834 if (route_get(link
->manager
, route
, &existing
) >= 0)
835 route_cancel_requesting(existing
);
839 r
= route_requeue_request(req
, link
, route
);
843 r
= route_configure(route
, sec
, link
, req
);
845 return log_link_warning_errno(link
, r
, "Failed to configure route: %m");
847 route_enter_configuring(route
);
848 if (route_get(link
->manager
, route
, &existing
) >= 0)
849 route_enter_configuring(existing
);
853 static int link_request_route_one(
856 const RouteNextHop
*nh
,
857 unsigned *message_counter
,
858 route_netlink_handler_t netlink_handler
) {
860 _cleanup_(route_unrefp
) Route
*tmp
= NULL
;
861 Route
*existing
= NULL
;
865 assert(link
->manager
);
868 r
= route_dup(route
, nh
, &tmp
);
872 r
= route_adjust_nexthops(tmp
, link
);
876 if (route_get(link
->manager
, tmp
, &existing
) >= 0)
877 /* Copy state for logging below. */
878 tmp
->state
= existing
->state
;
880 log_route_debug(tmp
, "Requesting", link
->manager
);
881 r
= link_queue_request_safe(link
, REQUEST_TYPE_ROUTE
,
886 route_process_request
,
893 route_enter_requesting(tmp
);
895 route_enter_requesting(existing
);
901 int link_request_route(
904 unsigned *message_counter
,
905 route_netlink_handler_t netlink_handler
) {
910 assert(link
->manager
);
912 assert(route
->source
!= NETWORK_CONFIG_SOURCE_FOREIGN
);
914 if (route
->family
== AF_INET
|| route_type_is_reject(route
) || ordered_set_isempty(route
->nexthops
))
915 return link_request_route_one(link
, route
, NULL
, message_counter
, netlink_handler
);
918 ORDERED_SET_FOREACH(nh
, route
->nexthops
) {
919 r
= link_request_route_one(link
, route
, nh
, message_counter
, netlink_handler
);
927 static int static_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Request
*req
, Link
*link
, Route
*route
) {
932 r
= route_configure_handler_internal(rtnl
, m
, link
, route
, "Could not set route");
936 if (link
->static_route_messages
== 0) {
937 log_link_debug(link
, "Routes set");
938 link
->static_routes_configured
= true;
939 link_check_ready(link
);
945 static int link_request_wireguard_routes(Link
*link
, bool only_ipv4
) {
952 if (!streq_ptr(link
->kind
, "wireguard"))
955 if (netdev_get(link
->manager
, link
->ifname
, &netdev
) < 0)
958 Wireguard
*w
= WIREGUARD(netdev
);
960 SET_FOREACH(route
, w
->routes
) {
961 if (only_ipv4
&& route
->family
!= AF_INET
)
964 r
= link_request_route(link
, route
, &link
->static_route_messages
, static_route_handler
);
972 int link_request_static_routes(Link
*link
, bool only_ipv4
) {
977 assert(link
->network
);
979 link
->static_routes_configured
= false;
981 HASHMAP_FOREACH(route
, link
->network
->routes_by_section
) {
982 if (route
->gateway_from_dhcp_or_ra
)
985 if (only_ipv4
&& route
->family
!= AF_INET
)
988 r
= link_request_route(link
, route
, &link
->static_route_messages
, static_route_handler
);
993 r
= link_request_wireguard_routes(link
, only_ipv4
);
997 if (link
->static_route_messages
== 0) {
998 link
->static_routes_configured
= true;
999 link_check_ready(link
);
1001 log_link_debug(link
, "Requesting routes");
1002 link_set_state(link
, LINK_STATE_CONFIGURING
);
1008 static int process_route_one(
1012 const struct rta_cacheinfo
*cacheinfo
) {
1014 Request
*req
= NULL
;
1015 Route
*route
= NULL
;
1017 bool is_new
= false, update_dhcp4
;
1022 assert(IN_SET(type
, RTM_NEWROUTE
, RTM_DELROUTE
));
1024 (void) route_get(manager
, tmp
, &route
);
1025 (void) route_get_request(manager
, tmp
, &req
);
1026 (void) route_get_link(manager
, tmp
, &link
);
1028 update_dhcp4
= link
&& tmp
->family
== AF_INET6
&& tmp
->dst_prefixlen
== 0;
1033 if (!manager
->manage_foreign_routes
&& !(req
&& req
->waiting_reply
)) {
1034 route_enter_configured(tmp
);
1035 log_route_debug(tmp
, "Ignoring received", manager
);
1039 /* If we do not know the route, then save it. */
1040 r
= route_attach(manager
, tmp
);
1042 log_link_warning_errno(link
, r
, "Failed to remember foreign route, ignoring: %m");
1046 route
= route_ref(tmp
);
1050 /* Update remembered route with the received notification. */
1051 route
->nexthop
.weight
= tmp
->nexthop
.weight
;
1053 /* Also update information that cannot be obtained through netlink notification. */
1054 if (req
&& req
->waiting_reply
) {
1055 Route
*rt
= ASSERT_PTR(req
->userdata
);
1057 route
->source
= rt
->source
;
1058 route
->provider
= rt
->provider
;
1059 route
->lifetime_usec
= rt
->lifetime_usec
;
1062 route_enter_configured(route
);
1063 log_route_debug(route
, is_new
? "Received new" : "Received remembered", manager
);
1065 (void) route_setup_timer(route
, cacheinfo
);
1071 route_enter_removed(route
);
1072 log_route_debug(route
, "Forgetting removed", manager
);
1073 route_detach(route
);
1075 log_route_debug(tmp
,
1076 manager
->manage_foreign_routes
? "Kernel removed unknown" : "Ignoring received",
1080 route_enter_removed(req
->userdata
);
1085 assert_not_reached();
1089 r
= dhcp4_update_ipv6_connectivity(link
);
1091 log_link_warning_errno(link
, r
, "Failed to notify IPv6 connectivity to DHCPv4 client: %m");
1092 link_enter_failed(link
);
1099 int manager_rtnl_process_route(sd_netlink
*rtnl
, sd_netlink_message
*message
, Manager
*m
) {
1100 _cleanup_(route_unrefp
) Route
*tmp
= NULL
;
1107 if (sd_netlink_message_is_error(message
)) {
1108 r
= sd_netlink_message_get_errno(message
);
1110 log_message_warning_errno(message
, r
, "rtnl: failed to receive route message, ignoring");
1116 r
= sd_netlink_message_get_type(message
, &type
);
1118 log_warning_errno(r
, "rtnl: could not get message type, ignoring: %m");
1120 } else if (!IN_SET(type
, RTM_NEWROUTE
, RTM_DELROUTE
)) {
1121 log_warning("rtnl: received unexpected message type %u when processing route, ignoring.", type
);
1125 r
= route_new(&tmp
);
1130 r
= sd_rtnl_message_route_get_family(message
, &tmp
->family
);
1132 log_warning_errno(r
, "rtnl: received route message without family, ignoring: %m");
1134 } else if (!IN_SET(tmp
->family
, AF_INET
, AF_INET6
)) {
1135 log_debug("rtnl: received route message with invalid family '%i', ignoring.", tmp
->family
);
1139 r
= sd_rtnl_message_route_get_dst_prefixlen(message
, &tmp
->dst_prefixlen
);
1141 log_warning_errno(r
, "rtnl: received route message with invalid destination prefixlen, ignoring: %m");
1145 r
= sd_rtnl_message_route_get_src_prefixlen(message
, &tmp
->src_prefixlen
);
1147 log_warning_errno(r
, "rtnl: received route message with invalid source prefixlen, ignoring: %m");
1151 r
= sd_rtnl_message_route_get_tos(message
, &tmp
->tos
);
1153 log_warning_errno(r
, "rtnl: received route message with invalid tos, ignoring: %m");
1157 r
= sd_rtnl_message_route_get_protocol(message
, &tmp
->protocol
);
1159 log_warning_errno(r
, "rtnl: received route message without route protocol, ignoring: %m");
1163 r
= sd_rtnl_message_route_get_scope(message
, &tmp
->scope
);
1165 log_warning_errno(r
, "rtnl: received route message with invalid scope, ignoring: %m");
1169 r
= sd_rtnl_message_route_get_type(message
, &tmp
->type
);
1171 log_warning_errno(r
, "rtnl: received route message with invalid type, ignoring: %m");
1175 r
= sd_rtnl_message_route_get_flags(message
, &tmp
->flags
);
1177 log_warning_errno(r
, "rtnl: received route message without route flags, ignoring: %m");
1182 r
= netlink_message_read_in_addr_union(message
, RTA_DST
, tmp
->family
, &tmp
->dst
);
1183 if (r
< 0 && r
!= -ENODATA
) {
1184 log_warning_errno(r
, "rtnl: received route message without valid destination, ignoring: %m");
1188 r
= netlink_message_read_in_addr_union(message
, RTA_SRC
, tmp
->family
, &tmp
->src
);
1189 if (r
< 0 && r
!= -ENODATA
) {
1190 log_warning_errno(r
, "rtnl: received route message without valid source, ignoring: %m");
1194 r
= sd_netlink_message_read_u32(message
, RTA_PRIORITY
, &tmp
->priority
);
1195 if (r
< 0 && r
!= -ENODATA
) {
1196 log_warning_errno(r
, "rtnl: received route message with invalid priority, ignoring: %m");
1200 r
= netlink_message_read_in_addr_union(message
, RTA_PREFSRC
, tmp
->family
, &tmp
->prefsrc
);
1201 if (r
< 0 && r
!= -ENODATA
) {
1202 log_warning_errno(r
, "rtnl: received route message without valid preferred source, ignoring: %m");
1206 r
= sd_netlink_message_read_u32(message
, RTA_TABLE
, &tmp
->table
);
1207 if (r
== -ENODATA
) {
1208 unsigned char table
;
1210 r
= sd_rtnl_message_route_get_table(message
, &table
);
1215 log_warning_errno(r
, "rtnl: received route message with invalid table, ignoring: %m");
1219 r
= sd_netlink_message_read_u8(message
, RTA_PREF
, &tmp
->pref
);
1220 if (r
< 0 && r
!= -ENODATA
) {
1221 log_warning_errno(r
, "rtnl: received route message with invalid preference, ignoring: %m");
1226 if (route_nexthops_read_netlink_message(tmp
, message
) < 0)
1230 if (route_metric_read_netlink_message(&tmp
->metric
, message
) < 0)
1234 struct rta_cacheinfo cacheinfo
;
1235 r
= sd_netlink_message_read(message
, RTA_CACHEINFO
, sizeof(cacheinfo
), &cacheinfo
);
1236 if (r
< 0 && r
!= -ENODATA
) {
1237 log_warning_errno(r
, "rtnl: failed to read RTA_CACHEINFO attribute, ignoring: %m");
1240 has_cacheinfo
= r
>= 0;
1242 if (tmp
->family
== AF_INET
|| ordered_set_isempty(tmp
->nexthops
))
1243 return process_route_one(m
, type
, tmp
, has_cacheinfo
? &cacheinfo
: NULL
);
1246 ORDERED_SET_FOREACH(nh
, tmp
->nexthops
) {
1247 _cleanup_(route_unrefp
) Route
*dup
= NULL
;
1249 r
= route_dup(tmp
, nh
, &dup
);
1253 r
= process_route_one(m
, type
, dup
, has_cacheinfo
? &cacheinfo
: NULL
);
1261 void manager_mark_routes(Manager
*manager
, Link
*link
, NetworkConfigSource source
) {
1266 SET_FOREACH(route
, manager
->routes
) {
1267 if (route
->source
!= source
)
1273 if (route_get_link(manager
, route
, &route_link
) < 0)
1275 if (route_link
!= link
)
1283 static bool route_by_kernel(const Route
*route
) {
1286 if (route
->protocol
== RTPROT_KERNEL
)
1289 /* The kernels older than a826b04303a40d52439aa141035fca5654ccaccd (v5.11) create the IPv6
1290 * multicast with RTPROT_BOOT. Do not touch it. */
1291 if (route
->protocol
== RTPROT_BOOT
&&
1292 route
->family
== AF_INET6
&&
1293 route
->dst_prefixlen
== 8 &&
1294 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 }}}))
1300 bool route_can_update(const Route
*existing
, const Route
*requesting
) {
1304 if (route_compare_func(existing
, requesting
) != 0)
1307 switch (existing
->family
) {
1309 if (existing
->nexthop
.weight
!= requesting
->nexthop
.weight
)
1314 if (existing
->protocol
!= requesting
->protocol
)
1316 if (existing
->type
!= requesting
->type
)
1318 if (existing
->flags
!= requesting
->flags
)
1320 if (!in6_addr_equal(&existing
->prefsrc
.in6
, &requesting
->prefsrc
.in6
))
1322 if (existing
->pref
!= requesting
->pref
)
1324 if (existing
->expiration_managed_by_kernel
&& requesting
->lifetime_usec
!= USEC_INFINITY
)
1325 return false; /* We cannot disable expiration timer in the kernel. */
1326 if (!route_metric_can_update(&existing
->metric
, &requesting
->metric
, existing
->expiration_managed_by_kernel
))
1328 if (existing
->nexthop
.weight
!= requesting
->nexthop
.weight
)
1333 assert_not_reached();
1337 static int link_unmark_route(Link
*link
, const Route
*route
, const RouteNextHop
*nh
) {
1338 _cleanup_(route_unrefp
) Route
*tmp
= NULL
;
1345 r
= route_dup(route
, nh
, &tmp
);
1349 r
= route_adjust_nexthops(tmp
, link
);
1353 if (route_get(link
->manager
, tmp
, &existing
) < 0)
1356 if (!route_can_update(existing
, tmp
))
1359 route_unmark(existing
);
1363 static int link_mark_routes(Link
*link
, bool foreign
) {
1369 assert(link
->manager
);
1371 /* First, mark all routes. */
1372 SET_FOREACH(route
, link
->manager
->routes
) {
1373 /* Do not touch routes managed by the kernel. */
1374 if (route_by_kernel(route
))
1377 /* When 'foreign' is true, mark only foreign routes, and vice versa.
1378 * Note, do not touch dynamic routes. They will removed by when e.g. lease is lost. */
1379 if (route
->source
!= (foreign
? NETWORK_CONFIG_SOURCE_FOREIGN
: NETWORK_CONFIG_SOURCE_STATIC
))
1382 /* Ignore routes not assigned yet or already removed. */
1383 if (!route_exists(route
))
1386 if (link
->network
) {
1387 if (route
->protocol
== RTPROT_STATIC
&&
1388 FLAGS_SET(link
->network
->keep_configuration
, KEEP_CONFIGURATION_STATIC
))
1391 if (route
->protocol
== RTPROT_DHCP
&&
1392 FLAGS_SET(link
->network
->keep_configuration
, KEEP_CONFIGURATION_DHCP
))
1396 /* When we mark foreign routes, do not mark routes assigned to other interfaces.
1397 * Otherwise, routes assigned to unmanaged interfaces will be dropped.
1398 * Note, route_get_link() does not provide assigned link for routes with an unreachable type
1399 * or IPv4 multipath routes. So, the current implementation does not support managing such
1400 * routes by other daemon or so, unless ManageForeignRoutes=no. */
1404 if (route_get_link(link
->manager
, route
, &route_link
) >= 0 && route_link
!= link
)
1411 /* Then, unmark all routes requested by active links. */
1412 HASHMAP_FOREACH(other
, link
->manager
->links_by_index
) {
1413 if (!foreign
&& other
== link
)
1416 if (!IN_SET(other
->state
, LINK_STATE_CONFIGURING
, LINK_STATE_CONFIGURED
))
1419 HASHMAP_FOREACH(route
, other
->network
->routes_by_section
) {
1420 if (route
->family
== AF_INET
|| ordered_set_isempty(route
->nexthops
)) {
1421 r
= link_unmark_route(other
, route
, NULL
);
1427 ORDERED_SET_FOREACH(nh
, route
->nexthops
) {
1428 r
= link_unmark_route(other
, route
, nh
);
1436 /* Also unmark routes requested in .netdev file. */
1437 if (foreign
&& link
->netdev
&& link
->netdev
->kind
== NETDEV_KIND_WIREGUARD
) {
1438 Wireguard
*w
= WIREGUARD(link
->netdev
);
1440 SET_FOREACH(route
, w
->routes
) {
1441 r
= link_unmark_route(link
, route
, NULL
);
1450 int link_drop_routes(Link
*link
, bool foreign
) {
1455 assert(link
->manager
);
1457 r
= link_mark_routes(link
, foreign
);
1461 SET_FOREACH(route
, link
->manager
->routes
) {
1462 if (!route_is_marked(route
))
1465 RET_GATHER(r
, route_remove(route
, link
->manager
));
1471 int link_foreignize_routes(Link
*link
) {
1476 assert(link
->manager
);
1478 r
= link_mark_routes(link
, /* foreign = */ false);
1482 SET_FOREACH(route
, link
->manager
->routes
) {
1483 if (!route_is_marked(route
))
1486 route
->source
= NETWORK_CONFIG_SOURCE_FOREIGN
;
1492 int network_add_ipv4ll_route(Network
*network
) {
1493 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1494 unsigned section_line
;
1499 if (!network
->ipv4ll_route
)
1502 r
= hashmap_by_section_find_unused_line(network
->routes_by_section
, network
->filename
, §ion_line
);
1506 /* IPv4LLRoute= is in [Network] section. */
1507 r
= route_new_static(network
, network
->filename
, section_line
, &route
);
1511 r
= in_addr_from_string(AF_INET
, "169.254.0.0", &route
->dst
);
1515 route
->family
= AF_INET
;
1516 route
->dst_prefixlen
= 16;
1517 route
->scope
= RT_SCOPE_LINK
;
1518 route
->scope_set
= true;
1519 route
->table_set
= true;
1520 route
->priority
= IPV4LL_ROUTE_METRIC
;
1521 route
->protocol
= RTPROT_STATIC
;
1527 int network_add_default_route_on_device(Network
*network
) {
1528 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1529 unsigned section_line
;
1534 if (!network
->default_route_on_device
)
1537 r
= hashmap_by_section_find_unused_line(network
->routes_by_section
, network
->filename
, §ion_line
);
1541 /* DefaultRouteOnDevice= is in [Network] section. */
1542 r
= route_new_static(network
, network
->filename
, section_line
, &route
);
1546 route
->family
= AF_INET
;
1547 route
->scope
= RT_SCOPE_LINK
;
1548 route
->scope_set
= true;
1549 route
->protocol
= RTPROT_STATIC
;
1555 int config_parse_preferred_src(
1557 const char *filename
,
1559 const char *section
,
1560 unsigned section_line
,
1567 Network
*network
= userdata
;
1568 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1577 r
= route_new_static(network
, filename
, section_line
, &route
);
1581 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1582 "Failed to allocate route, ignoring assignment: %m");
1586 if (route
->family
== AF_UNSPEC
)
1587 r
= in_addr_from_string_auto(rvalue
, &route
->family
, &route
->prefsrc
);
1589 r
= in_addr_from_string(route
->family
, rvalue
, &route
->prefsrc
);
1591 log_syntax(unit
, LOG_WARNING
, filename
, line
, EINVAL
,
1592 "Invalid %s='%s', ignoring assignment: %m", lvalue
, rvalue
);
1600 int config_parse_destination(
1602 const char *filename
,
1604 const char *section
,
1605 unsigned section_line
,
1612 Network
*network
= userdata
;
1613 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1614 union in_addr_union
*buffer
;
1615 unsigned char *prefixlen
;
1624 r
= route_new_static(network
, filename
, section_line
, &route
);
1628 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1629 "Failed to allocate route, ignoring assignment: %m");
1633 if (streq(lvalue
, "Destination")) {
1634 buffer
= &route
->dst
;
1635 prefixlen
= &route
->dst_prefixlen
;
1636 } else if (streq(lvalue
, "Source")) {
1637 buffer
= &route
->src
;
1638 prefixlen
= &route
->src_prefixlen
;
1640 assert_not_reached();
1642 if (route
->family
== AF_UNSPEC
)
1643 r
= in_addr_prefix_from_string_auto(rvalue
, &route
->family
, buffer
, prefixlen
);
1645 r
= in_addr_prefix_from_string(rvalue
, route
->family
, buffer
, prefixlen
);
1647 log_syntax(unit
, LOG_WARNING
, filename
, line
, EINVAL
,
1648 "Invalid %s='%s', ignoring assignment: %m", lvalue
, rvalue
);
1652 (void) in_addr_mask(route
->family
, buffer
, *prefixlen
);
1658 int config_parse_route_priority(
1660 const char *filename
,
1662 const char *section
,
1663 unsigned section_line
,
1670 Network
*network
= userdata
;
1671 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1680 r
= route_new_static(network
, filename
, section_line
, &route
);
1684 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1685 "Failed to allocate route, ignoring assignment: %m");
1689 r
= safe_atou32(rvalue
, &route
->priority
);
1691 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1692 "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue
);
1696 route
->priority_set
= true;
1701 int config_parse_route_scope(
1703 const char *filename
,
1705 const char *section
,
1706 unsigned section_line
,
1713 Network
*network
= userdata
;
1714 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1723 r
= route_new_static(network
, filename
, section_line
, &route
);
1727 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1728 "Failed to allocate route, ignoring assignment: %m");
1732 r
= route_scope_from_string(rvalue
);
1734 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Unknown route scope: %s", rvalue
);
1739 route
->scope_set
= true;
1744 int config_parse_route_table(
1746 const char *filename
,
1748 const char *section
,
1749 unsigned section_line
,
1756 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1757 Network
*network
= userdata
;
1766 r
= route_new_static(network
, filename
, section_line
, &route
);
1770 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1771 "Failed to allocate route, ignoring assignment: %m");
1775 r
= manager_get_route_table_from_string(network
->manager
, rvalue
, &route
->table
);
1777 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1778 "Could not parse route table \"%s\", ignoring assignment: %m", rvalue
);
1782 route
->table_set
= true;
1787 int config_parse_ipv6_route_preference(
1789 const char *filename
,
1791 const char *section
,
1792 unsigned section_line
,
1799 Network
*network
= userdata
;
1800 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1803 r
= route_new_static(network
, filename
, section_line
, &route
);
1807 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1808 "Failed to allocate route, ignoring assignment: %m");
1812 if (streq(rvalue
, "low"))
1813 route
->pref
= ICMPV6_ROUTER_PREF_LOW
;
1814 else if (streq(rvalue
, "medium"))
1815 route
->pref
= ICMPV6_ROUTER_PREF_MEDIUM
;
1816 else if (streq(rvalue
, "high"))
1817 route
->pref
= ICMPV6_ROUTER_PREF_HIGH
;
1819 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "Unknown route preference: %s", rvalue
);
1823 route
->pref_set
= true;
1828 int config_parse_route_protocol(
1830 const char *filename
,
1832 const char *section
,
1833 unsigned section_line
,
1840 Network
*network
= userdata
;
1841 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1844 r
= route_new_static(network
, filename
, section_line
, &route
);
1848 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1849 "Failed to allocate route, ignoring assignment: %m");
1853 r
= route_protocol_from_string(rvalue
);
1855 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1856 "Failed to parse route protocol \"%s\", ignoring assignment: %m", rvalue
);
1860 route
->protocol
= r
;
1866 int config_parse_route_type(
1868 const char *filename
,
1870 const char *section
,
1871 unsigned section_line
,
1878 Network
*network
= userdata
;
1879 _cleanup_(route_unref_or_set_invalidp
) Route
*route
= NULL
;
1882 r
= route_new_static(network
, filename
, section_line
, &route
);
1886 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1887 "Failed to allocate route, ignoring assignment: %m");
1891 t
= route_type_from_string(rvalue
);
1893 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1894 "Could not parse route type \"%s\", ignoring assignment: %m", rvalue
);
1898 route
->type
= (unsigned char) t
;
1904 int route_section_verify(Route
*route
) {
1908 assert(route
->section
);
1910 if (section_is_invalid(route
->section
))
1913 /* Currently, we do not support static route with finite lifetime. */
1914 assert(route
->lifetime_usec
== USEC_INFINITY
);
1916 r
= route_section_verify_nexthops(route
);
1921 if (!route
->table_set
&& route
->network
&& route
->network
->vrf
) {
1922 route
->table
= VRF(route
->network
->vrf
)->table
;
1923 route
->table_set
= true;
1926 if (!route
->table_set
&& IN_SET(route
->type
, RTN_LOCAL
, RTN_BROADCAST
, RTN_ANYCAST
, RTN_NAT
))
1927 route
->table
= RT_TABLE_LOCAL
;
1930 if (!route
->scope_set
&& route
->family
== AF_INET
) {
1931 if (IN_SET(route
->type
, RTN_LOCAL
, RTN_NAT
))
1932 route
->scope
= RT_SCOPE_HOST
;
1933 else if (IN_SET(route
->type
, RTN_BROADCAST
, RTN_ANYCAST
, RTN_MULTICAST
))
1934 route
->scope
= RT_SCOPE_LINK
;
1935 else if (IN_SET(route
->type
, RTN_UNICAST
, RTN_UNSPEC
) &&
1936 !route
->gateway_from_dhcp_or_ra
&&
1937 !in_addr_is_set(route
->nexthop
.family
, &route
->nexthop
.gw
) &&
1938 ordered_set_isempty(route
->nexthops
) &&
1939 route
->nexthop_id
== 0)
1940 route
->scope
= RT_SCOPE_LINK
;
1944 if (route
->family
== AF_INET6
) {
1945 if (route
->scope
!= RT_SCOPE_UNIVERSE
) {
1946 log_warning("%s: Scope= is specified for IPv6 route. It will be ignored.", route
->section
->filename
);
1947 route
->scope
= RT_SCOPE_UNIVERSE
;
1950 if (route
->priority
== 0)
1951 route
->priority
= IP6_RT_PRIO_USER
;
1957 void network_drop_invalid_routes(Network
*network
) {
1962 HASHMAP_FOREACH(route
, network
->routes_by_section
)
1963 if (route_section_verify(route
) < 0)
1964 route_detach(route
);