1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 /* Make sure the net/if.h header is included before any linux/ one */
5 #include <linux/fib_rules.h>
8 #include "alloc-util.h"
9 #include "conf-parser.h"
11 #include "format-util.h"
13 #include "ip-protocol-list.h"
14 #include "netlink-util.h"
15 #include "networkd-manager.h"
16 #include "networkd-queue.h"
17 #include "networkd-route-util.h"
18 #include "networkd-routing-policy-rule.h"
19 #include "networkd-util.h"
20 #include "parse-util.h"
21 #include "socket-util.h"
22 #include "string-table.h"
23 #include "string-util.h"
25 #include "user-util.h"
27 static const char *const fr_act_type_table
[__FR_ACT_MAX
] = {
28 [FR_ACT_BLACKHOLE
] = "blackhole",
29 [FR_ACT_UNREACHABLE
] = "unreachable",
30 [FR_ACT_PROHIBIT
] = "prohibit",
33 static const char *const fr_act_type_full_table
[__FR_ACT_MAX
] = {
34 [FR_ACT_TO_TBL
] = "table",
35 [FR_ACT_GOTO
] = "goto",
37 [FR_ACT_BLACKHOLE
] = "blackhole",
38 [FR_ACT_UNREACHABLE
] = "unreachable",
39 [FR_ACT_PROHIBIT
] = "prohibit",
42 assert_cc(__FR_ACT_MAX
<= UINT8_MAX
);
43 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fr_act_type
, int);
44 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(fr_act_type_full
, int);
46 RoutingPolicyRule
*routing_policy_rule_free(RoutingPolicyRule
*rule
) {
51 assert(rule
->section
);
52 hashmap_remove(rule
->network
->rules_by_section
, rule
->section
);
56 set_remove(rule
->manager
->rules
, rule
);
58 config_section_free(rule
->section
);
65 DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutingPolicyRule
, routing_policy_rule_free
);
67 static int routing_policy_rule_new(RoutingPolicyRule
**ret
) {
68 RoutingPolicyRule
*rule
;
70 rule
= new(RoutingPolicyRule
, 1);
74 *rule
= (RoutingPolicyRule
) {
75 .table
= RT_TABLE_MAIN
,
76 .uid_range
.start
= UID_INVALID
,
77 .uid_range
.end
= UID_INVALID
,
78 .suppress_prefixlen
= -1,
79 .suppress_ifgroup
= -1,
80 .protocol
= RTPROT_UNSPEC
,
81 .type
= FR_ACT_TO_TBL
,
88 static int routing_policy_rule_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutingPolicyRule
**ret
) {
89 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
90 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
96 assert(section_line
> 0);
98 r
= config_section_new(filename
, section_line
, &n
);
102 rule
= hashmap_get(network
->rules_by_section
, n
);
104 *ret
= TAKE_PTR(rule
);
108 r
= routing_policy_rule_new(&rule
);
112 rule
->network
= network
;
113 rule
->section
= TAKE_PTR(n
);
114 rule
->source
= NETWORK_CONFIG_SOURCE_STATIC
;
115 rule
->protocol
= RTPROT_STATIC
;
117 r
= hashmap_ensure_put(&network
->rules_by_section
, &config_section_hash_ops
, rule
->section
, rule
);
121 *ret
= TAKE_PTR(rule
);
125 static int routing_policy_rule_dup(const RoutingPolicyRule
*src
, RoutingPolicyRule
**ret
) {
126 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*dest
= NULL
;
131 dest
= newdup(RoutingPolicyRule
, src
, 1);
135 /* Unset all pointers */
136 dest
->manager
= NULL
;
137 dest
->network
= NULL
;
138 dest
->section
= NULL
;
139 dest
->iif
= dest
->oif
= NULL
;
142 dest
->iif
= strdup(src
->iif
);
148 dest
->oif
= strdup(src
->oif
);
153 *ret
= TAKE_PTR(dest
);
157 static void routing_policy_rule_hash_func(const RoutingPolicyRule
*rule
, struct siphash
*state
) {
160 siphash24_compress_typesafe(rule
->family
, state
);
162 switch (rule
->family
) {
165 in_addr_hash_func(&rule
->from
, rule
->family
, state
);
166 siphash24_compress_typesafe(rule
->from_prefixlen
, state
);
168 siphash24_compress_boolean(rule
->l3mdev
, state
);
170 in_addr_hash_func(&rule
->to
, rule
->family
, state
);
171 siphash24_compress_typesafe(rule
->to_prefixlen
, state
);
173 siphash24_compress_boolean(rule
->invert_rule
, state
);
175 siphash24_compress_typesafe(rule
->tos
, state
);
176 siphash24_compress_typesafe(rule
->type
, state
);
177 siphash24_compress_typesafe(rule
->fwmark
, state
);
178 siphash24_compress_typesafe(rule
->fwmask
, state
);
179 siphash24_compress_typesafe(rule
->priority
, state
);
180 siphash24_compress_typesafe(rule
->table
, state
);
181 siphash24_compress_typesafe(rule
->suppress_prefixlen
, state
);
182 siphash24_compress_typesafe(rule
->suppress_ifgroup
, state
);
184 siphash24_compress_typesafe(rule
->ipproto
, state
);
185 siphash24_compress_typesafe(rule
->protocol
, state
);
186 siphash24_compress_typesafe(rule
->sport
, state
);
187 siphash24_compress_typesafe(rule
->dport
, state
);
188 siphash24_compress_typesafe(rule
->uid_range
, state
);
190 siphash24_compress_string(rule
->iif
, state
);
191 siphash24_compress_string(rule
->oif
, state
);
195 /* treat any other address family as AF_UNSPEC */
200 static int routing_policy_rule_compare_func(const RoutingPolicyRule
*a
, const RoutingPolicyRule
*b
) {
203 r
= CMP(a
->family
, b
->family
);
210 r
= CMP(a
->from_prefixlen
, b
->from_prefixlen
);
214 r
= memcmp(&a
->from
, &b
->from
, FAMILY_ADDRESS_SIZE(a
->family
));
218 r
= CMP(a
->l3mdev
, b
->l3mdev
);
222 r
= CMP(a
->to_prefixlen
, b
->to_prefixlen
);
226 r
= memcmp(&a
->to
, &b
->to
, FAMILY_ADDRESS_SIZE(a
->family
));
230 r
= CMP(a
->invert_rule
, b
->invert_rule
);
234 r
= CMP(a
->tos
, b
->tos
);
238 r
= CMP(a
->type
, b
->type
);
242 r
= CMP(a
->fwmark
, b
->fwmark
);
246 r
= CMP(a
->fwmask
, b
->fwmask
);
250 r
= CMP(a
->priority
, b
->priority
);
254 r
= CMP(a
->table
, b
->table
);
258 r
= CMP(a
->suppress_prefixlen
, b
->suppress_prefixlen
);
262 r
= CMP(a
->suppress_ifgroup
, b
->suppress_ifgroup
);
266 r
= CMP(a
->ipproto
, b
->ipproto
);
270 r
= CMP(a
->protocol
, b
->protocol
);
274 r
= memcmp(&a
->sport
, &b
->sport
, sizeof(a
->sport
));
278 r
= memcmp(&a
->dport
, &b
->dport
, sizeof(a
->dport
));
282 r
= memcmp(&a
->uid_range
, &b
->uid_range
, sizeof(a
->uid_range
));
286 r
= strcmp_ptr(a
->iif
, b
->iif
);
290 r
= strcmp_ptr(a
->oif
, b
->oif
);
296 /* treat any other address family as AF_UNSPEC */
301 static bool routing_policy_rule_equal(const RoutingPolicyRule
*rule1
, const RoutingPolicyRule
*rule2
) {
305 if (!rule1
|| !rule2
)
308 return routing_policy_rule_compare_func(rule1
, rule2
) == 0;
311 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
312 routing_policy_rule_hash_ops
,
314 routing_policy_rule_hash_func
,
315 routing_policy_rule_compare_func
,
316 routing_policy_rule_free
);
318 static int routing_policy_rule_get(Manager
*m
, const RoutingPolicyRule
*in
, RoutingPolicyRule
**ret
) {
319 RoutingPolicyRule
*rule
;
324 rule
= set_get(m
->rules
, in
);
331 if (in
->priority_set
)
334 /* Also find rules configured without priority. */
335 SET_FOREACH(rule
, m
->rules
) {
339 if (rule
->priority_set
)
340 /* The rule is configured with priority. */
343 priority
= rule
->priority
;
345 found
= routing_policy_rule_equal(rule
, in
);
346 rule
->priority
= priority
;
358 static int routing_policy_rule_add(Manager
*m
, RoutingPolicyRule
*rule
) {
363 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
365 r
= set_ensure_put(&m
->rules
, &routing_policy_rule_hash_ops
, rule
);
375 static int routing_policy_rule_acquire_priority(Manager
*manager
, RoutingPolicyRule
*rule
) {
376 _cleanup_set_free_ Set
*priorities
= NULL
;
377 RoutingPolicyRule
*tmp
;
384 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
386 if (rule
->priority_set
)
389 /* Find the highest unused priority. Note that 32766 is already used by kernel.
390 * See kernel_rules[] below. */
392 SET_FOREACH(tmp
, manager
->rules
) {
393 if (tmp
->family
!= rule
->family
)
395 if (tmp
->priority
== 0 || tmp
->priority
> 32765)
397 r
= set_ensure_put(&priorities
, NULL
, UINT32_TO_PTR(tmp
->priority
));
402 ORDERED_HASHMAP_FOREACH(network
, manager
->networks
)
403 HASHMAP_FOREACH(tmp
, network
->rules_by_section
) {
404 if (tmp
->family
!= AF_UNSPEC
&& tmp
->family
!= rule
->family
)
406 if (!tmp
->priority_set
)
408 if (tmp
->priority
== 0 || tmp
->priority
> 32765)
410 r
= set_ensure_put(&priorities
, NULL
, UINT32_TO_PTR(tmp
->priority
));
415 for (priority
= 32765; priority
> 0; priority
--)
416 if (!set_contains(priorities
, UINT32_TO_PTR(priority
)))
419 rule
->priority
= priority
;
423 static void log_routing_policy_rule_debug(const RoutingPolicyRule
*rule
, const char *str
, const Link
*link
, const Manager
*m
) {
424 _cleanup_free_
char *state
= NULL
, *table
= NULL
;
427 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
431 /* link may be NULL. */
436 (void) network_config_state_to_string_alloc(rule
->state
, &state
);
437 (void) manager_get_route_table_to_string(m
, rule
->table
, /* append_num = */ true, &table
);
440 "%s %s routing policy rule (%s): priority: %"PRIu32
", %s -> %s, iif: %s, oif: %s, table: %s",
441 str
, strna(network_config_source_to_string(rule
->source
)), strna(state
),
443 IN_ADDR_PREFIX_TO_STRING(rule
->family
, &rule
->from
, rule
->from_prefixlen
),
444 IN_ADDR_PREFIX_TO_STRING(rule
->family
, &rule
->to
, rule
->to_prefixlen
),
445 strna(rule
->iif
), strna(rule
->oif
), strna(table
));
448 static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule
*rule
, sd_netlink_message
*m
, Link
*link
) {
454 /* link may be NULL. */
456 if (rule
->from_prefixlen
> 0) {
457 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, rule
->family
, &rule
->from
);
461 r
= sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(m
, rule
->from_prefixlen
);
466 if (rule
->to_prefixlen
> 0) {
467 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, rule
->family
, &rule
->to
);
471 r
= sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(m
, rule
->to_prefixlen
);
476 r
= sd_netlink_message_append_u32(m
, FRA_PRIORITY
, rule
->priority
);
481 r
= sd_rtnl_message_routing_policy_rule_set_tos(m
, rule
->tos
);
487 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
488 else if (rule
->table
< 256)
489 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, rule
->table
);
491 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
495 r
= sd_netlink_message_append_u32(m
, FRA_TABLE
, rule
->table
);
500 if (rule
->fwmark
> 0) {
501 r
= sd_netlink_message_append_u32(m
, FRA_FWMARK
, rule
->fwmark
);
505 r
= sd_netlink_message_append_u32(m
, FRA_FWMASK
, rule
->fwmask
);
511 r
= sd_netlink_message_append_string(m
, FRA_IIFNAME
, rule
->iif
);
517 r
= sd_netlink_message_append_string(m
, FRA_OIFNAME
, rule
->oif
);
522 r
= sd_netlink_message_append_u8(m
, FRA_IP_PROTO
, rule
->ipproto
);
526 r
= sd_netlink_message_append_u8(m
, FRA_PROTOCOL
, rule
->protocol
);
530 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
531 r
= sd_netlink_message_append_data(m
, FRA_SPORT_RANGE
, &rule
->sport
, sizeof(rule
->sport
));
536 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
537 r
= sd_netlink_message_append_data(m
, FRA_DPORT_RANGE
, &rule
->dport
, sizeof(rule
->dport
));
542 if (rule
->uid_range
.start
!= UID_INVALID
&& rule
->uid_range
.end
!= UID_INVALID
) {
543 r
= sd_netlink_message_append_data(m
, FRA_UID_RANGE
, &rule
->uid_range
, sizeof(rule
->uid_range
));
548 if (rule
->invert_rule
) {
549 r
= sd_rtnl_message_routing_policy_rule_set_flags(m
, FIB_RULE_INVERT
);
555 r
= sd_netlink_message_append_u8(m
, FRA_L3MDEV
, 1);
560 if (rule
->suppress_prefixlen
>= 0) {
561 r
= sd_netlink_message_append_u32(m
, FRA_SUPPRESS_PREFIXLEN
, (uint32_t) rule
->suppress_prefixlen
);
566 if (rule
->suppress_ifgroup
>= 0) {
567 r
= sd_netlink_message_append_u32(m
, FRA_SUPPRESS_IFGROUP
, (uint32_t) rule
->suppress_ifgroup
);
572 r
= sd_rtnl_message_routing_policy_rule_set_fib_type(m
, rule
->type
);
579 static int routing_policy_rule_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
584 r
= sd_netlink_message_get_errno(m
);
586 log_message_warning_errno(m
, r
, "Could not drop routing policy rule");
591 static int routing_policy_rule_remove(RoutingPolicyRule
*rule
) {
592 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
596 assert(rule
->manager
);
597 assert(rule
->manager
->rtnl
);
598 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
600 log_routing_policy_rule_debug(rule
, "Removing", NULL
, rule
->manager
);
602 r
= sd_rtnl_message_new_routing_policy_rule(rule
->manager
->rtnl
, &m
, RTM_DELRULE
, rule
->family
);
604 return log_warning_errno(r
, "Could not allocate netlink message: %m");
606 r
= routing_policy_rule_set_netlink_message(rule
, m
, NULL
);
608 return log_warning_errno(r
, "Could not create netlink message: %m");
610 r
= netlink_call_async(rule
->manager
->rtnl
, NULL
, m
,
611 routing_policy_rule_remove_handler
,
614 return log_warning_errno(r
, "Could not send netlink message: %m");
616 routing_policy_rule_enter_removing(rule
);
620 static int routing_policy_rule_configure(RoutingPolicyRule
*rule
, Link
*link
, Request
*req
) {
621 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
625 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
627 assert(link
->ifindex
> 0);
628 assert(link
->manager
);
629 assert(link
->manager
->rtnl
);
632 log_routing_policy_rule_debug(rule
, "Configuring", link
, link
->manager
);
634 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_NEWRULE
, rule
->family
);
638 r
= routing_policy_rule_set_netlink_message(rule
, m
, link
);
642 return request_call_netlink_async(link
->manager
->rtnl
, m
, req
);
645 static void manager_mark_routing_policy_rules(Manager
*m
, bool foreign
, const Link
*except
) {
646 RoutingPolicyRule
*rule
;
651 /* First, mark all existing rules. */
652 SET_FOREACH(rule
, m
->rules
) {
653 /* Do not touch rules managed by kernel. */
654 if (rule
->protocol
== RTPROT_KERNEL
)
657 /* When 'foreign' is true, mark only foreign rules, and vice versa. */
658 if (rule
->source
!= (foreign
? NETWORK_CONFIG_SOURCE_FOREIGN
: NETWORK_CONFIG_SOURCE_STATIC
))
661 /* Ignore rules not assigned yet or already removing. */
662 if (!routing_policy_rule_exists(rule
))
665 routing_policy_rule_mark(rule
);
668 /* Then, unmark all rules requested by active links. */
669 HASHMAP_FOREACH(link
, m
->links_by_index
) {
673 if (!IN_SET(link
->state
, LINK_STATE_CONFIGURING
, LINK_STATE_CONFIGURED
))
676 HASHMAP_FOREACH(rule
, link
->network
->rules_by_section
) {
677 RoutingPolicyRule
*existing
;
679 if (IN_SET(rule
->family
, AF_INET
, AF_INET6
)) {
680 if (routing_policy_rule_get(m
, rule
, &existing
) >= 0)
681 routing_policy_rule_unmark(existing
);
683 /* The case Family=both. */
684 rule
->family
= AF_INET
;
685 if (routing_policy_rule_get(m
, rule
, &existing
) >= 0)
686 routing_policy_rule_unmark(existing
);
688 rule
->family
= AF_INET6
;
689 if (routing_policy_rule_get(m
, rule
, &existing
) >= 0)
690 routing_policy_rule_unmark(existing
);
692 rule
->family
= AF_UNSPEC
;
698 int manager_drop_routing_policy_rules_internal(Manager
*m
, bool foreign
, const Link
*except
) {
699 RoutingPolicyRule
*rule
;
704 manager_mark_routing_policy_rules(m
, foreign
, except
);
706 SET_FOREACH(rule
, m
->rules
) {
707 if (!routing_policy_rule_is_marked(rule
))
710 RET_GATHER(r
, routing_policy_rule_remove(rule
));
716 void link_foreignize_routing_policy_rules(Link
*link
) {
717 RoutingPolicyRule
*rule
;
720 assert(link
->manager
);
722 manager_mark_routing_policy_rules(link
->manager
, /* foreign = */ false, link
);
724 SET_FOREACH(rule
, link
->manager
->rules
) {
725 if (!routing_policy_rule_is_marked(rule
))
728 rule
->source
= NETWORK_CONFIG_SOURCE_FOREIGN
;
732 static int routing_policy_rule_process_request(Request
*req
, Link
*link
, RoutingPolicyRule
*rule
) {
739 if (!link_is_ready_to_configure(link
, false))
742 r
= routing_policy_rule_configure(rule
, link
, req
);
744 return log_link_warning_errno(link
, r
, "Failed to configure routing policy rule: %m");
746 routing_policy_rule_enter_configuring(rule
);
750 static int static_routing_policy_rule_configure_handler(
752 sd_netlink_message
*m
,
755 RoutingPolicyRule
*rule
) {
762 r
= sd_netlink_message_get_errno(m
);
763 if (r
< 0 && r
!= -EEXIST
) {
764 log_link_message_warning_errno(link
, m
, r
, "Could not add routing policy rule");
765 link_enter_failed(link
);
769 if (link
->static_routing_policy_rule_messages
== 0) {
770 log_link_debug(link
, "Routing policy rule configured");
771 link
->static_routing_policy_rules_configured
= true;
772 link_check_ready(link
);
778 static int link_request_routing_policy_rule(Link
*link
, RoutingPolicyRule
*rule
) {
779 RoutingPolicyRule
*existing
;
783 assert(link
->manager
);
785 assert(rule
->source
!= NETWORK_CONFIG_SOURCE_FOREIGN
);
787 if (routing_policy_rule_get(link
->manager
, rule
, &existing
) < 0) {
788 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
790 r
= routing_policy_rule_dup(rule
, &tmp
);
794 r
= routing_policy_rule_acquire_priority(link
->manager
, tmp
);
798 r
= routing_policy_rule_add(link
->manager
, tmp
);
802 existing
= TAKE_PTR(tmp
);
804 existing
->source
= rule
->source
;
806 log_routing_policy_rule_debug(existing
, "Requesting", link
, link
->manager
);
807 r
= link_queue_request_safe(link
, REQUEST_TYPE_ROUTING_POLICY_RULE
,
809 routing_policy_rule_hash_func
,
810 routing_policy_rule_compare_func
,
811 routing_policy_rule_process_request
,
812 &link
->static_routing_policy_rule_messages
,
813 static_routing_policy_rule_configure_handler
,
818 routing_policy_rule_enter_requesting(existing
);
822 static int link_request_static_routing_policy_rule(Link
*link
, RoutingPolicyRule
*rule
) {
825 if (IN_SET(rule
->family
, AF_INET
, AF_INET6
))
826 return link_request_routing_policy_rule(link
, rule
);
828 rule
->family
= AF_INET
;
829 r
= link_request_routing_policy_rule(link
, rule
);
831 rule
->family
= AF_UNSPEC
;
835 rule
->family
= AF_INET6
;
836 r
= link_request_routing_policy_rule(link
, rule
);
837 rule
->family
= AF_UNSPEC
;
841 int link_request_static_routing_policy_rules(Link
*link
) {
842 RoutingPolicyRule
*rule
;
846 assert(link
->network
);
848 link
->static_routing_policy_rules_configured
= false;
850 HASHMAP_FOREACH(rule
, link
->network
->rules_by_section
) {
851 r
= link_request_static_routing_policy_rule(link
, rule
);
853 return log_link_warning_errno(link
, r
, "Could not request routing policy rule: %m");
856 if (link
->static_routing_policy_rule_messages
== 0) {
857 link
->static_routing_policy_rules_configured
= true;
858 link_check_ready(link
);
860 log_link_debug(link
, "Requesting routing policy rules");
861 link_set_state(link
, LINK_STATE_CONFIGURING
);
867 static const RoutingPolicyRule kernel_rules
[] = {
868 { .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, },
869 { .family
= AF_INET
, .priority_set
= true, .priority
= 1000, .table
= RT_TABLE_UNSPEC
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, .suppress_ifgroup
= -1, .l3mdev
= true },
870 { .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, },
871 { .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, },
872 { .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, },
873 { .family
= AF_INET6
, .priority_set
= true, .priority
= 1000, .table
= RT_TABLE_UNSPEC
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, .suppress_ifgroup
= -1, .l3mdev
= true },
874 { .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, },
877 static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule
*rule
) {
880 for (size_t i
= 0; i
< ELEMENTSOF(kernel_rules
); i
++)
881 if (routing_policy_rule_equal(rule
, &kernel_rules
[i
]))
887 int manager_rtnl_process_rule(sd_netlink
*rtnl
, sd_netlink_message
*message
, Manager
*m
) {
888 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
889 RoutingPolicyRule
*rule
= NULL
;
890 bool adjust_protocol
= false;
897 if (sd_netlink_message_is_error(message
)) {
898 r
= sd_netlink_message_get_errno(message
);
900 log_message_warning_errno(message
, r
, "rtnl: failed to receive rule message, ignoring");
905 r
= sd_netlink_message_get_type(message
, &type
);
907 log_warning_errno(r
, "rtnl: could not get message type, ignoring: %m");
909 } else if (!IN_SET(type
, RTM_NEWRULE
, RTM_DELRULE
)) {
910 log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type
);
914 r
= routing_policy_rule_new(&tmp
);
920 r
= sd_rtnl_message_get_family(message
, &tmp
->family
);
922 log_warning_errno(r
, "rtnl: could not get rule family, ignoring: %m");
924 } else if (!IN_SET(tmp
->family
, AF_INET
, AF_INET6
)) {
925 log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp
->family
);
929 r
= netlink_message_read_in_addr_union(message
, FRA_SRC
, tmp
->family
, &tmp
->from
);
930 if (r
< 0 && r
!= -ENODATA
) {
931 log_warning_errno(r
, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
934 r
= sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(message
, &tmp
->from_prefixlen
);
936 log_warning_errno(r
, "rtnl: received rule message without valid source prefix length, ignoring: %m");
941 r
= netlink_message_read_in_addr_union(message
, FRA_DST
, tmp
->family
, &tmp
->to
);
942 if (r
< 0 && r
!= -ENODATA
) {
943 log_warning_errno(r
, "rtnl: could not get FRA_DST attribute, ignoring: %m");
946 r
= sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(message
, &tmp
->to_prefixlen
);
948 log_warning_errno(r
, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
954 r
= sd_rtnl_message_routing_policy_rule_get_flags(message
, &flags
);
956 log_warning_errno(r
, "rtnl: received rule message without valid flag, ignoring: %m");
959 tmp
->invert_rule
= flags
& FIB_RULE_INVERT
;
961 r
= sd_netlink_message_read_u32(message
, FRA_FWMARK
, &tmp
->fwmark
);
962 if (r
< 0 && r
!= -ENODATA
) {
963 log_warning_errno(r
, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m");
967 r
= sd_netlink_message_read_u32(message
, FRA_FWMASK
, &tmp
->fwmask
);
968 if (r
< 0 && r
!= -ENODATA
) {
969 log_warning_errno(r
, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m");
973 r
= sd_netlink_message_read_u32(message
, FRA_PRIORITY
, &tmp
->priority
);
974 if (r
< 0 && r
!= -ENODATA
) {
975 log_warning_errno(r
, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
978 /* The kernel does not send priority if priority is zero. So, the flag below must be always set
979 * even if the message does not contain FRA_PRIORITY. */
980 tmp
->priority_set
= true;
982 r
= sd_netlink_message_read_u32(message
, FRA_TABLE
, &tmp
->table
);
983 if (r
< 0 && r
!= -ENODATA
) {
984 log_warning_errno(r
, "rtnl: could not get FRA_TABLE attribute, ignoring: %m");
988 r
= sd_rtnl_message_routing_policy_rule_get_tos(message
, &tmp
->tos
);
989 if (r
< 0 && r
!= -ENODATA
) {
990 log_warning_errno(r
, "rtnl: could not get FIB rule TOS, ignoring: %m");
994 r
= sd_rtnl_message_routing_policy_rule_get_fib_type(message
, &tmp
->type
);
995 if (r
< 0 && r
!= -ENODATA
) {
996 log_warning_errno(r
, "rtnl: could not get FIB rule type, ignoring: %m");
1000 r
= sd_netlink_message_read_string_strdup(message
, FRA_IIFNAME
, &tmp
->iif
);
1001 if (r
< 0 && r
!= -ENODATA
) {
1002 log_warning_errno(r
, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
1006 r
= sd_netlink_message_read_string_strdup(message
, FRA_OIFNAME
, &tmp
->oif
);
1007 if (r
< 0 && r
!= -ENODATA
) {
1008 log_warning_errno(r
, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m");
1012 r
= sd_netlink_message_read_u8(message
, FRA_IP_PROTO
, &tmp
->ipproto
);
1013 if (r
< 0 && r
!= -ENODATA
) {
1014 log_warning_errno(r
, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
1018 r
= sd_netlink_message_read_u8(message
, FRA_PROTOCOL
, &tmp
->protocol
);
1020 /* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended.
1021 * When the received message does not have FRA_PROTOCOL, then we need to adjust the
1022 * protocol of the rule later. */
1023 adjust_protocol
= true;
1025 log_warning_errno(r
, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m");
1030 r
= sd_netlink_message_read_u8(message
, FRA_L3MDEV
, &l3mdev
);
1031 if (r
< 0 && r
!= -ENODATA
) {
1032 log_warning_errno(r
, "rtnl: could not get FRA_L3MDEV attribute, ignoring: %m");
1035 tmp
->l3mdev
= l3mdev
!= 0;
1037 r
= sd_netlink_message_read(message
, FRA_SPORT_RANGE
, sizeof(tmp
->sport
), &tmp
->sport
);
1038 if (r
< 0 && r
!= -ENODATA
) {
1039 log_warning_errno(r
, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
1043 r
= sd_netlink_message_read(message
, FRA_DPORT_RANGE
, sizeof(tmp
->dport
), &tmp
->dport
);
1044 if (r
< 0 && r
!= -ENODATA
) {
1045 log_warning_errno(r
, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
1049 r
= sd_netlink_message_read(message
, FRA_UID_RANGE
, sizeof(tmp
->uid_range
), &tmp
->uid_range
);
1050 if (r
< 0 && r
!= -ENODATA
) {
1051 log_warning_errno(r
, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m");
1055 uint32_t suppress_prefixlen
;
1056 r
= sd_netlink_message_read_u32(message
, FRA_SUPPRESS_PREFIXLEN
, &suppress_prefixlen
);
1057 if (r
< 0 && r
!= -ENODATA
) {
1058 log_warning_errno(r
, "rtnl: could not get FRA_SUPPRESS_PREFIXLEN attribute, ignoring: %m");
1062 tmp
->suppress_prefixlen
= (int32_t) suppress_prefixlen
;
1064 uint32_t suppress_ifgroup
;
1065 r
= sd_netlink_message_read_u32(message
, FRA_SUPPRESS_IFGROUP
, &suppress_ifgroup
);
1066 if (r
< 0 && r
!= -ENODATA
) {
1067 log_warning_errno(r
, "rtnl: could not get FRA_SUPPRESS_IFGROUP attribute, ignoring: %m");
1071 tmp
->suppress_ifgroup
= (int32_t) suppress_ifgroup
;
1073 if (adjust_protocol
)
1074 /* As .network files does not have setting to specify protocol, we can assume the
1075 * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */
1076 tmp
->protocol
= routing_policy_rule_is_created_by_kernel(tmp
) ? RTPROT_KERNEL
: RTPROT_STATIC
;
1078 (void) routing_policy_rule_get(m
, tmp
, &rule
);
1083 routing_policy_rule_enter_configured(rule
);
1084 log_routing_policy_rule_debug(rule
, "Received remembered", NULL
, m
);
1085 } else if (!m
->manage_foreign_rules
) {
1086 routing_policy_rule_enter_configured(tmp
);
1087 log_routing_policy_rule_debug(tmp
, "Ignoring received", NULL
, m
);
1089 routing_policy_rule_enter_configured(tmp
);
1090 log_routing_policy_rule_debug(tmp
, "Remembering", NULL
, m
);
1091 r
= routing_policy_rule_add(m
, tmp
);
1093 log_warning_errno(r
, "Could not remember foreign rule, ignoring: %m");
1101 routing_policy_rule_enter_removed(rule
);
1102 if (rule
->state
== 0) {
1103 log_routing_policy_rule_debug(rule
, "Forgetting", NULL
, m
);
1104 routing_policy_rule_free(rule
);
1106 log_routing_policy_rule_debug(rule
, "Removed", NULL
, m
);
1108 log_routing_policy_rule_debug(tmp
, "Kernel removed unknown", NULL
, m
);
1112 assert_not_reached();
1118 static int parse_fwmark_fwmask(const char *s
, uint32_t *ret_fwmark
, uint32_t *ret_fwmask
) {
1119 _cleanup_free_
char *fwmark_str
= NULL
;
1120 uint32_t fwmark
, fwmask
= 0;
1128 slash
= strchr(s
, '/');
1130 fwmark_str
= strndup(s
, slash
- s
);
1135 r
= safe_atou32(fwmark_str
?: s
, &fwmark
);
1141 r
= safe_atou32(slash
+ 1, &fwmask
);
1145 fwmask
= UINT32_MAX
;
1148 *ret_fwmark
= fwmark
;
1149 *ret_fwmask
= fwmask
;
1154 int config_parse_routing_policy_rule_tos(
1156 const char *filename
,
1158 const char *section
,
1159 unsigned section_line
,
1166 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1167 Network
*network
= userdata
;
1176 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1180 r
= safe_atou8(rvalue
, &n
->tos
);
1182 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule TOS, ignoring: %s", rvalue
);
1190 int config_parse_routing_policy_rule_priority(
1192 const char *filename
,
1194 const char *section
,
1195 unsigned section_line
,
1202 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1203 Network
*network
= userdata
;
1212 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1216 if (isempty(rvalue
)) {
1218 n
->priority_set
= false;
1223 r
= safe_atou32(rvalue
, &n
->priority
);
1225 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule priority, ignoring: %s", rvalue
);
1228 n
->priority_set
= true;
1234 int config_parse_routing_policy_rule_table(
1236 const char *filename
,
1238 const char *section
,
1239 unsigned section_line
,
1246 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1247 Network
*network
= userdata
;
1256 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1260 r
= manager_get_route_table_from_string(network
->manager
, rvalue
, &n
->table
);
1262 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1263 "Could not parse RPDB rule route table \"%s\", ignoring assignment: %m", rvalue
);
1271 int config_parse_routing_policy_rule_fwmark_mask(
1273 const char *filename
,
1275 const char *section
,
1276 unsigned section_line
,
1283 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1284 Network
*network
= userdata
;
1293 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1297 r
= parse_fwmark_fwmask(rvalue
, &n
->fwmark
, &n
->fwmask
);
1299 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue
);
1307 int config_parse_routing_policy_rule_prefix(
1309 const char *filename
,
1311 const char *section
,
1312 unsigned section_line
,
1319 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1320 Network
*network
= userdata
;
1321 union in_addr_union
*buffer
;
1331 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1335 if (streq(lvalue
, "To")) {
1337 prefixlen
= &n
->to_prefixlen
;
1340 prefixlen
= &n
->from_prefixlen
;
1343 if (n
->family
== AF_UNSPEC
)
1344 r
= in_addr_prefix_from_string_auto(rvalue
, &n
->family
, buffer
, prefixlen
);
1346 r
= in_addr_prefix_from_string(rvalue
, n
->family
, buffer
, prefixlen
);
1348 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue
);
1356 int config_parse_routing_policy_rule_device(
1358 const char *filename
,
1360 const char *section
,
1361 unsigned section_line
,
1368 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1369 Network
*network
= userdata
;
1378 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1382 if (!ifname_valid(rvalue
)) {
1383 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1384 "Invalid interface name '%s' in %s=, ignoring assignment.", rvalue
, lvalue
);
1388 r
= free_and_strdup(streq(lvalue
, "IncomingInterface") ? &n
->iif
: &n
->oif
, rvalue
);
1396 int config_parse_routing_policy_rule_port_range(
1398 const char *filename
,
1400 const char *section
,
1401 unsigned section_line
,
1408 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1409 Network
*network
= userdata
;
1419 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1423 r
= parse_ip_port_range(rvalue
, &low
, &high
, /* allow_zero = */ false);
1425 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse routing policy rule port range '%s'", rvalue
);
1429 if (streq(lvalue
, "SourcePort")) {
1430 n
->sport
.start
= low
;
1431 n
->sport
.end
= high
;
1433 n
->dport
.start
= low
;
1434 n
->dport
.end
= high
;
1441 int config_parse_routing_policy_rule_ip_protocol(
1443 const char *filename
,
1445 const char *section
,
1446 unsigned section_line
,
1453 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1454 Network
*network
= userdata
;
1463 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1467 r
= parse_ip_protocol(rvalue
);
1469 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue
);
1479 int config_parse_routing_policy_rule_invert(
1481 const char *filename
,
1483 const char *section
,
1484 unsigned section_line
,
1491 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1492 Network
*network
= userdata
;
1501 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1505 r
= parse_boolean(rvalue
);
1507 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule invert, ignoring: %s", rvalue
);
1517 int config_parse_routing_policy_rule_l3mdev(
1519 const char *filename
,
1521 const char *section
,
1522 unsigned section_line
,
1529 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1530 Network
*network
= userdata
;
1539 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1543 r
= parse_boolean(rvalue
);
1545 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule l3mdev, ignoring: %s", rvalue
);
1555 int config_parse_routing_policy_rule_family(
1557 const char *filename
,
1559 const char *section
,
1560 unsigned section_line
,
1567 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1568 Network
*network
= userdata
;
1578 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1582 a
= routing_policy_rule_address_family_from_string(rvalue
);
1584 log_syntax(unit
, LOG_WARNING
, filename
, line
, a
,
1585 "Invalid address family '%s', ignoring.", rvalue
);
1589 n
->address_family
= a
;
1595 int config_parse_routing_policy_rule_uid_range(
1597 const char *filename
,
1599 const char *section
,
1600 unsigned section_line
,
1607 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1608 Network
*network
= userdata
;
1618 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1622 r
= get_user_creds(&rvalue
, &start
, NULL
, NULL
, NULL
, 0);
1626 r
= parse_uid_range(rvalue
, &start
, &end
);
1628 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1629 "Invalid uid or uid range '%s', ignoring: %m", rvalue
);
1634 n
->uid_range
.start
= start
;
1635 n
->uid_range
.end
= end
;
1641 int config_parse_routing_policy_rule_suppress_prefixlen(
1643 const char *filename
,
1645 const char *section
,
1646 unsigned section_line
,
1653 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1654 Network
*network
= userdata
;
1663 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1667 r
= parse_ip_prefix_length(rvalue
, &n
->suppress_prefixlen
);
1669 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Prefix length outside of valid range 0-128, ignoring: %s", rvalue
);
1673 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", rvalue
);
1681 int config_parse_routing_policy_rule_suppress_ifgroup(
1683 const char *filename
,
1685 const char *section
,
1686 unsigned section_line
,
1693 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1694 Network
*network
= userdata
;
1695 int32_t suppress_ifgroup
;
1704 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1708 if (isempty(rvalue
)) {
1709 n
->suppress_ifgroup
= -1;
1713 r
= safe_atoi32(rvalue
, &suppress_ifgroup
);
1715 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1716 "Failed to parse SuppressInterfaceGroup=, ignoring assignment: %s", rvalue
);
1719 if (suppress_ifgroup
< 0) {
1720 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1721 "Value of SuppressInterfaceGroup= must be in the range 0…2147483647, ignoring assignment: %s", rvalue
);
1724 n
->suppress_ifgroup
= suppress_ifgroup
;
1729 int config_parse_routing_policy_rule_type(
1731 const char *filename
,
1733 const char *section
,
1734 unsigned section_line
,
1741 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1742 Network
*network
= userdata
;
1751 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1755 t
= fr_act_type_from_string(rvalue
);
1757 log_syntax(unit
, LOG_WARNING
, filename
, line
, t
,
1758 "Could not parse FIB rule type \"%s\", ignoring assignment: %m", rvalue
);
1762 n
->type
= (uint8_t) t
;
1768 static int routing_policy_rule_section_verify(RoutingPolicyRule
*rule
) {
1769 if (section_is_invalid(rule
->section
))
1772 if ((rule
->family
== AF_INET
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) ||
1773 (rule
->family
== AF_INET6
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)))
1774 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1775 "%s: address family specified by Family= conflicts with the address "
1776 "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
1777 rule
->section
->filename
, rule
->section
->line
);
1779 if (rule
->family
== AF_UNSPEC
) {
1780 if (IN_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
, ADDRESS_FAMILY_NO
))
1781 rule
->family
= AF_INET
;
1782 else if (rule
->address_family
== ADDRESS_FAMILY_IPV6
)
1783 rule
->family
= AF_INET6
;
1784 /* rule->family can be AF_UNSPEC only when Family=both. */
1790 void network_drop_invalid_routing_policy_rules(Network
*network
) {
1791 RoutingPolicyRule
*rule
;
1795 HASHMAP_FOREACH(rule
, network
->rules_by_section
)
1796 if (routing_policy_rule_section_verify(rule
) < 0)
1797 routing_policy_rule_free(rule
);