1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <linux/icmpv6.h>
4 #include <linux/ipv6_route.h>
6 #include "alloc-util.h"
7 #include "netlink-util.h"
8 #include "networkd-ipv4ll.h"
9 #include "networkd-manager.h"
10 #include "networkd-network.h"
11 #include "networkd-nexthop.h"
12 #include "networkd-route.h"
13 #include "networkd-routing-policy-rule.h"
14 #include "parse-util.h"
15 #include "socket-netlink.h"
16 #include "string-table.h"
17 #include "string-util.h"
20 #include "sysctl-util.h"
23 #define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
25 static uint32_t link_get_vrf_table(const Link
*link
) {
26 return link
->network
->vrf
? VRF(link
->network
->vrf
)->table
: RT_TABLE_MAIN
;
29 uint32_t link_get_dhcp_route_table(const Link
*link
) {
30 /* When the interface is part of an VRF use the VRFs routing table, unless
31 * another table is explicitly specified. */
32 if (link
->network
->dhcp_route_table_set
)
33 return link
->network
->dhcp_route_table
;
34 return link_get_vrf_table(link
);
37 uint32_t link_get_ipv6_accept_ra_route_table(const Link
*link
) {
38 if (link
->network
->ipv6_accept_ra_route_table_set
)
39 return link
->network
->ipv6_accept_ra_route_table
;
40 return link_get_vrf_table(link
);
43 static const char * const route_type_table
[__RTN_MAX
] = {
44 [RTN_UNICAST
] = "unicast",
45 [RTN_LOCAL
] = "local",
46 [RTN_BROADCAST
] = "broadcast",
47 [RTN_ANYCAST
] = "anycast",
48 [RTN_MULTICAST
] = "multicast",
49 [RTN_BLACKHOLE
] = "blackhole",
50 [RTN_UNREACHABLE
] = "unreachable",
51 [RTN_PROHIBIT
] = "prohibit",
52 [RTN_THROW
] = "throw",
54 [RTN_XRESOLVE
] = "xresolve",
57 assert_cc(__RTN_MAX
<= UCHAR_MAX
);
58 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_type
, int);
60 static const char * const route_scope_table
[] = {
61 [RT_SCOPE_UNIVERSE
] = "global",
62 [RT_SCOPE_SITE
] = "site",
63 [RT_SCOPE_LINK
] = "link",
64 [RT_SCOPE_HOST
] = "host",
65 [RT_SCOPE_NOWHERE
] = "nowhere",
68 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_scope
, int);
70 #define ROUTE_SCOPE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("nowhere") + 1)
71 static const char *format_route_scope(int scope
, char *buf
, size_t size
) {
75 s
= route_scope_to_string(scope
);
79 strpcpyf(&p
, size
, "%d", scope
);
84 static const char * const route_table_table
[] = {
85 [RT_TABLE_DEFAULT
] = "default",
86 [RT_TABLE_MAIN
] = "main",
87 [RT_TABLE_LOCAL
] = "local",
90 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_table
, int);
92 #define ROUTE_TABLE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("default") + 1)
93 static const char *format_route_table(int table
, char *buf
, size_t size
) {
97 s
= route_table_to_string(table
);
101 strpcpyf(&p
, size
, "%d", table
);
106 static const char * const route_protocol_table
[] = {
107 [RTPROT_KERNEL
] = "kernel",
108 [RTPROT_BOOT
] = "boot",
109 [RTPROT_STATIC
] = "static",
112 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_protocol
, int);
114 static const char * const route_protocol_full_table
[] = {
115 [RTPROT_REDIRECT
] = "redirect",
116 [RTPROT_KERNEL
] = "kernel",
117 [RTPROT_BOOT
] = "boot",
118 [RTPROT_STATIC
] = "static",
119 [RTPROT_GATED
] = "gated",
121 [RTPROT_MRT
] = "mrt",
122 [RTPROT_ZEBRA
] = "zebra",
123 [RTPROT_BIRD
] = "bird",
124 [RTPROT_DNROUTED
] = "dnrouted",
125 [RTPROT_XORP
] = "xorp",
126 [RTPROT_NTK
] = "ntk",
127 [RTPROT_DHCP
] = "dhcp",
128 [RTPROT_MROUTED
] = "mrouted",
129 [RTPROT_BABEL
] = "babel",
130 [RTPROT_BGP
] = "bgp",
131 [RTPROT_ISIS
] = "isis",
132 [RTPROT_OSPF
] = "ospf",
133 [RTPROT_RIP
] = "rip",
134 [RTPROT_EIGRP
] = "eigrp",
137 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(route_protocol_full
, int);
139 #define ROUTE_PROTOCOL_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("redirect") + 1)
140 static const char *format_route_protocol(int protocol
, char *buf
, size_t size
) {
144 s
= route_protocol_full_to_string(protocol
);
146 strpcpy(&p
, size
, s
);
148 strpcpyf(&p
, size
, "%d", protocol
);
153 static unsigned routes_max(void) {
154 static thread_local
unsigned cached
= 0;
155 _cleanup_free_
char *s4
= NULL
, *s6
= NULL
;
156 unsigned val4
= ROUTES_DEFAULT_MAX_PER_FAMILY
, val6
= ROUTES_DEFAULT_MAX_PER_FAMILY
;
161 if (sysctl_read_ip_property(AF_INET
, NULL
, "route/max_size", &s4
) >= 0)
162 if (safe_atou(s4
, &val4
) >= 0 && val4
== 2147483647U)
163 /* This is the default "no limit" value in the kernel */
164 val4
= ROUTES_DEFAULT_MAX_PER_FAMILY
;
166 if (sysctl_read_ip_property(AF_INET6
, NULL
, "route/max_size", &s6
) >= 0)
167 (void) safe_atou(s6
, &val6
);
169 cached
= MAX(ROUTES_DEFAULT_MAX_PER_FAMILY
, val4
) +
170 MAX(ROUTES_DEFAULT_MAX_PER_FAMILY
, val6
);
174 int route_new(Route
**ret
) {
175 _cleanup_(route_freep
) Route
*route
= NULL
;
177 route
= new(Route
, 1);
183 .scope
= RT_SCOPE_UNIVERSE
,
184 .protocol
= RTPROT_UNSPEC
,
186 .table
= RT_TABLE_MAIN
,
187 .lifetime
= USEC_INFINITY
,
189 .fast_open_no_cookie
= -1,
190 .gateway_onlink
= -1,
194 *ret
= TAKE_PTR(route
);
199 static int route_new_static(Network
*network
, const char *filename
, unsigned section_line
, Route
**ret
) {
200 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
201 _cleanup_(route_freep
) Route
*route
= NULL
;
207 assert(section_line
> 0);
209 r
= network_config_section_new(filename
, section_line
, &n
);
213 route
= hashmap_get(network
->routes_by_section
, n
);
215 *ret
= TAKE_PTR(route
);
219 if (hashmap_size(network
->routes_by_section
) >= routes_max())
222 r
= route_new(&route
);
226 route
->protocol
= RTPROT_STATIC
;
227 route
->network
= network
;
228 route
->section
= TAKE_PTR(n
);
230 r
= hashmap_ensure_put(&network
->routes_by_section
, &network_config_hash_ops
, route
->section
, route
);
234 *ret
= TAKE_PTR(route
);
238 Route
*route_free(Route
*route
) {
242 if (route
->network
) {
243 assert(route
->section
);
244 hashmap_remove(route
->network
->routes_by_section
, route
->section
);
247 network_config_section_free(route
->section
);
252 set_remove(route
->link
->routes
, route
);
253 set_remove(route
->link
->routes_foreign
, route
);
254 set_remove(route
->link
->dhcp_routes
, route
);
255 set_remove(route
->link
->dhcp_routes_old
, route
);
256 set_remove(route
->link
->dhcp6_routes
, route
);
257 set_remove(route
->link
->dhcp6_routes_old
, route
);
258 set_remove(route
->link
->dhcp6_pd_routes
, route
);
259 set_remove(route
->link
->dhcp6_pd_routes_old
, route
);
260 SET_FOREACH(n
, route
->link
->ndisc_routes
)
261 if (n
->route
== route
)
262 free(set_remove(route
->link
->ndisc_routes
, n
));
265 if (route
->manager
) {
266 set_remove(route
->manager
->routes
, route
);
267 set_remove(route
->manager
->routes_foreign
, route
);
270 ordered_set_free_free(route
->multipath_routes
);
272 sd_event_source_unref(route
->expire
);
277 void route_hash_func(const Route
*route
, struct siphash
*state
) {
280 siphash24_compress(&route
->family
, sizeof(route
->family
), state
);
282 switch (route
->family
) {
285 siphash24_compress(&route
->dst_prefixlen
, sizeof(route
->dst_prefixlen
), state
);
286 siphash24_compress(&route
->dst
, FAMILY_ADDRESS_SIZE(route
->family
), state
);
288 siphash24_compress(&route
->src_prefixlen
, sizeof(route
->src_prefixlen
), state
);
289 siphash24_compress(&route
->src
, FAMILY_ADDRESS_SIZE(route
->family
), state
);
291 siphash24_compress(&route
->gw_family
, sizeof(route
->gw_family
), state
);
292 if (IN_SET(route
->gw_family
, AF_INET
, AF_INET6
)) {
293 siphash24_compress(&route
->gw
, FAMILY_ADDRESS_SIZE(route
->gw_family
), state
);
294 siphash24_compress(&route
->gw_weight
, sizeof(route
->gw_weight
), state
);
297 siphash24_compress(&route
->prefsrc
, FAMILY_ADDRESS_SIZE(route
->family
), state
);
299 siphash24_compress(&route
->tos
, sizeof(route
->tos
), state
);
300 siphash24_compress(&route
->priority
, sizeof(route
->priority
), state
);
301 siphash24_compress(&route
->table
, sizeof(route
->table
), state
);
302 siphash24_compress(&route
->protocol
, sizeof(route
->protocol
), state
);
303 siphash24_compress(&route
->scope
, sizeof(route
->scope
), state
);
304 siphash24_compress(&route
->type
, sizeof(route
->type
), state
);
306 siphash24_compress(&route
->initcwnd
, sizeof(route
->initcwnd
), state
);
307 siphash24_compress(&route
->initrwnd
, sizeof(route
->initrwnd
), state
);
309 siphash24_compress(&route
->advmss
, sizeof(route
->advmss
), state
);
313 /* treat any other address family as AF_UNSPEC */
318 int route_compare_func(const Route
*a
, const Route
*b
) {
321 r
= CMP(a
->family
, b
->family
);
328 r
= CMP(a
->dst_prefixlen
, b
->dst_prefixlen
);
332 r
= memcmp(&a
->dst
, &b
->dst
, FAMILY_ADDRESS_SIZE(a
->family
));
336 r
= CMP(a
->src_prefixlen
, b
->src_prefixlen
);
340 r
= memcmp(&a
->src
, &b
->src
, FAMILY_ADDRESS_SIZE(a
->family
));
344 r
= CMP(a
->gw_family
, b
->gw_family
);
348 if (IN_SET(a
->gw_family
, AF_INET
, AF_INET6
)) {
349 r
= memcmp(&a
->gw
, &b
->gw
, FAMILY_ADDRESS_SIZE(a
->family
));
353 r
= CMP(a
->gw_weight
, b
->gw_weight
);
358 r
= memcmp(&a
->prefsrc
, &b
->prefsrc
, FAMILY_ADDRESS_SIZE(a
->family
));
362 r
= CMP(a
->tos
, b
->tos
);
366 r
= CMP(a
->priority
, b
->priority
);
370 r
= CMP(a
->table
, b
->table
);
374 r
= CMP(a
->protocol
, b
->protocol
);
378 r
= CMP(a
->scope
, b
->scope
);
382 r
= CMP(a
->type
, b
->type
);
386 r
= CMP(a
->initcwnd
, b
->initcwnd
);
390 r
= CMP(a
->initrwnd
, b
->initrwnd
);
394 r
= CMP(a
->advmss
, b
->advmss
);
400 /* treat any other address family as AF_UNSPEC */
405 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
412 static bool route_equal(const Route
*r1
, const Route
*r2
) {
419 return route_compare_func(r1
, r2
) == 0;
422 static int route_get(const Manager
*manager
, const Link
*link
, const Route
*in
, Route
**ret
) {
425 assert(manager
|| link
);
429 existing
= set_get(link
->routes
, in
);
436 existing
= set_get(link
->routes_foreign
, in
);
443 existing
= set_get(manager
->routes
, in
);
450 existing
= set_get(manager
->routes_foreign
, in
);
461 static void route_copy(Route
*dest
, const Route
*src
, const MultipathRoute
*m
) {
465 dest
->family
= src
->family
;
466 dest
->src
= src
->src
;
467 dest
->src_prefixlen
= src
->src_prefixlen
;
468 dest
->dst
= src
->dst
;
469 dest
->dst_prefixlen
= src
->dst_prefixlen
;
470 dest
->prefsrc
= src
->prefsrc
;
471 dest
->scope
= src
->scope
;
472 dest
->protocol
= src
->protocol
;
473 dest
->type
= src
->type
;
474 dest
->tos
= src
->tos
;
475 dest
->priority
= src
->priority
;
476 dest
->table
= src
->table
;
477 dest
->initcwnd
= src
->initcwnd
;
478 dest
->initrwnd
= src
->initrwnd
;
479 dest
->lifetime
= src
->lifetime
;
480 dest
->advmss
= src
->advmss
;
483 dest
->gw_family
= m
->gateway
.family
;
484 dest
->gw
= m
->gateway
.address
;
485 dest
->gw_weight
= m
->weight
;
487 dest
->gw_family
= src
->gw_family
;
489 dest
->gw_weight
= src
->gw_weight
;
493 static int route_add_internal(Manager
*manager
, Link
*link
, Set
**routes
, const Route
*in
, Route
**ret
) {
494 _cleanup_(route_freep
) Route
*route
= NULL
;
497 assert(manager
|| link
);
501 r
= route_new(&route
);
505 route_copy(route
, in
, NULL
);
507 r
= set_ensure_put(routes
, &route_hash_ops
, route
);
514 route
->manager
= manager
;
524 static int route_add_foreign(Manager
*manager
, Link
*link
, const Route
*in
, Route
**ret
) {
525 assert(manager
|| link
);
526 return route_add_internal(manager
, link
, link
? &link
->routes_foreign
: &manager
->routes_foreign
, in
, ret
);
529 static int route_add(Manager
*manager
, Link
*link
, const Route
*in
, const MultipathRoute
*m
, Route
**ret
) {
530 _cleanup_(route_freep
) Route
*tmp
= NULL
;
534 assert(manager
|| link
);
538 assert(link
&& (m
->ifindex
== 0 || m
->ifindex
== link
->ifindex
));
544 route_copy(tmp
, in
, m
);
548 r
= route_get(manager
, link
, in
, &route
);
550 /* Route does not exist, create a new one */
551 r
= route_add_internal(manager
, link
, link
? &link
->routes
: &manager
->routes
, in
, &route
);
555 /* Take over a foreign route */
557 r
= set_ensure_put(&link
->routes
, &route_hash_ops
, route
);
561 set_remove(link
->routes_foreign
, route
);
563 r
= set_ensure_put(&manager
->routes
, &route_hash_ops
, route
);
567 set_remove(manager
->routes_foreign
, route
);
570 /* Route exists, do nothing */
581 static bool route_type_is_reject(const Route
*route
) {
584 return IN_SET(route
->type
, RTN_UNREACHABLE
, RTN_PROHIBIT
, RTN_BLACKHOLE
, RTN_THROW
);
587 static void log_route_debug(const Route
*route
, const char *str
, const Link
*link
) {
591 /* link may be NULL. */
594 _cleanup_free_
char *dst
= NULL
, *dst_prefixlen
= NULL
, *src
= NULL
, *gw
= NULL
, *prefsrc
= NULL
;
595 char scope
[ROUTE_SCOPE_STR_MAX
], table
[ROUTE_TABLE_STR_MAX
], protocol
[ROUTE_PROTOCOL_STR_MAX
];
597 if (!in_addr_is_null(route
->family
, &route
->dst
)) {
598 (void) in_addr_to_string(route
->family
, &route
->dst
, &dst
);
599 (void) asprintf(&dst_prefixlen
, "/%u", route
->dst_prefixlen
);
601 if (!in_addr_is_null(route
->family
, &route
->src
))
602 (void) in_addr_to_string(route
->family
, &route
->src
, &src
);
603 if (!in_addr_is_null(route
->gw_family
, &route
->gw
))
604 (void) in_addr_to_string(route
->gw_family
, &route
->gw
, &gw
);
605 if (!in_addr_is_null(route
->family
, &route
->prefsrc
))
606 (void) in_addr_to_string(route
->family
, &route
->prefsrc
, &prefsrc
);
609 "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
610 str
, strna(dst
), strempty(dst_prefixlen
), strna(src
), strna(gw
), strna(prefsrc
),
611 format_route_scope(route
->scope
, scope
, sizeof(scope
)),
612 format_route_table(route
->table
, table
, sizeof(table
)),
613 format_route_protocol(route
->protocol
, protocol
, sizeof(protocol
)),
614 strna(route_type_to_string(route
->type
)));
618 static int route_set_netlink_message(const Route
*route
, sd_netlink_message
*req
, Link
*link
) {
625 /* link may be NULL */
627 if (in_addr_is_null(route
->gw_family
, &route
->gw
) == 0) {
628 if (route
->gw_family
== route
->family
) {
629 r
= netlink_message_append_in_addr_union(req
, RTA_GATEWAY
, route
->gw_family
, &route
->gw
);
631 return log_link_error_errno(link
, r
, "Could not append RTA_GATEWAY attribute: %m");
634 .family
= route
->gw_family
,
635 .address
= route
->gw
,
638 r
= sd_netlink_message_append_data(req
, RTA_VIA
, &rtvia
, sizeof(rtvia
));
640 return log_link_error_errno(link
, r
, "Could not append RTA_VIA attribute: %m");
644 if (route
->dst_prefixlen
> 0) {
645 r
= netlink_message_append_in_addr_union(req
, RTA_DST
, route
->family
, &route
->dst
);
647 return log_link_error_errno(link
, r
, "Could not append RTA_DST attribute: %m");
649 r
= sd_rtnl_message_route_set_dst_prefixlen(req
, route
->dst_prefixlen
);
651 return log_link_error_errno(link
, r
, "Could not set destination prefix length: %m");
654 if (route
->src_prefixlen
> 0) {
655 r
= netlink_message_append_in_addr_union(req
, RTA_SRC
, route
->family
, &route
->src
);
657 return log_link_error_errno(link
, r
, "Could not append RTA_SRC attribute: %m");
659 r
= sd_rtnl_message_route_set_src_prefixlen(req
, route
->src_prefixlen
);
661 return log_link_error_errno(link
, r
, "Could not set source prefix length: %m");
664 if (in_addr_is_null(route
->family
, &route
->prefsrc
) == 0) {
665 r
= netlink_message_append_in_addr_union(req
, RTA_PREFSRC
, route
->family
, &route
->prefsrc
);
667 return log_link_error_errno(link
, r
, "Could not append RTA_PREFSRC attribute: %m");
670 r
= sd_rtnl_message_route_set_scope(req
, route
->scope
);
672 return log_link_error_errno(link
, r
, "Could not set scope: %m");
674 flags
= route
->flags
;
675 if (route
->gateway_onlink
>= 0)
676 SET_FLAG(flags
, RTNH_F_ONLINK
, route
->gateway_onlink
);
678 r
= sd_rtnl_message_route_set_flags(req
, flags
);
680 return log_link_error_errno(link
, r
, "Could not set flags: %m");
682 if (route
->table
!= RT_TABLE_MAIN
) {
683 if (route
->table
< 256) {
684 r
= sd_rtnl_message_route_set_table(req
, route
->table
);
686 return log_link_error_errno(link
, r
, "Could not set route table: %m");
688 r
= sd_rtnl_message_route_set_table(req
, RT_TABLE_UNSPEC
);
690 return log_link_error_errno(link
, r
, "Could not set route table: %m");
692 /* Table attribute to allow more than 256. */
693 r
= sd_netlink_message_append_data(req
, RTA_TABLE
, &route
->table
, sizeof(route
->table
));
695 return log_link_error_errno(link
, r
, "Could not append RTA_TABLE attribute: %m");
699 r
= sd_rtnl_message_route_set_type(req
, route
->type
);
701 return log_link_error_errno(link
, r
, "Could not set route type: %m");
703 if (!route_type_is_reject(route
)) {
704 assert(link
); /* Those routes must be attached to a specific link */
706 r
= sd_netlink_message_append_u32(req
, RTA_OIF
, link
->ifindex
);
708 return log_link_error_errno(link
, r
, "Could not append RTA_OIF attribute: %m");
711 r
= sd_netlink_message_append_u8(req
, RTA_PREF
, route
->pref
);
713 return log_link_error_errno(link
, r
, "Could not append RTA_PREF attribute: %m");
715 r
= sd_netlink_message_append_u32(req
, RTA_PRIORITY
, route
->priority
);
717 return log_link_error_errno(link
, r
, "Could not append RTA_PRIORITY attribute: %m");
722 static int route_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
727 /* Note that link may be NULL. */
728 if (link
&& IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
731 r
= sd_netlink_message_get_errno(m
);
732 if (r
< 0 && r
!= -ESRCH
)
733 log_link_message_warning_errno(link
, m
, r
, "Could not drop route, ignoring");
742 link_netlink_message_handler_t callback
) {
744 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
747 assert(link
|| manager
);
748 assert(IN_SET(route
->family
, AF_INET
, AF_INET6
));
751 manager
= link
->manager
;
752 /* link may be NULL! */
754 log_route_debug(route
, "Removing", link
);
756 r
= sd_rtnl_message_new_route(manager
->rtnl
, &req
,
757 RTM_DELROUTE
, route
->family
,
760 return log_link_error_errno(link
, r
, "Could not create RTM_DELROUTE message: %m");
762 r
= route_set_netlink_message(route
, req
, link
);
766 r
= netlink_call_async(manager
->rtnl
, NULL
, req
,
767 callback
?: route_remove_handler
,
768 link_netlink_destroy_callback
, link
);
770 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
772 link_ref(link
); /* link may be NULL, link_ref() is OK with that */
777 static bool link_has_route(const Link
*link
, const Route
*route
) {
786 HASHMAP_FOREACH(net_route
, link
->network
->routes_by_section
)
787 if (route_equal(net_route
, route
))
793 static bool links_have_route(const Manager
*manager
, const Route
*route
, const Link
*except
) {
798 HASHMAP_FOREACH(link
, manager
->links
) {
802 if (link_has_route(link
, route
))
809 static int manager_drop_routes_internal(Manager
*manager
, bool foreign
, const Link
*except
) {
816 routes
= foreign
? manager
->routes_foreign
: manager
->routes
;
817 SET_FOREACH(route
, routes
) {
818 /* Do not touch routes managed by the kernel */
819 if (route
->protocol
== RTPROT_KERNEL
)
822 /* The route will be configured later, or already configured by a link */
823 if (links_have_route(manager
, route
, except
))
826 /* The existing links do not have the route. Let's drop this now. It may by
827 * re-configured later. */
828 k
= route_remove(route
, manager
, NULL
, NULL
);
836 static int manager_drop_foreign_routes(Manager
*manager
) {
837 return manager_drop_routes_internal(manager
, true, NULL
);
840 static int manager_drop_routes(Manager
*manager
, const Link
*except
) {
841 return manager_drop_routes_internal(manager
, false, except
);
844 int link_drop_foreign_routes(Link
*link
) {
849 assert(link
->manager
);
851 SET_FOREACH(route
, link
->routes_foreign
) {
852 /* do not touch routes managed by the kernel */
853 if (route
->protocol
== RTPROT_KERNEL
)
856 /* do not touch multicast route added by kernel */
857 /* FIXME: Why the kernel adds this route with protocol RTPROT_BOOT??? We need to investigate that.
858 * https://tools.ietf.org/html/rfc4862#section-5.4 may explain why. */
859 if (route
->protocol
== RTPROT_BOOT
&&
860 route
->family
== AF_INET6
&&
861 route
->dst_prefixlen
== 8 &&
862 in_addr_equal(AF_INET6
, &route
->dst
, &(union in_addr_union
) { .in6
= {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}} }))
865 if (route
->protocol
== RTPROT_STATIC
&& link
->network
&&
866 FLAGS_SET(link
->network
->keep_configuration
, KEEP_CONFIGURATION_STATIC
))
869 if (route
->protocol
== RTPROT_DHCP
&& link
->network
&&
870 FLAGS_SET(link
->network
->keep_configuration
, KEEP_CONFIGURATION_DHCP
))
873 if (link_has_route(link
, route
))
874 k
= route_add(NULL
, link
, route
, NULL
, NULL
);
876 k
= route_remove(route
, NULL
, link
, NULL
);
881 k
= manager_drop_foreign_routes(link
->manager
);
888 int link_drop_routes(Link
*link
) {
894 SET_FOREACH(route
, link
->routes
) {
895 /* do not touch routes managed by the kernel */
896 if (route
->protocol
== RTPROT_KERNEL
)
899 k
= route_remove(route
, NULL
, link
, NULL
);
904 k
= manager_drop_routes(link
->manager
, link
);
911 static int route_expire_handler(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
912 Route
*route
= userdata
;
917 r
= route_remove(route
, route
->manager
, route
->link
, NULL
);
919 log_link_warning_errno(route
->link
, r
, "Could not remove route: %m");
926 static int route_add_and_setup_timer(Link
*link
, const Route
*route
, const MultipathRoute
*m
, Route
**ret
) {
927 _cleanup_(sd_event_source_unrefp
) sd_event_source
*expire
= NULL
;
934 if (route_type_is_reject(route
))
935 r
= route_add(link
->manager
, NULL
, route
, NULL
, &nr
);
936 else if (!m
|| m
->ifindex
== 0 || m
->ifindex
== link
->ifindex
)
937 r
= route_add(NULL
, link
, route
, m
, &nr
);
941 r
= link_get(link
->manager
, m
->ifindex
, &link_gw
);
943 return log_link_error_errno(link
, r
, "Failed to get link with ifindex %d: %m", m
->ifindex
);
945 r
= route_add(NULL
, link_gw
, route
, m
, &nr
);
948 return log_link_error_errno(link
, r
, "Could not add route: %m");
950 /* TODO: drop expiration handling once it can be pushed into the kernel */
951 if (nr
->lifetime
!= USEC_INFINITY
&& !kernel_route_expiration_supported()) {
952 r
= sd_event_add_time(link
->manager
->event
, &expire
, clock_boottime_or_monotonic(),
953 nr
->lifetime
, 0, route_expire_handler
, nr
);
955 return log_link_error_errno(link
, r
, "Could not arm expiration timer: %m");
958 sd_event_source_unref(nr
->expire
);
959 nr
->expire
= TAKE_PTR(expire
);
967 static int append_nexthop_one(const Route
*route
, const MultipathRoute
*m
, struct rtattr
**rta
, size_t offset
) {
968 struct rtnexthop
*rtnh
;
969 struct rtattr
*new_rta
;
977 new_rta
= realloc(*rta
, RTA_ALIGN((*rta
)->rta_len
) + RTA_SPACE(sizeof(struct rtnexthop
)));
982 rtnh
= (struct rtnexthop
*)((uint8_t *) *rta
+ offset
);
983 *rtnh
= (struct rtnexthop
) {
984 .rtnh_len
= sizeof(*rtnh
),
985 .rtnh_ifindex
= m
->ifindex
,
986 .rtnh_hops
= m
->weight
> 0 ? m
->weight
- 1 : 0,
989 (*rta
)->rta_len
+= sizeof(struct rtnexthop
);
991 if (route
->family
== m
->gateway
.family
) {
992 r
= rtattr_append_attribute(rta
, RTA_GATEWAY
, &m
->gateway
.address
, FAMILY_ADDRESS_SIZE(m
->gateway
.family
));
995 rtnh
= (struct rtnexthop
*)((uint8_t *) *rta
+ offset
);
996 rtnh
->rtnh_len
+= RTA_SPACE(FAMILY_ADDRESS_SIZE(m
->gateway
.family
));
998 r
= rtattr_append_attribute(rta
, RTA_VIA
, &m
->gateway
, FAMILY_ADDRESS_SIZE(m
->gateway
.family
) + sizeof(m
->gateway
.family
));
1001 rtnh
= (struct rtnexthop
*)((uint8_t *) *rta
+ offset
);
1002 rtnh
->rtnh_len
+= RTA_SPACE(FAMILY_ADDRESS_SIZE(m
->gateway
.family
) + sizeof(m
->gateway
.family
));
1008 (*rta
)->rta_len
-= sizeof(struct rtnexthop
);
1012 static int append_nexthops(const Route
*route
, sd_netlink_message
*req
) {
1013 _cleanup_free_
struct rtattr
*rta
= NULL
;
1014 struct rtnexthop
*rtnh
;
1019 if (ordered_set_isempty(route
->multipath_routes
))
1022 rta
= new(struct rtattr
, 1);
1026 *rta
= (struct rtattr
) {
1027 .rta_type
= RTA_MULTIPATH
,
1028 .rta_len
= RTA_LENGTH(0),
1030 offset
= (uint8_t *) RTA_DATA(rta
) - (uint8_t *) rta
;
1032 ORDERED_SET_FOREACH(m
, route
->multipath_routes
) {
1033 r
= append_nexthop_one(route
, m
, &rta
, offset
);
1037 rtnh
= (struct rtnexthop
*)((uint8_t *) rta
+ offset
);
1038 offset
= (uint8_t *) RTNH_NEXT(rtnh
) - (uint8_t *) rta
;
1041 r
= sd_netlink_message_append_data(req
, RTA_MULTIPATH
, RTA_DATA(rta
), RTA_PAYLOAD(rta
));
1048 int route_configure(
1051 link_netlink_message_handler_t callback
,
1054 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
1058 assert(link
->manager
);
1059 assert(link
->manager
->rtnl
);
1060 assert(link
->ifindex
> 0);
1061 assert(IN_SET(route
->family
, AF_INET
, AF_INET6
));
1064 if (route_get(link
->manager
, link
, route
, NULL
) <= 0 &&
1065 set_size(link
->routes
) >= routes_max())
1066 return log_link_error_errno(link
, SYNTHETIC_ERRNO(E2BIG
),
1067 "Too many routes are configured, refusing: %m");
1069 log_route_debug(route
, "Configuring", link
);
1071 r
= sd_rtnl_message_new_route(link
->manager
->rtnl
, &req
,
1072 RTM_NEWROUTE
, route
->family
,
1075 return log_link_error_errno(link
, r
, "Could not create RTM_NEWROUTE message: %m");
1077 r
= route_set_netlink_message(route
, req
, link
);
1081 if (route
->lifetime
!= USEC_INFINITY
&& kernel_route_expiration_supported()) {
1082 r
= sd_netlink_message_append_u32(req
, RTA_EXPIRES
,
1083 DIV_ROUND_UP(usec_sub_unsigned(route
->lifetime
, now(clock_boottime_or_monotonic())), USEC_PER_SEC
));
1085 return log_link_error_errno(link
, r
, "Could not append RTA_EXPIRES attribute: %m");
1088 if (route
->ttl_propagate
>= 0) {
1089 r
= sd_netlink_message_append_u8(req
, RTA_TTL_PROPAGATE
, route
->ttl_propagate
);
1091 return log_link_error_errno(link
, r
, "Could not append RTA_TTL_PROPAGATE attribute: %m");
1094 r
= sd_netlink_message_open_container(req
, RTA_METRICS
);
1096 return log_link_error_errno(link
, r
, "Could not append RTA_METRICS attribute: %m");
1098 if (route
->mtu
> 0) {
1099 r
= sd_netlink_message_append_u32(req
, RTAX_MTU
, route
->mtu
);
1101 return log_link_error_errno(link
, r
, "Could not append RTAX_MTU attribute: %m");
1104 if (route
->initcwnd
> 0) {
1105 r
= sd_netlink_message_append_u32(req
, RTAX_INITCWND
, route
->initcwnd
);
1107 return log_link_error_errno(link
, r
, "Could not append RTAX_INITCWND attribute: %m");
1110 if (route
->initrwnd
> 0) {
1111 r
= sd_netlink_message_append_u32(req
, RTAX_INITRWND
, route
->initrwnd
);
1113 return log_link_error_errno(link
, r
, "Could not append RTAX_INITRWND attribute: %m");
1116 if (route
->quickack
>= 0) {
1117 r
= sd_netlink_message_append_u32(req
, RTAX_QUICKACK
, route
->quickack
);
1119 return log_link_error_errno(link
, r
, "Could not append RTAX_QUICKACK attribute: %m");
1122 if (route
->fast_open_no_cookie
>= 0) {
1123 r
= sd_netlink_message_append_u32(req
, RTAX_FASTOPEN_NO_COOKIE
, route
->fast_open_no_cookie
);
1125 return log_link_error_errno(link
, r
, "Could not append RTAX_FASTOPEN_NO_COOKIE attribute: %m");
1128 if (route
->advmss
> 0) {
1129 r
= sd_netlink_message_append_u32(req
, RTAX_ADVMSS
, route
->advmss
);
1131 return log_link_error_errno(link
, r
, "Could not append RTAX_ADVMSS attribute: %m");
1134 r
= sd_netlink_message_close_container(req
);
1136 return log_link_error_errno(link
, r
, "Could not append RTA_METRICS attribute: %m");
1138 r
= append_nexthops(route
, req
);
1140 return log_link_error_errno(link
, r
, "Could not append RTA_MULTIPATH attribute: %m");
1142 if (ordered_set_isempty(route
->multipath_routes
)) {
1145 r
= route_add_and_setup_timer(link
, route
, NULL
, &nr
);
1156 ORDERED_SET_FOREACH(m
, route
->multipath_routes
) {
1157 r
= route_add_and_setup_timer(link
, route
, m
, NULL
);
1163 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, req
, callback
,
1164 link_netlink_destroy_callback
, link
);
1166 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
1173 static int route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
1177 assert(link
->route_messages
> 0);
1179 link
->route_messages
--;
1181 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
1184 r
= sd_netlink_message_get_errno(m
);
1185 if (r
< 0 && r
!= -EEXIST
) {
1186 log_link_message_warning_errno(link
, m
, r
, "Could not set route");
1187 link_enter_failed(link
);
1191 if (link
->route_messages
== 0) {
1192 log_link_debug(link
, "Routes set");
1193 link
->static_routes_configured
= true;
1194 link_set_nexthop(link
);
1200 int link_set_routes(Link
*link
) {
1202 PHASE_NON_GATEWAY
, /* First phase: Routes without a gateway */
1203 PHASE_GATEWAY
, /* Second phase: Routes with a gateway */
1210 assert(link
->network
);
1211 assert(link
->state
!= _LINK_STATE_INVALID
);
1213 link
->static_routes_configured
= false;
1215 if (!link
->addresses_ready
)
1218 if (!link_has_carrier(link
) && !link
->network
->configure_without_carrier
)
1219 /* During configuring addresses, the link lost its carrier. As networkd is dropping
1220 * the addresses now, let's not configure the routes either. */
1223 if (link
->route_messages
!= 0) {
1224 log_link_debug(link
, "Static routes are configuring.");
1228 r
= link_set_routing_policy_rules(link
);
1232 /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
1233 for (phase
= 0; phase
< _PHASE_MAX
; phase
++)
1234 HASHMAP_FOREACH(rt
, link
->network
->routes_by_section
) {
1235 if (rt
->gateway_from_dhcp_or_ra
)
1238 if ((in_addr_is_null(rt
->gw_family
, &rt
->gw
) && ordered_set_isempty(rt
->multipath_routes
)) != (phase
== PHASE_NON_GATEWAY
))
1241 r
= route_configure(rt
, link
, route_handler
, NULL
);
1243 return log_link_warning_errno(link
, r
, "Could not set routes: %m");
1245 link
->route_messages
++;
1248 if (link
->route_messages
== 0) {
1249 link
->static_routes_configured
= true;
1250 link_set_nexthop(link
);
1252 log_link_debug(link
, "Setting routes");
1253 link_set_state(link
, LINK_STATE_CONFIGURING
);
1259 static int process_route_one(Manager
*manager
, Link
*link
, uint16_t type
, const Route
*tmp
, const MultipathRoute
*m
) {
1260 _cleanup_(route_freep
) Route
*nr
= NULL
;
1261 Route
*route
= NULL
;
1266 assert(IN_SET(type
, RTM_NEWROUTE
, RTM_DELROUTE
));
1270 return log_link_warning_errno(link
, SYNTHETIC_ERRNO(EINVAL
),
1271 "rtnl: received route contains both RTA_OIF and RTA_MULTIPATH, ignoring.");
1273 if (m
->ifindex
<= 0)
1274 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
1275 "rtnl: received multipath route with invalid ifindex, ignoring.");
1277 r
= link_get(manager
, m
->ifindex
, &link
);
1279 log_warning_errno(r
, "rtnl: received multipath route for link (%d) we do not know, ignoring: %m", m
->ifindex
);
1287 route_copy(nr
, tmp
, m
);
1292 (void) route_get(manager
, link
, tmp
, &route
);
1297 if (!manager
->manage_foreign_routes
)
1298 log_route_debug(tmp
, "Ignoring received foreign", link
);
1300 /* A route appeared that we did not request */
1301 log_route_debug(tmp
, "Remembering foreign", link
);
1302 r
= route_add_foreign(manager
, link
, tmp
, NULL
);
1304 log_link_warning_errno(link
, r
, "Failed to remember foreign route, ignoring: %m");
1309 log_route_debug(tmp
, "Received remembered", link
);
1314 log_route_debug(tmp
,
1315 route
? "Forgetting" :
1316 manager
->manage_foreign_routes
? "Kernel removed unknown" : "Ignoring received foreign", link
);
1321 assert_not_reached("Received route message with invalid RTNL message type");
1327 int manager_rtnl_process_route(sd_netlink
*rtnl
, sd_netlink_message
*message
, Manager
*m
) {
1328 _cleanup_ordered_set_free_free_ OrderedSet
*multipath_routes
= NULL
;
1329 _cleanup_(route_freep
) Route
*tmp
= NULL
;
1330 _cleanup_free_
void *rta_multipath
= NULL
;
1334 unsigned char table
;
1342 if (sd_netlink_message_is_error(message
)) {
1343 r
= sd_netlink_message_get_errno(message
);
1345 log_message_warning_errno(message
, r
, "rtnl: failed to receive route message, ignoring");
1350 r
= sd_netlink_message_get_type(message
, &type
);
1352 log_warning_errno(r
, "rtnl: could not get message type, ignoring: %m");
1354 } else if (!IN_SET(type
, RTM_NEWROUTE
, RTM_DELROUTE
)) {
1355 log_warning("rtnl: received unexpected message type %u when processing route, ignoring.", type
);
1359 r
= sd_netlink_message_read_u32(message
, RTA_OIF
, &ifindex
);
1360 if (r
< 0 && r
!= -ENODATA
) {
1361 log_warning_errno(r
, "rtnl: could not get ifindex from route message, ignoring: %m");
1363 } else if (r
>= 0) {
1365 log_warning("rtnl: received route message with invalid ifindex %d, ignoring.", ifindex
);
1369 r
= link_get(m
, ifindex
, &link
);
1370 if (r
< 0 || !link
) {
1371 /* when enumerating we might be out of sync, but we will
1372 * get the route again, so just ignore it */
1373 if (!m
->enumerating
)
1374 log_warning("rtnl: received route message for link (%d) we do not know about, ignoring", ifindex
);
1379 r
= route_new(&tmp
);
1383 r
= sd_rtnl_message_route_get_family(message
, &tmp
->family
);
1385 log_link_warning(link
, "rtnl: received route message without family, ignoring");
1387 } else if (!IN_SET(tmp
->family
, AF_INET
, AF_INET6
)) {
1388 log_link_debug(link
, "rtnl: received route message with invalid family '%i', ignoring", tmp
->family
);
1392 r
= sd_rtnl_message_route_get_protocol(message
, &tmp
->protocol
);
1394 log_warning_errno(r
, "rtnl: received route message without route protocol: %m");
1398 r
= netlink_message_read_in_addr_union(message
, RTA_DST
, tmp
->family
, &tmp
->dst
);
1399 if (r
< 0 && r
!= -ENODATA
) {
1400 log_link_warning_errno(link
, r
, "rtnl: received route message without valid destination, ignoring: %m");
1404 r
= netlink_message_read_in_addr_union(message
, RTA_GATEWAY
, tmp
->family
, &tmp
->gw
);
1405 if (r
< 0 && r
!= -ENODATA
) {
1406 log_link_warning_errno(link
, r
, "rtnl: received route message without valid gateway, ignoring: %m");
1409 tmp
->gw_family
= tmp
->family
;
1410 else if (tmp
->family
== AF_INET
) {
1413 r
= sd_netlink_message_read(message
, RTA_VIA
, sizeof(via
), &via
);
1414 if (r
< 0 && r
!= -ENODATA
) {
1415 log_link_warning_errno(link
, r
, "rtnl: received route message without valid gateway, ignoring: %m");
1417 } else if (r
>= 0) {
1418 tmp
->gw_family
= via
.family
;
1419 tmp
->gw
= via
.address
;
1423 r
= netlink_message_read_in_addr_union(message
, RTA_SRC
, tmp
->family
, &tmp
->src
);
1424 if (r
< 0 && r
!= -ENODATA
) {
1425 log_link_warning_errno(link
, r
, "rtnl: received route message without valid source, ignoring: %m");
1429 r
= netlink_message_read_in_addr_union(message
, RTA_PREFSRC
, tmp
->family
, &tmp
->prefsrc
);
1430 if (r
< 0 && r
!= -ENODATA
) {
1431 log_link_warning_errno(link
, r
, "rtnl: received route message without valid preferred source, ignoring: %m");
1435 r
= sd_rtnl_message_route_get_dst_prefixlen(message
, &tmp
->dst_prefixlen
);
1437 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid destination prefixlen, ignoring: %m");
1441 r
= sd_rtnl_message_route_get_src_prefixlen(message
, &tmp
->src_prefixlen
);
1443 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid source prefixlen, ignoring: %m");
1447 r
= sd_rtnl_message_route_get_scope(message
, &tmp
->scope
);
1449 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid scope, ignoring: %m");
1453 r
= sd_rtnl_message_route_get_tos(message
, &tmp
->tos
);
1455 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid tos, ignoring: %m");
1459 r
= sd_rtnl_message_route_get_type(message
, &tmp
->type
);
1461 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid type, ignoring: %m");
1465 r
= sd_rtnl_message_route_get_table(message
, &table
);
1467 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid table, ignoring: %m");
1472 r
= sd_netlink_message_read_u32(message
, RTA_PRIORITY
, &tmp
->priority
);
1473 if (r
< 0 && r
!= -ENODATA
) {
1474 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid priority, ignoring: %m");
1478 r
= sd_netlink_message_enter_container(message
, RTA_METRICS
);
1479 if (r
< 0 && r
!= -ENODATA
) {
1480 log_link_error_errno(link
, r
, "rtnl: Could not enter RTA_METRICS container: %m");
1484 r
= sd_netlink_message_read_u32(message
, RTAX_INITCWND
, &tmp
->initcwnd
);
1485 if (r
< 0 && r
!= -ENODATA
) {
1486 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid initcwnd, ignoring: %m");
1490 r
= sd_netlink_message_read_u32(message
, RTAX_INITRWND
, &tmp
->initrwnd
);
1491 if (r
< 0 && r
!= -ENODATA
) {
1492 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid initrwnd, ignoring: %m");
1496 r
= sd_netlink_message_read_u32(message
, RTAX_ADVMSS
, &tmp
->advmss
);
1497 if (r
< 0 && r
!= -ENODATA
) {
1498 log_link_warning_errno(link
, r
, "rtnl: received route message with invalid advmss, ignoring: %m");
1502 r
= sd_netlink_message_exit_container(message
);
1504 log_link_error_errno(link
, r
, "rtnl: Could not exit from RTA_METRICS container: %m");
1509 r
= sd_netlink_message_read_data(message
, RTA_MULTIPATH
, &rta_len
, &rta_multipath
);
1510 if (r
< 0 && r
!= -ENODATA
) {
1511 log_link_warning_errno(link
, r
, "rtnl: failed to read RTA_MULTIPATH attribute, ignoring: %m");
1513 } else if (r
>= 0) {
1514 r
= rtattr_read_nexthop(rta_multipath
, rta_len
, tmp
->family
, &multipath_routes
);
1516 log_link_warning_errno(link
, r
, "rtnl: failed to parse RTA_MULTIPATH attribute, ignoring: %m");
1521 /* IPv6 routes with reject type are always assigned to the loopback interface. See kernel's
1522 * fib6_nh_init() in net/ipv6/route.c. However, we'd like to manage them by Manager. Hence, set
1523 * link to NULL here. */
1524 if (route_type_is_reject(tmp
))
1527 if (ordered_set_isempty(multipath_routes
))
1528 (void) process_route_one(m
, link
, type
, tmp
, NULL
);
1532 ORDERED_SET_FOREACH(mr
, multipath_routes
) {
1533 r
= process_route_one(m
, link
, type
, tmp
, mr
);
1542 int network_add_ipv4ll_route(Network
*network
) {
1543 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1544 unsigned section_line
;
1549 if (!network
->ipv4ll_route
)
1552 section_line
= hashmap_find_free_section_line(network
->routes_by_section
);
1554 /* IPv4LLRoute= is in [Network] section. */
1555 r
= route_new_static(network
, network
->filename
, section_line
, &n
);
1559 r
= in_addr_from_string(AF_INET
, "169.254.0.0", &n
->dst
);
1563 n
->family
= AF_INET
;
1564 n
->dst_prefixlen
= 16;
1565 n
->scope
= RT_SCOPE_LINK
;
1566 n
->scope_set
= true;
1567 n
->table_set
= true;
1568 n
->priority
= IPV4LL_ROUTE_METRIC
;
1569 n
->protocol
= RTPROT_STATIC
;
1575 int network_add_default_route_on_device(Network
*network
) {
1576 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1577 unsigned section_line
;
1582 if (!network
->default_route_on_device
)
1585 section_line
= hashmap_find_free_section_line(network
->routes_by_section
);
1587 /* DefaultRouteOnDevice= is in [Network] section. */
1588 r
= route_new_static(network
, network
->filename
, section_line
, &n
);
1592 n
->family
= AF_INET
;
1593 n
->scope
= RT_SCOPE_LINK
;
1594 n
->scope_set
= true;
1595 n
->protocol
= RTPROT_STATIC
;
1601 int config_parse_gateway(
1603 const char *filename
,
1605 const char *section
,
1606 unsigned section_line
,
1613 Network
*network
= userdata
;
1614 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1623 if (streq(section
, "Network")) {
1624 /* we are not in an Route section, so use line number instead */
1625 r
= route_new_static(network
, filename
, line
, &n
);
1629 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1630 "Failed to allocate route, ignoring assignment: %m");
1634 r
= route_new_static(network
, filename
, section_line
, &n
);
1638 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1639 "Failed to allocate route, ignoring assignment: %m");
1643 if (isempty(rvalue
)) {
1644 n
->gateway_from_dhcp_or_ra
= false;
1645 n
->gw_family
= AF_UNSPEC
;
1646 n
->gw
= IN_ADDR_NULL
;
1651 if (streq(rvalue
, "_dhcp")) {
1652 n
->gateway_from_dhcp_or_ra
= true;
1657 if (streq(rvalue
, "_dhcp4")) {
1658 n
->gw_family
= AF_INET
;
1659 n
->gateway_from_dhcp_or_ra
= true;
1664 if (streq(rvalue
, "_ipv6ra")) {
1665 n
->gw_family
= AF_INET6
;
1666 n
->gateway_from_dhcp_or_ra
= true;
1672 r
= in_addr_from_string_auto(rvalue
, &n
->gw_family
, &n
->gw
);
1674 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1675 "Invalid %s='%s', ignoring assignment: %m", lvalue
, rvalue
);
1679 n
->gateway_from_dhcp_or_ra
= false;
1684 int config_parse_preferred_src(
1686 const char *filename
,
1688 const char *section
,
1689 unsigned section_line
,
1696 Network
*network
= userdata
;
1697 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1706 r
= route_new_static(network
, filename
, section_line
, &n
);
1710 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1711 "Failed to allocate route, ignoring assignment: %m");
1715 if (n
->family
== AF_UNSPEC
)
1716 r
= in_addr_from_string_auto(rvalue
, &n
->family
, &n
->prefsrc
);
1718 r
= in_addr_from_string(n
->family
, rvalue
, &n
->prefsrc
);
1720 log_syntax(unit
, LOG_WARNING
, filename
, line
, EINVAL
,
1721 "Invalid %s='%s', ignoring assignment: %m", lvalue
, rvalue
);
1729 int config_parse_destination(
1731 const char *filename
,
1733 const char *section
,
1734 unsigned section_line
,
1741 Network
*network
= userdata
;
1742 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1743 union in_addr_union
*buffer
;
1744 unsigned char *prefixlen
;
1753 r
= route_new_static(network
, filename
, section_line
, &n
);
1757 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1758 "Failed to allocate route, ignoring assignment: %m");
1762 if (streq(lvalue
, "Destination")) {
1764 prefixlen
= &n
->dst_prefixlen
;
1765 } else if (streq(lvalue
, "Source")) {
1767 prefixlen
= &n
->src_prefixlen
;
1769 assert_not_reached(lvalue
);
1771 if (n
->family
== AF_UNSPEC
)
1772 r
= in_addr_prefix_from_string_auto(rvalue
, &n
->family
, buffer
, prefixlen
);
1774 r
= in_addr_prefix_from_string(rvalue
, n
->family
, buffer
, prefixlen
);
1776 log_syntax(unit
, LOG_WARNING
, filename
, line
, EINVAL
,
1777 "Invalid %s='%s', ignoring assignment: %m", lvalue
, rvalue
);
1785 int config_parse_route_priority(
1787 const char *filename
,
1789 const char *section
,
1790 unsigned section_line
,
1797 Network
*network
= userdata
;
1798 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1807 r
= route_new_static(network
, filename
, section_line
, &n
);
1811 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1812 "Failed to allocate route, ignoring assignment: %m");
1816 r
= safe_atou32(rvalue
, &n
->priority
);
1818 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1819 "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue
);
1823 n
->priority_set
= true;
1828 int config_parse_route_scope(
1830 const char *filename
,
1832 const char *section
,
1833 unsigned section_line
,
1840 Network
*network
= userdata
;
1841 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1850 r
= route_new_static(network
, filename
, section_line
, &n
);
1854 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1855 "Failed to allocate route, ignoring assignment: %m");
1859 r
= route_scope_from_string(rvalue
);
1861 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "Unknown route scope: %s", rvalue
);
1866 n
->scope_set
= true;
1871 int config_parse_route_table(
1873 const char *filename
,
1875 const char *section
,
1876 unsigned section_line
,
1883 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1884 Network
*network
= userdata
;
1893 r
= route_new_static(network
, filename
, section_line
, &n
);
1897 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1898 "Failed to allocate route, ignoring assignment: %m");
1902 r
= route_table_from_string(rvalue
);
1906 r
= safe_atou32(rvalue
, &n
->table
);
1908 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1909 "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue
);
1914 n
->table_set
= true;
1919 int config_parse_route_boolean(
1921 const char *filename
,
1923 const char *section
,
1924 unsigned section_line
,
1931 Network
*network
= userdata
;
1932 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1941 r
= route_new_static(network
, filename
, section_line
, &n
);
1945 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1946 "Failed to allocate route, ignoring assignment: %m");
1950 r
= parse_boolean(rvalue
);
1952 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1953 "Could not parse %s=\"%s\", ignoring assignment: %m", lvalue
, rvalue
);
1957 if (STR_IN_SET(lvalue
, "GatewayOnLink", "GatewayOnlink"))
1958 n
->gateway_onlink
= r
;
1959 else if (streq(lvalue
, "QuickAck"))
1961 else if (streq(lvalue
, "FastOpenNoCookie"))
1962 n
->fast_open_no_cookie
= r
;
1963 else if (streq(lvalue
, "TTLPropagate"))
1964 n
->ttl_propagate
= r
;
1966 assert_not_reached("Invalid lvalue");
1972 int config_parse_ipv6_route_preference(
1974 const char *filename
,
1976 const char *section
,
1977 unsigned section_line
,
1984 Network
*network
= userdata
;
1985 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
1988 r
= route_new_static(network
, filename
, section_line
, &n
);
1992 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1993 "Failed to allocate route, ignoring assignment: %m");
1997 if (streq(rvalue
, "low"))
1998 n
->pref
= ICMPV6_ROUTER_PREF_LOW
;
1999 else if (streq(rvalue
, "medium"))
2000 n
->pref
= ICMPV6_ROUTER_PREF_MEDIUM
;
2001 else if (streq(rvalue
, "high"))
2002 n
->pref
= ICMPV6_ROUTER_PREF_HIGH
;
2004 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "Unknown route preference: %s", rvalue
);
2013 int config_parse_route_protocol(
2015 const char *filename
,
2017 const char *section
,
2018 unsigned section_line
,
2025 Network
*network
= userdata
;
2026 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
2029 r
= route_new_static(network
, filename
, section_line
, &n
);
2033 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2034 "Failed to allocate route, ignoring assignment: %m");
2038 r
= route_protocol_from_string(rvalue
);
2042 r
= safe_atou8(rvalue
, &n
->protocol
);
2044 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2045 "Could not parse route protocol \"%s\", ignoring assignment: %m", rvalue
);
2054 int config_parse_route_type(
2056 const char *filename
,
2058 const char *section
,
2059 unsigned section_line
,
2066 Network
*network
= userdata
;
2067 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
2070 r
= route_new_static(network
, filename
, section_line
, &n
);
2074 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2075 "Failed to allocate route, ignoring assignment: %m");
2079 t
= route_type_from_string(rvalue
);
2081 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
2082 "Could not parse route type \"%s\", ignoring assignment: %m", rvalue
);
2086 n
->type
= (unsigned char) t
;
2092 int config_parse_tcp_advmss(
2094 const char *filename
,
2096 const char *section
,
2097 unsigned section_line
,
2104 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
2105 Network
*network
= userdata
;
2115 r
= route_new_static(network
, filename
, section_line
, &n
);
2119 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2120 "Failed to allocate route, ignoring assignment: %m");
2124 if (isempty(rvalue
)) {
2130 r
= parse_size(rvalue
, 1024, &u
);
2132 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2133 "Could not parse TCPAdvertisedMaximumSegmentSize= \"%s\", ignoring assignment: %m", rvalue
);
2137 if (u
== 0 || u
> UINT32_MAX
) {
2138 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
2139 "Invalid TCPAdvertisedMaximumSegmentSize= \"%s\", ignoring assignment: %m", rvalue
);
2149 int config_parse_tcp_window(
2151 const char *filename
,
2153 const char *section
,
2154 unsigned section_line
,
2161 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
2162 Network
*network
= userdata
;
2172 r
= route_new_static(network
, filename
, section_line
, &n
);
2176 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2177 "Failed to allocate route, ignoring assignment: %m");
2181 r
= safe_atou32(rvalue
, &k
);
2183 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2184 "Could not parse TCP %s \"%s\", ignoring assignment: %m", lvalue
, rvalue
);
2188 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
2189 "Specified TCP %s \"%s\" is too large, ignoring assignment: %m", lvalue
, rvalue
);
2193 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
2194 "Invalid TCP %s \"%s\", ignoring assignment: %m", lvalue
, rvalue
);
2198 if (streq(lvalue
, "InitialCongestionWindow"))
2200 else if (streq(lvalue
, "InitialAdvertisedReceiveWindow"))
2203 assert_not_reached("Invalid TCP window type.");
2209 int config_parse_route_mtu(
2211 const char *filename
,
2213 const char *section
,
2214 unsigned section_line
,
2221 Network
*network
= userdata
;
2222 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
2231 r
= route_new_static(network
, filename
, section_line
, &n
);
2235 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2236 "Failed to allocate route, ignoring assignment: %m");
2240 r
= config_parse_mtu(unit
, filename
, line
, section
, section_line
, lvalue
, ltype
, rvalue
, &n
->mtu
, userdata
);
2248 int config_parse_multipath_route(
2250 const char *filename
,
2252 const char *section
,
2253 unsigned section_line
,
2260 _cleanup_(route_free_or_set_invalidp
) Route
*n
= NULL
;
2261 _cleanup_free_
char *word
= NULL
, *buf
= NULL
;
2262 _cleanup_free_ MultipathRoute
*m
= NULL
;
2263 Network
*network
= userdata
;
2264 const char *p
, *ip
, *dev
;
2265 union in_addr_union a
;
2274 r
= route_new_static(network
, filename
, section_line
, &n
);
2278 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2279 "Failed to allocate route, ignoring assignment: %m");
2283 if (isempty(rvalue
)) {
2284 n
->multipath_routes
= ordered_set_free_free(n
->multipath_routes
);
2288 m
= new0(MultipathRoute
, 1);
2293 r
= extract_first_word(&p
, &word
, NULL
, 0);
2297 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2298 "Invalid multipath route option, ignoring assignment: %s", rvalue
);
2302 dev
= strchr(word
, '@');
2304 buf
= strndup(word
, dev
- word
);
2312 r
= in_addr_from_string_auto(ip
, &family
, &a
);
2314 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2315 "Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue
);
2318 m
->gateway
.address
= a
;
2319 m
->gateway
.family
= family
;
2322 r
= resolve_interface(NULL
, dev
);
2324 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2325 "Invalid interface name or index, ignoring assignment: %s", dev
);
2332 r
= safe_atou32(p
, &m
->weight
);
2334 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2335 "Invalid multipath route weight, ignoring assignment: %s", p
);
2338 if (m
->weight
== 0 || m
->weight
> 256) {
2339 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
2340 "Invalid multipath route weight, ignoring assignment: %s", p
);
2345 r
= ordered_set_ensure_put(&n
->multipath_routes
, NULL
, m
);
2349 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
2350 "Failed to store multipath route, ignoring assignment: %m");
2359 static int route_section_verify(Route
*route
, Network
*network
) {
2360 if (section_is_invalid(route
->section
))
2363 if (route
->gateway_from_dhcp_or_ra
) {
2364 if (route
->gw_family
== AF_UNSPEC
) {
2365 /* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */
2366 switch (route
->family
) {
2368 log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
2369 "Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".",
2370 route
->section
->filename
, route
->section
->line
);
2371 route
->family
= AF_INET
;
2375 log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
2376 "Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.",
2377 route
->section
->filename
, route
->section
->line
, route
->family
== AF_INET
? "_dhcp4" : "_ipv6ra");
2380 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
2381 "%s: Invalid route family. Ignoring [Route] section from line %u.",
2382 route
->section
->filename
, route
->section
->line
);
2384 route
->gw_family
= route
->family
;
2387 if (route
->gw_family
== AF_INET
&& !FLAGS_SET(network
->dhcp
, ADDRESS_FAMILY_IPV4
))
2388 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
2389 "%s: Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled. "
2390 "Ignoring [Route] section from line %u.",
2391 route
->section
->filename
, route
->section
->line
);
2393 if (route
->gw_family
== AF_INET6
&& !network
->ipv6_accept_ra
)
2394 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
2395 "%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. "
2396 "Ignoring [Route] section from line %u.",
2397 route
->section
->filename
, route
->section
->line
);
2400 /* When only Gateway= is specified, assume the route family based on the Gateway address. */
2401 if (route
->family
== AF_UNSPEC
)
2402 route
->family
= route
->gw_family
;
2404 if (route
->family
== AF_UNSPEC
) {
2405 assert(route
->section
);
2407 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
2408 "%s: Route section without Gateway=, Destination=, Source=, "
2409 "or PreferredSource= field configured. "
2410 "Ignoring [Route] section from line %u.",
2411 route
->section
->filename
, route
->section
->line
);
2414 if (route
->family
== AF_INET6
&& route
->gw_family
== AF_INET
)
2415 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
2416 "%s: IPv4 gateway is configured for IPv6 route. "
2417 "Ignoring [Route] section from line %u.",
2418 route
->section
->filename
, route
->section
->line
);
2420 if (!route
->table_set
&& network
->vrf
) {
2421 route
->table
= VRF(network
->vrf
)->table
;
2422 route
->table_set
= true;
2425 if (!route
->table_set
&& IN_SET(route
->type
, RTN_LOCAL
, RTN_BROADCAST
, RTN_ANYCAST
, RTN_NAT
))
2426 route
->table
= RT_TABLE_LOCAL
;
2428 if (!route
->scope_set
&& route
->family
!= AF_INET6
) {
2429 if (IN_SET(route
->type
, RTN_LOCAL
, RTN_NAT
))
2430 route
->scope
= RT_SCOPE_HOST
;
2431 else if (IN_SET(route
->type
, RTN_BROADCAST
, RTN_ANYCAST
, RTN_MULTICAST
))
2432 route
->scope
= RT_SCOPE_LINK
;
2435 if (route
->scope
!= RT_SCOPE_UNIVERSE
&& route
->family
== AF_INET6
) {
2436 log_warning("%s: Scope= is specified for IPv6 route. It will be ignored.", route
->section
->filename
);
2437 route
->scope
= RT_SCOPE_UNIVERSE
;
2440 if (route
->family
== AF_INET6
&& route
->priority
== 0)
2441 route
->priority
= IP6_RT_PRIO_USER
;
2443 if (ordered_hashmap_isempty(network
->addresses_by_section
) &&
2444 in_addr_is_null(route
->gw_family
, &route
->gw
) == 0 &&
2445 route
->gateway_onlink
< 0) {
2446 log_warning("%s: Gateway= without static address configured. "
2447 "Enabling GatewayOnLink= option.",
2449 route
->gateway_onlink
= true;
2455 void network_drop_invalid_routes(Network
*network
) {
2460 HASHMAP_FOREACH(route
, network
->routes_by_section
)
2461 if (route_section_verify(route
, network
) < 0)