1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <linux/fib_rules.h>
7 #include "alloc-util.h"
8 #include "conf-parser.h"
10 #include "format-util.h"
12 #include "ip-protocol-list.h"
13 #include "netlink-util.h"
14 #include "networkd-manager.h"
15 #include "networkd-queue.h"
16 #include "networkd-route-util.h"
17 #include "networkd-routing-policy-rule.h"
18 #include "networkd-util.h"
19 #include "parse-util.h"
20 #include "socket-util.h"
21 #include "string-table.h"
22 #include "string-util.h"
24 #include "user-util.h"
26 static const char *const fr_act_type_table
[__FR_ACT_MAX
] = {
27 [FR_ACT_BLACKHOLE
] = "blackhole",
28 [FR_ACT_UNREACHABLE
] = "unreachable",
29 [FR_ACT_PROHIBIT
] = "prohibit",
32 static const char *const fr_act_type_full_table
[__FR_ACT_MAX
] = {
33 [FR_ACT_TO_TBL
] = "table",
34 [FR_ACT_GOTO
] = "goto",
36 [FR_ACT_BLACKHOLE
] = "blackhole",
37 [FR_ACT_UNREACHABLE
] = "unreachable",
38 [FR_ACT_PROHIBIT
] = "prohibit",
41 assert_cc(__FR_ACT_MAX
<= UINT8_MAX
);
42 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fr_act_type
, int);
43 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(fr_act_type_full
, int);
45 RoutingPolicyRule
*routing_policy_rule_free(RoutingPolicyRule
*rule
) {
50 assert(rule
->section
);
51 hashmap_remove(rule
->network
->rules_by_section
, rule
->section
);
55 set_remove(rule
->manager
->rules
, rule
);
57 config_section_free(rule
->section
);
64 DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutingPolicyRule
, routing_policy_rule_free
);
66 static int routing_policy_rule_new(RoutingPolicyRule
**ret
) {
67 RoutingPolicyRule
*rule
;
69 rule
= new(RoutingPolicyRule
, 1);
73 *rule
= (RoutingPolicyRule
) {
74 .table
= RT_TABLE_MAIN
,
75 .uid_range
.start
= UID_INVALID
,
76 .uid_range
.end
= UID_INVALID
,
77 .suppress_prefixlen
= -1,
78 .suppress_ifgroup
= -1,
79 .protocol
= RTPROT_UNSPEC
,
80 .type
= FR_ACT_TO_TBL
,
87 static int routing_policy_rule_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutingPolicyRule
**ret
) {
88 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
89 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
95 assert(section_line
> 0);
97 r
= config_section_new(filename
, section_line
, &n
);
101 rule
= hashmap_get(network
->rules_by_section
, n
);
103 *ret
= TAKE_PTR(rule
);
107 r
= routing_policy_rule_new(&rule
);
111 rule
->network
= network
;
112 rule
->section
= TAKE_PTR(n
);
113 rule
->source
= NETWORK_CONFIG_SOURCE_STATIC
;
114 rule
->protocol
= RTPROT_STATIC
;
116 r
= hashmap_ensure_put(&network
->rules_by_section
, &config_section_hash_ops
, rule
->section
, rule
);
120 *ret
= TAKE_PTR(rule
);
124 static int routing_policy_rule_dup(const RoutingPolicyRule
*src
, RoutingPolicyRule
**ret
) {
125 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*dest
= NULL
;
130 dest
= newdup(RoutingPolicyRule
, src
, 1);
134 /* Unset all pointers */
135 dest
->manager
= NULL
;
136 dest
->network
= NULL
;
137 dest
->section
= NULL
;
138 dest
->iif
= dest
->oif
= NULL
;
141 dest
->iif
= strdup(src
->iif
);
147 dest
->oif
= strdup(src
->oif
);
152 *ret
= TAKE_PTR(dest
);
156 static void routing_policy_rule_hash_func(const RoutingPolicyRule
*rule
, struct siphash
*state
) {
159 siphash24_compress_typesafe(rule
->family
, state
);
161 switch (rule
->family
) {
164 in_addr_hash_func(&rule
->from
, rule
->family
, state
);
165 siphash24_compress_typesafe(rule
->from_prefixlen
, state
);
167 in_addr_hash_func(&rule
->to
, rule
->family
, state
);
168 siphash24_compress_typesafe(rule
->to_prefixlen
, state
);
170 siphash24_compress_boolean(rule
->invert_rule
, state
);
172 siphash24_compress_typesafe(rule
->tos
, state
);
173 siphash24_compress_typesafe(rule
->type
, state
);
174 siphash24_compress_typesafe(rule
->fwmark
, state
);
175 siphash24_compress_typesafe(rule
->fwmask
, state
);
176 siphash24_compress_typesafe(rule
->priority
, state
);
177 siphash24_compress_typesafe(rule
->table
, state
);
178 siphash24_compress_typesafe(rule
->suppress_prefixlen
, state
);
179 siphash24_compress_typesafe(rule
->suppress_ifgroup
, state
);
181 siphash24_compress_typesafe(rule
->ipproto
, state
);
182 siphash24_compress_typesafe(rule
->protocol
, state
);
183 siphash24_compress_typesafe(rule
->sport
, state
);
184 siphash24_compress_typesafe(rule
->dport
, state
);
185 siphash24_compress_typesafe(rule
->uid_range
, state
);
187 siphash24_compress_string(rule
->iif
, state
);
188 siphash24_compress_string(rule
->oif
, state
);
192 /* treat any other address family as AF_UNSPEC */
197 static int routing_policy_rule_compare_func(const RoutingPolicyRule
*a
, const RoutingPolicyRule
*b
) {
200 r
= CMP(a
->family
, b
->family
);
207 r
= CMP(a
->from_prefixlen
, b
->from_prefixlen
);
211 r
= memcmp(&a
->from
, &b
->from
, FAMILY_ADDRESS_SIZE(a
->family
));
215 r
= CMP(a
->to_prefixlen
, b
->to_prefixlen
);
219 r
= memcmp(&a
->to
, &b
->to
, FAMILY_ADDRESS_SIZE(a
->family
));
223 r
= CMP(a
->invert_rule
, b
->invert_rule
);
227 r
= CMP(a
->tos
, b
->tos
);
231 r
= CMP(a
->type
, b
->type
);
235 r
= CMP(a
->fwmark
, b
->fwmark
);
239 r
= CMP(a
->fwmask
, b
->fwmask
);
243 r
= CMP(a
->priority
, b
->priority
);
247 r
= CMP(a
->table
, b
->table
);
251 r
= CMP(a
->suppress_prefixlen
, b
->suppress_prefixlen
);
255 r
= CMP(a
->suppress_ifgroup
, b
->suppress_ifgroup
);
259 r
= CMP(a
->ipproto
, b
->ipproto
);
263 r
= CMP(a
->protocol
, b
->protocol
);
267 r
= memcmp(&a
->sport
, &b
->sport
, sizeof(a
->sport
));
271 r
= memcmp(&a
->dport
, &b
->dport
, sizeof(a
->dport
));
275 r
= memcmp(&a
->uid_range
, &b
->uid_range
, sizeof(a
->uid_range
));
279 r
= strcmp_ptr(a
->iif
, b
->iif
);
283 r
= strcmp_ptr(a
->oif
, b
->oif
);
289 /* treat any other address family as AF_UNSPEC */
294 static bool routing_policy_rule_equal(const RoutingPolicyRule
*rule1
, const RoutingPolicyRule
*rule2
) {
298 if (!rule1
|| !rule2
)
301 return routing_policy_rule_compare_func(rule1
, rule2
) == 0;
304 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
305 routing_policy_rule_hash_ops
,
307 routing_policy_rule_hash_func
,
308 routing_policy_rule_compare_func
,
309 routing_policy_rule_free
);
311 static int routing_policy_rule_get(Manager
*m
, const RoutingPolicyRule
*in
, RoutingPolicyRule
**ret
) {
312 RoutingPolicyRule
*rule
;
317 rule
= set_get(m
->rules
, in
);
324 if (in
->priority_set
)
327 /* Also find rules configured without priority. */
328 SET_FOREACH(rule
, m
->rules
) {
332 if (rule
->priority_set
)
333 /* The rule is configured with priority. */
336 priority
= rule
->priority
;
338 found
= routing_policy_rule_equal(rule
, in
);
339 rule
->priority
= priority
;
351 static int routing_policy_rule_add(Manager
*m
, RoutingPolicyRule
*rule
) {
356 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
358 r
= set_ensure_put(&m
->rules
, &routing_policy_rule_hash_ops
, rule
);
368 static int routing_policy_rule_acquire_priority(Manager
*manager
, RoutingPolicyRule
*rule
) {
369 _cleanup_set_free_ Set
*priorities
= NULL
;
370 RoutingPolicyRule
*tmp
;
377 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
379 if (rule
->priority_set
)
382 /* Find the highest unused priority. Note that 32766 is already used by kernel.
383 * See kernel_rules[] below. */
385 SET_FOREACH(tmp
, manager
->rules
) {
386 if (tmp
->family
!= rule
->family
)
388 if (tmp
->priority
== 0 || tmp
->priority
> 32765)
390 r
= set_ensure_put(&priorities
, NULL
, UINT32_TO_PTR(tmp
->priority
));
395 ORDERED_HASHMAP_FOREACH(network
, manager
->networks
)
396 HASHMAP_FOREACH(tmp
, network
->rules_by_section
) {
397 if (tmp
->family
!= AF_UNSPEC
&& tmp
->family
!= rule
->family
)
399 if (!tmp
->priority_set
)
401 if (tmp
->priority
== 0 || tmp
->priority
> 32765)
403 r
= set_ensure_put(&priorities
, NULL
, UINT32_TO_PTR(tmp
->priority
));
408 for (priority
= 32765; priority
> 0; priority
--)
409 if (!set_contains(priorities
, UINT32_TO_PTR(priority
)))
412 rule
->priority
= priority
;
416 static void log_routing_policy_rule_debug(const RoutingPolicyRule
*rule
, const char *str
, const Link
*link
, const Manager
*m
) {
417 _cleanup_free_
char *state
= NULL
, *table
= NULL
;
420 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
424 /* link may be NULL. */
429 (void) network_config_state_to_string_alloc(rule
->state
, &state
);
430 (void) manager_get_route_table_to_string(m
, rule
->table
, /* append_num = */ true, &table
);
433 "%s %s routing policy rule (%s): priority: %"PRIu32
", %s -> %s, iif: %s, oif: %s, table: %s",
434 str
, strna(network_config_source_to_string(rule
->source
)), strna(state
),
436 IN_ADDR_PREFIX_TO_STRING(rule
->family
, &rule
->from
, rule
->from_prefixlen
),
437 IN_ADDR_PREFIX_TO_STRING(rule
->family
, &rule
->to
, rule
->to_prefixlen
),
438 strna(rule
->iif
), strna(rule
->oif
), strna(table
));
441 static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule
*rule
, sd_netlink_message
*m
, Link
*link
) {
447 /* link may be NULL. */
449 if (rule
->from_prefixlen
> 0) {
450 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, rule
->family
, &rule
->from
);
454 r
= sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(m
, rule
->from_prefixlen
);
459 if (rule
->to_prefixlen
> 0) {
460 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, rule
->family
, &rule
->to
);
464 r
= sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(m
, rule
->to_prefixlen
);
469 r
= sd_netlink_message_append_u32(m
, FRA_PRIORITY
, rule
->priority
);
474 r
= sd_rtnl_message_routing_policy_rule_set_tos(m
, rule
->tos
);
479 if (rule
->table
< 256) {
480 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, rule
->table
);
484 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
488 r
= sd_netlink_message_append_u32(m
, FRA_TABLE
, rule
->table
);
493 if (rule
->fwmark
> 0) {
494 r
= sd_netlink_message_append_u32(m
, FRA_FWMARK
, rule
->fwmark
);
498 r
= sd_netlink_message_append_u32(m
, FRA_FWMASK
, rule
->fwmask
);
504 r
= sd_netlink_message_append_string(m
, FRA_IIFNAME
, rule
->iif
);
510 r
= sd_netlink_message_append_string(m
, FRA_OIFNAME
, rule
->oif
);
515 r
= sd_netlink_message_append_u8(m
, FRA_IP_PROTO
, rule
->ipproto
);
519 r
= sd_netlink_message_append_u8(m
, FRA_PROTOCOL
, rule
->protocol
);
523 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
524 r
= sd_netlink_message_append_data(m
, FRA_SPORT_RANGE
, &rule
->sport
, sizeof(rule
->sport
));
529 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
530 r
= sd_netlink_message_append_data(m
, FRA_DPORT_RANGE
, &rule
->dport
, sizeof(rule
->dport
));
535 if (rule
->uid_range
.start
!= UID_INVALID
&& rule
->uid_range
.end
!= UID_INVALID
) {
536 r
= sd_netlink_message_append_data(m
, FRA_UID_RANGE
, &rule
->uid_range
, sizeof(rule
->uid_range
));
541 if (rule
->invert_rule
) {
542 r
= sd_rtnl_message_routing_policy_rule_set_flags(m
, FIB_RULE_INVERT
);
547 if (rule
->suppress_prefixlen
>= 0) {
548 r
= sd_netlink_message_append_u32(m
, FRA_SUPPRESS_PREFIXLEN
, (uint32_t) rule
->suppress_prefixlen
);
553 if (rule
->suppress_ifgroup
>= 0) {
554 r
= sd_netlink_message_append_u32(m
, FRA_SUPPRESS_IFGROUP
, (uint32_t) rule
->suppress_ifgroup
);
559 r
= sd_rtnl_message_routing_policy_rule_set_fib_type(m
, rule
->type
);
566 static int routing_policy_rule_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
571 r
= sd_netlink_message_get_errno(m
);
573 log_message_warning_errno(m
, r
, "Could not drop routing policy rule");
578 static int routing_policy_rule_remove(RoutingPolicyRule
*rule
) {
579 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
583 assert(rule
->manager
);
584 assert(rule
->manager
->rtnl
);
585 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
587 log_routing_policy_rule_debug(rule
, "Removing", NULL
, rule
->manager
);
589 r
= sd_rtnl_message_new_routing_policy_rule(rule
->manager
->rtnl
, &m
, RTM_DELRULE
, rule
->family
);
591 return log_warning_errno(r
, "Could not allocate netlink message: %m");
593 r
= routing_policy_rule_set_netlink_message(rule
, m
, NULL
);
595 return log_warning_errno(r
, "Could not create netlink message: %m");
597 r
= netlink_call_async(rule
->manager
->rtnl
, NULL
, m
,
598 routing_policy_rule_remove_handler
,
601 return log_warning_errno(r
, "Could not send netlink message: %m");
603 routing_policy_rule_enter_removing(rule
);
607 static int routing_policy_rule_configure(RoutingPolicyRule
*rule
, Link
*link
, Request
*req
) {
608 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
612 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
614 assert(link
->ifindex
> 0);
615 assert(link
->manager
);
616 assert(link
->manager
->rtnl
);
619 log_routing_policy_rule_debug(rule
, "Configuring", link
, link
->manager
);
621 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_NEWRULE
, rule
->family
);
625 r
= routing_policy_rule_set_netlink_message(rule
, m
, link
);
629 return request_call_netlink_async(link
->manager
->rtnl
, m
, req
);
632 static void manager_mark_routing_policy_rules(Manager
*m
, bool foreign
, const Link
*except
) {
633 RoutingPolicyRule
*rule
;
638 /* First, mark all existing rules. */
639 SET_FOREACH(rule
, m
->rules
) {
640 /* Do not touch rules managed by kernel. */
641 if (rule
->protocol
== RTPROT_KERNEL
)
644 /* When 'foreign' is true, mark only foreign rules, and vice versa. */
645 if (foreign
!= (rule
->source
== NETWORK_CONFIG_SOURCE_FOREIGN
))
648 /* Ignore rules not assigned yet or already removing. */
649 if (!routing_policy_rule_exists(rule
))
652 routing_policy_rule_mark(rule
);
655 /* Then, unmark all rules requested by active links. */
656 HASHMAP_FOREACH(link
, m
->links_by_index
) {
660 if (!IN_SET(link
->state
, LINK_STATE_CONFIGURING
, LINK_STATE_CONFIGURED
))
663 HASHMAP_FOREACH(rule
, link
->network
->rules_by_section
) {
664 RoutingPolicyRule
*existing
;
666 if (IN_SET(rule
->family
, AF_INET
, AF_INET6
)) {
667 if (routing_policy_rule_get(m
, rule
, &existing
) >= 0)
668 routing_policy_rule_unmark(existing
);
670 /* The case Family=both. */
671 rule
->family
= AF_INET
;
672 if (routing_policy_rule_get(m
, rule
, &existing
) >= 0)
673 routing_policy_rule_unmark(existing
);
675 rule
->family
= AF_INET6
;
676 if (routing_policy_rule_get(m
, rule
, &existing
) >= 0)
677 routing_policy_rule_unmark(existing
);
679 rule
->family
= AF_UNSPEC
;
685 int manager_drop_routing_policy_rules_internal(Manager
*m
, bool foreign
, const Link
*except
) {
686 RoutingPolicyRule
*rule
;
691 manager_mark_routing_policy_rules(m
, foreign
, except
);
693 SET_FOREACH(rule
, m
->rules
) {
694 if (!routing_policy_rule_is_marked(rule
))
697 RET_GATHER(r
, routing_policy_rule_remove(rule
));
703 void link_foreignize_routing_policy_rules(Link
*link
) {
704 RoutingPolicyRule
*rule
;
707 assert(link
->manager
);
709 manager_mark_routing_policy_rules(link
->manager
, /* foreign = */ false, link
);
711 SET_FOREACH(rule
, link
->manager
->rules
) {
712 if (!routing_policy_rule_is_marked(rule
))
715 rule
->source
= NETWORK_CONFIG_SOURCE_FOREIGN
;
719 static int routing_policy_rule_process_request(Request
*req
, Link
*link
, RoutingPolicyRule
*rule
) {
726 if (!link_is_ready_to_configure(link
, false))
729 r
= routing_policy_rule_configure(rule
, link
, req
);
731 return log_link_warning_errno(link
, r
, "Failed to configure routing policy rule: %m");
733 routing_policy_rule_enter_configuring(rule
);
737 static int static_routing_policy_rule_configure_handler(
739 sd_netlink_message
*m
,
742 RoutingPolicyRule
*rule
) {
749 r
= sd_netlink_message_get_errno(m
);
750 if (r
< 0 && r
!= -EEXIST
) {
751 log_link_message_warning_errno(link
, m
, r
, "Could not add routing policy rule");
752 link_enter_failed(link
);
756 if (link
->static_routing_policy_rule_messages
== 0) {
757 log_link_debug(link
, "Routing policy rule configured");
758 link
->static_routing_policy_rules_configured
= true;
759 link_check_ready(link
);
765 static int link_request_routing_policy_rule(Link
*link
, RoutingPolicyRule
*rule
) {
766 RoutingPolicyRule
*existing
;
770 assert(link
->manager
);
772 assert(rule
->source
!= NETWORK_CONFIG_SOURCE_FOREIGN
);
774 if (routing_policy_rule_get(link
->manager
, rule
, &existing
) < 0) {
775 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
777 r
= routing_policy_rule_dup(rule
, &tmp
);
781 r
= routing_policy_rule_acquire_priority(link
->manager
, tmp
);
785 r
= routing_policy_rule_add(link
->manager
, tmp
);
789 existing
= TAKE_PTR(tmp
);
791 existing
->source
= rule
->source
;
793 log_routing_policy_rule_debug(existing
, "Requesting", link
, link
->manager
);
794 r
= link_queue_request_safe(link
, REQUEST_TYPE_ROUTING_POLICY_RULE
,
796 routing_policy_rule_hash_func
,
797 routing_policy_rule_compare_func
,
798 routing_policy_rule_process_request
,
799 &link
->static_routing_policy_rule_messages
,
800 static_routing_policy_rule_configure_handler
,
805 routing_policy_rule_enter_requesting(existing
);
809 static int link_request_static_routing_policy_rule(Link
*link
, RoutingPolicyRule
*rule
) {
812 if (IN_SET(rule
->family
, AF_INET
, AF_INET6
))
813 return link_request_routing_policy_rule(link
, rule
);
815 rule
->family
= AF_INET
;
816 r
= link_request_routing_policy_rule(link
, rule
);
818 rule
->family
= AF_UNSPEC
;
822 rule
->family
= AF_INET6
;
823 r
= link_request_routing_policy_rule(link
, rule
);
824 rule
->family
= AF_UNSPEC
;
828 int link_request_static_routing_policy_rules(Link
*link
) {
829 RoutingPolicyRule
*rule
;
833 assert(link
->network
);
835 link
->static_routing_policy_rules_configured
= false;
837 HASHMAP_FOREACH(rule
, link
->network
->rules_by_section
) {
838 r
= link_request_static_routing_policy_rule(link
, rule
);
840 return log_link_warning_errno(link
, r
, "Could not request routing policy rule: %m");
843 if (link
->static_routing_policy_rule_messages
== 0) {
844 link
->static_routing_policy_rules_configured
= true;
845 link_check_ready(link
);
847 log_link_debug(link
, "Requesting routing policy rules");
848 link_set_state(link
, LINK_STATE_CONFIGURING
);
854 static const RoutingPolicyRule kernel_rules
[] = {
855 { .family
= AF_INET
, .priority_set
= true, .priority
= 0, .table
= RT_TABLE_LOCAL
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, .suppress_ifgroup
= -1, },
856 { .family
= AF_INET
, .priority_set
= true, .priority
= 32766, .table
= RT_TABLE_MAIN
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, .suppress_ifgroup
= -1, },
857 { .family
= AF_INET
, .priority_set
= true, .priority
= 32767, .table
= RT_TABLE_DEFAULT
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, .suppress_ifgroup
= -1, },
858 { .family
= AF_INET6
, .priority_set
= true, .priority
= 0, .table
= RT_TABLE_LOCAL
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, .suppress_ifgroup
= -1, },
859 { .family
= AF_INET6
, .priority_set
= true, .priority
= 32766, .table
= RT_TABLE_MAIN
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, .suppress_ifgroup
= -1, },
862 static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule
*rule
) {
865 if (rule
->l3mdev
> 0)
866 /* Currently, [RoutingPolicyRule] does not explicitly set FRA_L3MDEV. So, if the flag
867 * is set, it is safe to treat the rule as created by kernel. */
870 for (size_t i
= 0; i
< ELEMENTSOF(kernel_rules
); i
++)
871 if (routing_policy_rule_equal(rule
, &kernel_rules
[i
]))
877 int manager_rtnl_process_rule(sd_netlink
*rtnl
, sd_netlink_message
*message
, Manager
*m
) {
878 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
879 RoutingPolicyRule
*rule
= NULL
;
880 bool adjust_protocol
= false;
887 if (sd_netlink_message_is_error(message
)) {
888 r
= sd_netlink_message_get_errno(message
);
890 log_message_warning_errno(message
, r
, "rtnl: failed to receive rule message, ignoring");
895 r
= sd_netlink_message_get_type(message
, &type
);
897 log_warning_errno(r
, "rtnl: could not get message type, ignoring: %m");
899 } else if (!IN_SET(type
, RTM_NEWRULE
, RTM_DELRULE
)) {
900 log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type
);
904 r
= routing_policy_rule_new(&tmp
);
910 r
= sd_rtnl_message_get_family(message
, &tmp
->family
);
912 log_warning_errno(r
, "rtnl: could not get rule family, ignoring: %m");
914 } else if (!IN_SET(tmp
->family
, AF_INET
, AF_INET6
)) {
915 log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp
->family
);
919 r
= netlink_message_read_in_addr_union(message
, FRA_SRC
, tmp
->family
, &tmp
->from
);
920 if (r
< 0 && r
!= -ENODATA
) {
921 log_warning_errno(r
, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
924 r
= sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(message
, &tmp
->from_prefixlen
);
926 log_warning_errno(r
, "rtnl: received rule message without valid source prefix length, ignoring: %m");
931 r
= netlink_message_read_in_addr_union(message
, FRA_DST
, tmp
->family
, &tmp
->to
);
932 if (r
< 0 && r
!= -ENODATA
) {
933 log_warning_errno(r
, "rtnl: could not get FRA_DST attribute, ignoring: %m");
936 r
= sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(message
, &tmp
->to_prefixlen
);
938 log_warning_errno(r
, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
944 r
= sd_rtnl_message_routing_policy_rule_get_flags(message
, &flags
);
946 log_warning_errno(r
, "rtnl: received rule message without valid flag, ignoring: %m");
949 tmp
->invert_rule
= flags
& FIB_RULE_INVERT
;
951 r
= sd_netlink_message_read_u32(message
, FRA_FWMARK
, &tmp
->fwmark
);
952 if (r
< 0 && r
!= -ENODATA
) {
953 log_warning_errno(r
, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m");
957 r
= sd_netlink_message_read_u32(message
, FRA_FWMASK
, &tmp
->fwmask
);
958 if (r
< 0 && r
!= -ENODATA
) {
959 log_warning_errno(r
, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m");
963 r
= sd_netlink_message_read_u32(message
, FRA_PRIORITY
, &tmp
->priority
);
964 if (r
< 0 && r
!= -ENODATA
) {
965 log_warning_errno(r
, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
968 /* The kernel does not send priority if priority is zero. So, the flag below must be always set
969 * even if the message does not contain FRA_PRIORITY. */
970 tmp
->priority_set
= true;
972 r
= sd_netlink_message_read_u32(message
, FRA_TABLE
, &tmp
->table
);
973 if (r
< 0 && r
!= -ENODATA
) {
974 log_warning_errno(r
, "rtnl: could not get FRA_TABLE attribute, ignoring: %m");
978 r
= sd_rtnl_message_routing_policy_rule_get_tos(message
, &tmp
->tos
);
979 if (r
< 0 && r
!= -ENODATA
) {
980 log_warning_errno(r
, "rtnl: could not get FIB rule TOS, ignoring: %m");
984 r
= sd_rtnl_message_routing_policy_rule_get_fib_type(message
, &tmp
->type
);
985 if (r
< 0 && r
!= -ENODATA
) {
986 log_warning_errno(r
, "rtnl: could not get FIB rule type, ignoring: %m");
990 r
= sd_netlink_message_read_string_strdup(message
, FRA_IIFNAME
, &tmp
->iif
);
991 if (r
< 0 && r
!= -ENODATA
) {
992 log_warning_errno(r
, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
996 r
= sd_netlink_message_read_string_strdup(message
, FRA_OIFNAME
, &tmp
->oif
);
997 if (r
< 0 && r
!= -ENODATA
) {
998 log_warning_errno(r
, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m");
1002 r
= sd_netlink_message_read_u8(message
, FRA_IP_PROTO
, &tmp
->ipproto
);
1003 if (r
< 0 && r
!= -ENODATA
) {
1004 log_warning_errno(r
, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
1008 r
= sd_netlink_message_read_u8(message
, FRA_PROTOCOL
, &tmp
->protocol
);
1010 /* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended.
1011 * When the received message does not have FRA_PROTOCOL, then we need to adjust the
1012 * protocol of the rule later. */
1013 adjust_protocol
= true;
1015 log_warning_errno(r
, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m");
1019 r
= sd_netlink_message_read_u8(message
, FRA_L3MDEV
, &tmp
->l3mdev
);
1020 if (r
< 0 && r
!= -ENODATA
) {
1021 log_warning_errno(r
, "rtnl: could not get FRA_L3MDEV attribute, ignoring: %m");
1025 r
= sd_netlink_message_read(message
, FRA_SPORT_RANGE
, sizeof(tmp
->sport
), &tmp
->sport
);
1026 if (r
< 0 && r
!= -ENODATA
) {
1027 log_warning_errno(r
, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
1031 r
= sd_netlink_message_read(message
, FRA_DPORT_RANGE
, sizeof(tmp
->dport
), &tmp
->dport
);
1032 if (r
< 0 && r
!= -ENODATA
) {
1033 log_warning_errno(r
, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
1037 r
= sd_netlink_message_read(message
, FRA_UID_RANGE
, sizeof(tmp
->uid_range
), &tmp
->uid_range
);
1038 if (r
< 0 && r
!= -ENODATA
) {
1039 log_warning_errno(r
, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m");
1043 uint32_t suppress_prefixlen
;
1044 r
= sd_netlink_message_read_u32(message
, FRA_SUPPRESS_PREFIXLEN
, &suppress_prefixlen
);
1045 if (r
< 0 && r
!= -ENODATA
) {
1046 log_warning_errno(r
, "rtnl: could not get FRA_SUPPRESS_PREFIXLEN attribute, ignoring: %m");
1050 tmp
->suppress_prefixlen
= (int32_t) suppress_prefixlen
;
1052 uint32_t suppress_ifgroup
;
1053 r
= sd_netlink_message_read_u32(message
, FRA_SUPPRESS_IFGROUP
, &suppress_ifgroup
);
1054 if (r
< 0 && r
!= -ENODATA
) {
1055 log_warning_errno(r
, "rtnl: could not get FRA_SUPPRESS_IFGROUP attribute, ignoring: %m");
1059 tmp
->suppress_ifgroup
= (int32_t) suppress_ifgroup
;
1061 if (adjust_protocol
)
1062 /* As .network files does not have setting to specify protocol, we can assume the
1063 * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */
1064 tmp
->protocol
= routing_policy_rule_is_created_by_kernel(tmp
) ? RTPROT_KERNEL
: RTPROT_STATIC
;
1066 (void) routing_policy_rule_get(m
, tmp
, &rule
);
1071 routing_policy_rule_enter_configured(rule
);
1072 log_routing_policy_rule_debug(rule
, "Received remembered", NULL
, m
);
1073 } else if (!m
->manage_foreign_rules
) {
1074 routing_policy_rule_enter_configured(tmp
);
1075 log_routing_policy_rule_debug(tmp
, "Ignoring received", NULL
, m
);
1077 routing_policy_rule_enter_configured(tmp
);
1078 log_routing_policy_rule_debug(tmp
, "Remembering", NULL
, m
);
1079 r
= routing_policy_rule_add(m
, tmp
);
1081 log_warning_errno(r
, "Could not remember foreign rule, ignoring: %m");
1089 routing_policy_rule_enter_removed(rule
);
1090 if (rule
->state
== 0) {
1091 log_routing_policy_rule_debug(rule
, "Forgetting", NULL
, m
);
1092 routing_policy_rule_free(rule
);
1094 log_routing_policy_rule_debug(rule
, "Removed", NULL
, m
);
1096 log_routing_policy_rule_debug(tmp
, "Kernel removed unknown", NULL
, m
);
1100 assert_not_reached();
1106 static int parse_fwmark_fwmask(const char *s
, uint32_t *ret_fwmark
, uint32_t *ret_fwmask
) {
1107 _cleanup_free_
char *fwmark_str
= NULL
;
1108 uint32_t fwmark
, fwmask
= 0;
1116 slash
= strchr(s
, '/');
1118 fwmark_str
= strndup(s
, slash
- s
);
1123 r
= safe_atou32(fwmark_str
?: s
, &fwmark
);
1129 r
= safe_atou32(slash
+ 1, &fwmask
);
1133 fwmask
= UINT32_MAX
;
1136 *ret_fwmark
= fwmark
;
1137 *ret_fwmask
= fwmask
;
1142 int config_parse_routing_policy_rule_tos(
1144 const char *filename
,
1146 const char *section
,
1147 unsigned section_line
,
1154 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1155 Network
*network
= userdata
;
1164 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1168 r
= safe_atou8(rvalue
, &n
->tos
);
1170 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule TOS, ignoring: %s", rvalue
);
1178 int config_parse_routing_policy_rule_priority(
1180 const char *filename
,
1182 const char *section
,
1183 unsigned section_line
,
1190 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1191 Network
*network
= userdata
;
1200 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1204 if (isempty(rvalue
)) {
1206 n
->priority_set
= false;
1211 r
= safe_atou32(rvalue
, &n
->priority
);
1213 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule priority, ignoring: %s", rvalue
);
1216 n
->priority_set
= true;
1222 int config_parse_routing_policy_rule_table(
1224 const char *filename
,
1226 const char *section
,
1227 unsigned section_line
,
1234 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1235 Network
*network
= userdata
;
1244 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1248 r
= manager_get_route_table_from_string(network
->manager
, rvalue
, &n
->table
);
1250 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1251 "Could not parse RPDB rule route table \"%s\", ignoring assignment: %m", rvalue
);
1259 int config_parse_routing_policy_rule_fwmark_mask(
1261 const char *filename
,
1263 const char *section
,
1264 unsigned section_line
,
1271 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1272 Network
*network
= userdata
;
1281 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1285 r
= parse_fwmark_fwmask(rvalue
, &n
->fwmark
, &n
->fwmask
);
1287 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue
);
1295 int config_parse_routing_policy_rule_prefix(
1297 const char *filename
,
1299 const char *section
,
1300 unsigned section_line
,
1307 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1308 Network
*network
= userdata
;
1309 union in_addr_union
*buffer
;
1319 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1323 if (streq(lvalue
, "To")) {
1325 prefixlen
= &n
->to_prefixlen
;
1328 prefixlen
= &n
->from_prefixlen
;
1331 if (n
->family
== AF_UNSPEC
)
1332 r
= in_addr_prefix_from_string_auto(rvalue
, &n
->family
, buffer
, prefixlen
);
1334 r
= in_addr_prefix_from_string(rvalue
, n
->family
, buffer
, prefixlen
);
1336 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue
);
1344 int config_parse_routing_policy_rule_device(
1346 const char *filename
,
1348 const char *section
,
1349 unsigned section_line
,
1356 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1357 Network
*network
= userdata
;
1366 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1370 if (!ifname_valid(rvalue
)) {
1371 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1372 "Invalid interface name '%s' in %s=, ignoring assignment.", rvalue
, lvalue
);
1376 r
= free_and_strdup(streq(lvalue
, "IncomingInterface") ? &n
->iif
: &n
->oif
, rvalue
);
1384 int config_parse_routing_policy_rule_port_range(
1386 const char *filename
,
1388 const char *section
,
1389 unsigned section_line
,
1396 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1397 Network
*network
= userdata
;
1407 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1411 r
= parse_ip_port_range(rvalue
, &low
, &high
, /* allow_zero = */ false);
1413 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse routing policy rule port range '%s'", rvalue
);
1417 if (streq(lvalue
, "SourcePort")) {
1418 n
->sport
.start
= low
;
1419 n
->sport
.end
= high
;
1421 n
->dport
.start
= low
;
1422 n
->dport
.end
= high
;
1429 int config_parse_routing_policy_rule_ip_protocol(
1431 const char *filename
,
1433 const char *section
,
1434 unsigned section_line
,
1441 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1442 Network
*network
= userdata
;
1451 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1455 r
= parse_ip_protocol(rvalue
);
1457 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue
);
1467 int config_parse_routing_policy_rule_invert(
1469 const char *filename
,
1471 const char *section
,
1472 unsigned section_line
,
1479 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1480 Network
*network
= userdata
;
1489 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1493 r
= parse_boolean(rvalue
);
1495 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule invert, ignoring: %s", rvalue
);
1505 int config_parse_routing_policy_rule_family(
1507 const char *filename
,
1509 const char *section
,
1510 unsigned section_line
,
1517 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1518 Network
*network
= userdata
;
1528 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1532 a
= routing_policy_rule_address_family_from_string(rvalue
);
1534 log_syntax(unit
, LOG_WARNING
, filename
, line
, a
,
1535 "Invalid address family '%s', ignoring.", rvalue
);
1539 n
->address_family
= a
;
1545 int config_parse_routing_policy_rule_uid_range(
1547 const char *filename
,
1549 const char *section
,
1550 unsigned section_line
,
1557 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1558 Network
*network
= userdata
;
1568 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1572 r
= get_user_creds(&rvalue
, &start
, NULL
, NULL
, NULL
, 0);
1576 r
= parse_uid_range(rvalue
, &start
, &end
);
1578 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1579 "Invalid uid or uid range '%s', ignoring: %m", rvalue
);
1584 n
->uid_range
.start
= start
;
1585 n
->uid_range
.end
= end
;
1591 int config_parse_routing_policy_rule_suppress_prefixlen(
1593 const char *filename
,
1595 const char *section
,
1596 unsigned section_line
,
1603 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1604 Network
*network
= userdata
;
1613 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1617 r
= parse_ip_prefix_length(rvalue
, &n
->suppress_prefixlen
);
1619 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Prefix length outside of valid range 0-128, ignoring: %s", rvalue
);
1623 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", rvalue
);
1631 int config_parse_routing_policy_rule_suppress_ifgroup(
1633 const char *filename
,
1635 const char *section
,
1636 unsigned section_line
,
1643 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1644 Network
*network
= userdata
;
1645 int32_t suppress_ifgroup
;
1654 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1658 if (isempty(rvalue
)) {
1659 n
->suppress_ifgroup
= -1;
1663 r
= safe_atoi32(rvalue
, &suppress_ifgroup
);
1665 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1666 "Failed to parse SuppressInterfaceGroup=, ignoring assignment: %s", rvalue
);
1669 if (suppress_ifgroup
< 0) {
1670 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1671 "Value of SuppressInterfaceGroup= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1674 n
->suppress_ifgroup
= suppress_ifgroup
;
1679 int config_parse_routing_policy_rule_type(
1681 const char *filename
,
1683 const char *section
,
1684 unsigned section_line
,
1691 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1692 Network
*network
= userdata
;
1701 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1705 t
= fr_act_type_from_string(rvalue
);
1707 log_syntax(unit
, LOG_WARNING
, filename
, line
, t
,
1708 "Could not parse FIB rule type \"%s\", ignoring assignment: %m", rvalue
);
1712 n
->type
= (uint8_t) t
;
1718 static int routing_policy_rule_section_verify(RoutingPolicyRule
*rule
) {
1719 if (section_is_invalid(rule
->section
))
1722 if ((rule
->family
== AF_INET
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) ||
1723 (rule
->family
== AF_INET6
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)))
1724 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1725 "%s: address family specified by Family= conflicts with the address "
1726 "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
1727 rule
->section
->filename
, rule
->section
->line
);
1729 if (rule
->family
== AF_UNSPEC
) {
1730 if (IN_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
, ADDRESS_FAMILY_NO
))
1731 rule
->family
= AF_INET
;
1732 else if (rule
->address_family
== ADDRESS_FAMILY_IPV6
)
1733 rule
->family
= AF_INET6
;
1734 /* rule->family can be AF_UNSPEC only when Family=both. */
1737 /* Currently, [RoutingPolicyRule] does not have a setting to set FRA_L3MDEV flag. Please also
1738 * update routing_policy_rule_is_created_by_kernel() when a new setting which sets the flag is
1739 * added in the future. */
1740 if (rule
->l3mdev
> 0)
1741 assert_not_reached();
1746 void network_drop_invalid_routing_policy_rules(Network
*network
) {
1747 RoutingPolicyRule
*rule
;
1751 HASHMAP_FOREACH(rule
, network
->rules_by_section
)
1752 if (routing_policy_rule_section_verify(rule
) < 0)
1753 routing_policy_rule_free(rule
);