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-routing-policy-rule.h"
16 #include "networkd-util.h"
17 #include "parse-util.h"
18 #include "socket-util.h"
19 #include "string-table.h"
20 #include "string-util.h"
22 #include "user-util.h"
24 static const char *const fr_act_type_table
[__FR_ACT_MAX
] = {
25 [FR_ACT_BLACKHOLE
] = "blackhole",
26 [FR_ACT_UNREACHABLE
] = "unreachable",
27 [FR_ACT_PROHIBIT
] = "prohibit",
30 assert_cc(__FR_ACT_MAX
<= UINT8_MAX
);
31 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fr_act_type
, int);
33 RoutingPolicyRule
*routing_policy_rule_free(RoutingPolicyRule
*rule
) {
38 assert(rule
->section
);
39 hashmap_remove(rule
->network
->rules_by_section
, rule
->section
);
43 set_remove(rule
->manager
->rules
, rule
);
44 set_remove(rule
->manager
->rules_foreign
, rule
);
47 network_config_section_free(rule
->section
);
54 DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule
, routing_policy_rule_free
);
56 static int routing_policy_rule_new(RoutingPolicyRule
**ret
) {
57 RoutingPolicyRule
*rule
;
59 rule
= new(RoutingPolicyRule
, 1);
63 *rule
= (RoutingPolicyRule
) {
64 .table
= RT_TABLE_MAIN
,
65 .uid_range
.start
= UID_INVALID
,
66 .uid_range
.end
= UID_INVALID
,
67 .suppress_prefixlen
= -1,
68 .protocol
= RTPROT_UNSPEC
,
69 .type
= FR_ACT_TO_TBL
,
76 static int routing_policy_rule_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutingPolicyRule
**ret
) {
77 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
78 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
84 assert(section_line
> 0);
86 r
= network_config_section_new(filename
, section_line
, &n
);
90 rule
= hashmap_get(network
->rules_by_section
, n
);
92 *ret
= TAKE_PTR(rule
);
96 r
= routing_policy_rule_new(&rule
);
100 rule
->network
= network
;
101 rule
->section
= TAKE_PTR(n
);
102 rule
->protocol
= RTPROT_STATIC
;
104 r
= hashmap_ensure_put(&network
->rules_by_section
, &network_config_hash_ops
, rule
->section
, rule
);
108 *ret
= TAKE_PTR(rule
);
112 static int routing_policy_rule_copy(RoutingPolicyRule
*dest
, const RoutingPolicyRule
*src
) {
113 _cleanup_free_
char *iif
= NULL
, *oif
= NULL
;
119 iif
= strdup(src
->iif
);
125 oif
= strdup(src
->oif
);
130 dest
->family
= src
->family
;
131 dest
->from
= src
->from
;
132 dest
->from_prefixlen
= src
->from_prefixlen
;
134 dest
->to_prefixlen
= src
->to_prefixlen
;
135 dest
->invert_rule
= src
->invert_rule
;
136 dest
->tos
= src
->tos
;
137 dest
->type
= src
->type
;
138 dest
->fwmark
= src
->fwmark
;
139 dest
->fwmask
= src
->fwmask
;
140 dest
->priority
= src
->priority
;
141 dest
->table
= src
->table
;
142 dest
->iif
= TAKE_PTR(iif
);
143 dest
->oif
= TAKE_PTR(oif
);
144 dest
->ipproto
= src
->ipproto
;
145 dest
->protocol
= src
->protocol
;
146 dest
->sport
= src
->sport
;
147 dest
->dport
= src
->dport
;
148 dest
->uid_range
= src
->uid_range
;
149 dest
->suppress_prefixlen
= src
->suppress_prefixlen
;
154 static void routing_policy_rule_hash_func(const RoutingPolicyRule
*rule
, struct siphash
*state
) {
157 siphash24_compress(&rule
->family
, sizeof(rule
->family
), state
);
159 switch (rule
->family
) {
162 siphash24_compress(&rule
->from
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
163 siphash24_compress(&rule
->from_prefixlen
, sizeof(rule
->from_prefixlen
), state
);
165 siphash24_compress(&rule
->to
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
166 siphash24_compress(&rule
->to_prefixlen
, sizeof(rule
->to_prefixlen
), state
);
168 siphash24_compress_boolean(rule
->invert_rule
, state
);
170 siphash24_compress(&rule
->tos
, sizeof(rule
->tos
), state
);
171 siphash24_compress(&rule
->type
, sizeof(rule
->type
), state
);
172 siphash24_compress(&rule
->fwmark
, sizeof(rule
->fwmark
), state
);
173 siphash24_compress(&rule
->fwmask
, sizeof(rule
->fwmask
), state
);
174 siphash24_compress(&rule
->priority
, sizeof(rule
->priority
), state
);
175 siphash24_compress(&rule
->table
, sizeof(rule
->table
), state
);
176 siphash24_compress(&rule
->suppress_prefixlen
, sizeof(rule
->suppress_prefixlen
), state
);
178 siphash24_compress(&rule
->ipproto
, sizeof(rule
->ipproto
), state
);
179 siphash24_compress(&rule
->protocol
, sizeof(rule
->protocol
), state
);
180 siphash24_compress(&rule
->sport
, sizeof(rule
->sport
), state
);
181 siphash24_compress(&rule
->dport
, sizeof(rule
->dport
), state
);
182 siphash24_compress(&rule
->uid_range
, sizeof(rule
->uid_range
), state
);
184 siphash24_compress_string(rule
->iif
, state
);
185 siphash24_compress_string(rule
->oif
, state
);
189 /* treat any other address family as AF_UNSPEC */
194 static int routing_policy_rule_compare_func(const RoutingPolicyRule
*a
, const RoutingPolicyRule
*b
) {
197 r
= CMP(a
->family
, b
->family
);
204 r
= CMP(a
->from_prefixlen
, b
->from_prefixlen
);
208 r
= memcmp(&a
->from
, &b
->from
, FAMILY_ADDRESS_SIZE(a
->family
));
212 r
= CMP(a
->to_prefixlen
, b
->to_prefixlen
);
216 r
= memcmp(&a
->to
, &b
->to
, FAMILY_ADDRESS_SIZE(a
->family
));
220 r
= CMP(a
->invert_rule
, b
->invert_rule
);
224 r
= CMP(a
->tos
, b
->tos
);
228 r
= CMP(a
->type
, b
->type
);
232 r
= CMP(a
->fwmark
, b
->fwmark
);
236 r
= CMP(a
->fwmask
, b
->fwmask
);
240 r
= CMP(a
->priority
, b
->priority
);
244 r
= CMP(a
->table
, b
->table
);
248 r
= CMP(a
->suppress_prefixlen
, b
->suppress_prefixlen
);
252 r
= CMP(a
->ipproto
, b
->ipproto
);
256 r
= CMP(a
->protocol
, b
->protocol
);
260 r
= memcmp(&a
->sport
, &b
->sport
, sizeof(a
->sport
));
264 r
= memcmp(&a
->dport
, &b
->dport
, sizeof(a
->dport
));
268 r
= memcmp(&a
->uid_range
, &b
->uid_range
, sizeof(a
->uid_range
));
272 r
= strcmp_ptr(a
->iif
, b
->iif
);
276 r
= strcmp_ptr(a
->oif
, b
->oif
);
282 /* treat any other address family as AF_UNSPEC */
287 static bool routing_policy_rule_equal(const RoutingPolicyRule
*rule1
, const RoutingPolicyRule
*rule2
) {
291 if (!rule1
|| !rule2
)
294 return routing_policy_rule_compare_func(rule1
, rule2
) == 0;
297 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
298 routing_policy_rule_hash_ops
,
300 routing_policy_rule_hash_func
,
301 routing_policy_rule_compare_func
,
302 routing_policy_rule_free
);
304 static int routing_policy_rule_get(Manager
*m
, const RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
305 RoutingPolicyRule
*existing
;
309 existing
= set_get(m
->rules
, rule
);
316 existing
= set_get(m
->rules_foreign
, rule
);
326 static int routing_policy_rule_add(Manager
*m
, const RoutingPolicyRule
*in
, int family
, RoutingPolicyRule
**ret
) {
327 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
328 RoutingPolicyRule
*existing
;
334 assert(IN_SET(family
, AF_INET
, AF_INET6
));
335 assert(in
->family
== AF_UNSPEC
|| in
->family
== family
);
337 r
= routing_policy_rule_new(&rule
);
341 r
= routing_policy_rule_copy(rule
, in
);
345 rule
->family
= family
;
347 r
= routing_policy_rule_get(m
, rule
, &existing
);
349 /* Rule does not exist, use a new one. */
350 r
= set_ensure_put(&m
->rules
, &routing_policy_rule_hash_ops
, rule
);
356 existing
= TAKE_PTR(rule
);
359 /* Take over a foreign rule. */
360 r
= set_ensure_put(&m
->rules
, &routing_policy_rule_hash_ops
, existing
);
365 set_remove(m
->rules_foreign
, existing
);
367 /* Already exists, do nothing. */
377 static int routing_policy_rule_consume_foreign(Manager
*m
, RoutingPolicyRule
*rule
) {
382 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
384 r
= set_ensure_consume(&m
->rules_foreign
, &routing_policy_rule_hash_ops
, rule
);
393 static void log_routing_policy_rule_debug(const RoutingPolicyRule
*rule
, int family
, const char *str
, const Link
*link
, const Manager
*m
) {
395 assert(IN_SET(family
, AF_INET
, AF_INET6
));
399 /* link may be NULL. */
402 _cleanup_free_
char *from
= NULL
, *to
= NULL
, *table
= NULL
;
404 (void) in_addr_to_string(family
, &rule
->from
, &from
);
405 (void) in_addr_to_string(family
, &rule
->to
, &to
);
406 (void) manager_get_route_table_to_string(m
, rule
->table
, &table
);
409 "%s routing policy rule: priority: %"PRIu32
", %s/%u -> %s/%u, iif: %s, oif: %s, table: %s",
410 str
, rule
->priority
, strna(from
), rule
->from_prefixlen
, strna(to
), rule
->to_prefixlen
,
411 strna(rule
->iif
), strna(rule
->oif
), strna(table
));
415 static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule
*rule
, sd_netlink_message
*m
, Link
*link
) {
421 /* link may be NULL. */
423 if (in_addr_is_null(rule
->family
, &rule
->from
) == 0) {
424 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, rule
->family
, &rule
->from
);
426 return log_link_error_errno(link
, r
, "Could not append FRA_SRC attribute: %m");
428 r
= sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(m
, rule
->from_prefixlen
);
430 return log_link_error_errno(link
, r
, "Could not set source prefix length: %m");
433 if (in_addr_is_null(rule
->family
, &rule
->to
) == 0) {
434 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, rule
->family
, &rule
->to
);
436 return log_link_error_errno(link
, r
, "Could not append FRA_DST attribute: %m");
438 r
= sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(m
, rule
->to_prefixlen
);
440 return log_link_error_errno(link
, r
, "Could not set destination prefix length: %m");
443 r
= sd_netlink_message_append_u32(m
, FRA_PRIORITY
, rule
->priority
);
445 return log_link_error_errno(link
, r
, "Could not append FRA_PRIORITY attribute: %m");
448 r
= sd_rtnl_message_routing_policy_rule_set_tos(m
, rule
->tos
);
450 return log_link_error_errno(link
, r
, "Could not set IP rule TOS: %m");
453 if (rule
->table
< 256) {
454 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, rule
->table
);
456 return log_link_error_errno(link
, r
, "Could not set IP rule table: %m");
458 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
460 return log_link_error_errno(link
, r
, "Could not set IP rule table: %m");
462 r
= sd_netlink_message_append_u32(m
, FRA_TABLE
, rule
->table
);
464 return log_link_error_errno(link
, r
, "Could not append FRA_TABLE attribute: %m");
467 if (rule
->fwmark
> 0) {
468 r
= sd_netlink_message_append_u32(m
, FRA_FWMARK
, rule
->fwmark
);
470 return log_link_error_errno(link
, r
, "Could not append FRA_FWMARK attribute: %m");
472 r
= sd_netlink_message_append_u32(m
, FRA_FWMASK
, rule
->fwmask
);
474 return log_link_error_errno(link
, r
, "Could not append FRA_FWMASK attribute: %m");
478 r
= sd_netlink_message_append_string(m
, FRA_IIFNAME
, rule
->iif
);
480 return log_link_error_errno(link
, r
, "Could not append FRA_IIFNAME attribute: %m");
484 r
= sd_netlink_message_append_string(m
, FRA_OIFNAME
, rule
->oif
);
486 return log_link_error_errno(link
, r
, "Could not append FRA_OIFNAME attribute: %m");
489 r
= sd_netlink_message_append_u8(m
, FRA_IP_PROTO
, rule
->ipproto
);
491 return log_link_error_errno(link
, r
, "Could not append FRA_IP_PROTO attribute: %m");
493 r
= sd_netlink_message_append_u8(m
, FRA_PROTOCOL
, rule
->protocol
);
495 return log_link_error_errno(link
, r
, "Could not append FRA_PROTOCOL attribute: %m");
497 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
498 r
= sd_netlink_message_append_data(m
, FRA_SPORT_RANGE
, &rule
->sport
, sizeof(rule
->sport
));
500 return log_link_error_errno(link
, r
, "Could not append FRA_SPORT_RANGE attribute: %m");
503 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
504 r
= sd_netlink_message_append_data(m
, FRA_DPORT_RANGE
, &rule
->dport
, sizeof(rule
->dport
));
506 return log_link_error_errno(link
, r
, "Could not append FRA_DPORT_RANGE attribute: %m");
509 if (rule
->uid_range
.start
!= UID_INVALID
&& rule
->uid_range
.end
!= UID_INVALID
) {
510 r
= sd_netlink_message_append_data(m
, FRA_UID_RANGE
, &rule
->uid_range
, sizeof(rule
->uid_range
));
512 return log_link_error_errno(link
, r
, "Could not append FRA_UID_RANGE attribute: %m");
515 if (rule
->invert_rule
) {
516 r
= sd_rtnl_message_routing_policy_rule_set_flags(m
, FIB_RULE_INVERT
);
518 return log_link_error_errno(link
, r
, "Could not append FIB_RULE_INVERT attribute: %m");
521 if (rule
->suppress_prefixlen
>= 0) {
522 r
= sd_netlink_message_append_u32(m
, FRA_SUPPRESS_PREFIXLEN
, (uint32_t) rule
->suppress_prefixlen
);
524 return log_link_error_errno(link
, r
, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m");
527 if (rule
->type
!= FR_ACT_TO_TBL
) {
528 r
= sd_rtnl_message_routing_policy_rule_set_fib_type(m
, rule
->type
);
530 return log_link_error_errno(link
, r
, "Could not append FIB rule type attribute: %m");
536 static int routing_policy_rule_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
541 r
= sd_netlink_message_get_errno(m
);
543 log_message_warning_errno(m
, r
, "Could not drop routing policy rule");
548 static int routing_policy_rule_remove(const RoutingPolicyRule
*rule
, Manager
*manager
) {
549 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
554 assert(manager
->rtnl
);
555 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
557 log_routing_policy_rule_debug(rule
, rule
->family
, "Removing", NULL
, manager
);
559 r
= sd_rtnl_message_new_routing_policy_rule(manager
->rtnl
, &m
, RTM_DELRULE
, rule
->family
);
561 return log_error_errno(r
, "Could not allocate RTM_DELRULE message: %m");
563 r
= routing_policy_rule_set_netlink_message(rule
, m
, NULL
);
567 r
= sd_netlink_call_async(manager
->rtnl
, NULL
, m
,
568 routing_policy_rule_remove_handler
,
569 NULL
, NULL
, 0, __func__
);
571 return log_error_errno(r
, "Could not send rtnetlink message: %m");
576 static int routing_policy_rule_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
582 assert(link
->ifname
);
583 assert(link
->routing_policy_rule_messages
> 0);
585 link
->routing_policy_rule_messages
--;
587 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
590 r
= sd_netlink_message_get_errno(m
);
591 if (r
< 0 && r
!= -EEXIST
) {
592 log_link_message_warning_errno(link
, m
, r
, "Could not add routing policy rule");
593 link_enter_failed(link
);
597 if (link
->routing_policy_rule_messages
== 0) {
598 log_link_debug(link
, "Routing policy rule configured");
599 link
->routing_policy_rules_configured
= true;
600 link_check_ready(link
);
606 static int routing_policy_rule_configure_internal(const RoutingPolicyRule
*rule
, int family
, Link
*link
) {
607 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
612 assert(link
->ifindex
> 0);
613 assert(link
->manager
);
614 assert(link
->manager
->rtnl
);
616 log_routing_policy_rule_debug(rule
, family
, "Configuring", link
, link
->manager
);
618 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_NEWRULE
, family
);
620 return log_link_error_errno(link
, r
, "Could not allocate RTM_NEWRULE message: %m");
622 r
= routing_policy_rule_set_netlink_message(rule
, m
, link
);
626 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
,
627 routing_policy_rule_handler
,
628 link_netlink_destroy_callback
, link
);
630 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
633 link
->routing_policy_rule_messages
++;
635 r
= routing_policy_rule_add(link
->manager
, rule
, family
, NULL
);
637 return log_link_error_errno(link
, r
, "Could not add rule: %m");
642 static int routing_policy_rule_configure(const RoutingPolicyRule
*rule
, Link
*link
) {
645 if (IN_SET(rule
->family
, AF_INET
, AF_INET6
))
646 return routing_policy_rule_configure_internal(rule
, rule
->family
, link
);
648 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)) {
649 r
= routing_policy_rule_configure_internal(rule
, AF_INET
, link
);
654 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) {
655 r
= routing_policy_rule_configure_internal(rule
, AF_INET6
, link
);
663 static int links_have_routing_policy_rule(const Manager
*m
, const RoutingPolicyRule
*rule
, const Link
*except
) {
670 HASHMAP_FOREACH(link
, m
->links
) {
671 RoutingPolicyRule
*link_rule
;
679 HASHMAP_FOREACH(link_rule
, link
->network
->rules_by_section
)
680 if (IN_SET(link_rule
->family
, AF_INET
, AF_INET6
)) {
681 if (routing_policy_rule_equal(link_rule
, rule
))
684 /* The case Family=both. */
685 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
687 r
= routing_policy_rule_new(&tmp
);
691 r
= routing_policy_rule_copy(tmp
, link_rule
);
695 tmp
->family
= AF_INET
;
696 if (routing_policy_rule_equal(tmp
, rule
))
699 tmp
->family
= AF_INET6
;
700 if (routing_policy_rule_equal(tmp
, rule
))
708 int manager_drop_routing_policy_rules_internal(Manager
*m
, bool foreign
, const Link
*except
) {
709 RoutingPolicyRule
*rule
;
715 rules
= foreign
? m
->rules_foreign
: m
->rules
;
716 SET_FOREACH(rule
, rules
) {
717 /* Do not touch rules managed by kernel. */
718 if (rule
->protocol
== RTPROT_KERNEL
)
721 /* The rule will be configured later, or already configured by a link. */
722 k
= links_have_routing_policy_rule(m
, rule
, except
);
729 k
= routing_policy_rule_remove(rule
, m
);
737 int link_set_routing_policy_rules(Link
*link
) {
738 RoutingPolicyRule
*rule
;
742 assert(link
->network
);
744 if (link
->routing_policy_rule_messages
!= 0) {
745 log_link_debug(link
, "Routing policy rules are configuring.");
749 link
->routing_policy_rules_configured
= false;
751 HASHMAP_FOREACH(rule
, link
->network
->rules_by_section
) {
752 r
= routing_policy_rule_configure(rule
, link
);
754 return log_link_warning_errno(link
, r
, "Could not set routing policy rule: %m");
757 if (link
->routing_policy_rule_messages
== 0)
758 link
->routing_policy_rules_configured
= true;
760 log_link_debug(link
, "Setting routing policy rules");
761 link_set_state(link
, LINK_STATE_CONFIGURING
);
767 static const RoutingPolicyRule kernel_rules
[] = {
768 { .family
= AF_INET
, .priority
= 0, .table
= RT_TABLE_LOCAL
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, },
769 { .family
= AF_INET
, .priority
= 32766, .table
= RT_TABLE_MAIN
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, },
770 { .family
= AF_INET
, .priority
= 32767, .table
= RT_TABLE_DEFAULT
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, },
771 { .family
= AF_INET6
, .priority
= 0, .table
= RT_TABLE_LOCAL
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, },
772 { .family
= AF_INET6
, .priority
= 32766, .table
= RT_TABLE_MAIN
, .type
= FR_ACT_TO_TBL
, .uid_range
.start
= UID_INVALID
, .uid_range
.end
= UID_INVALID
, .suppress_prefixlen
= -1, },
775 static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule
*rule
) {
778 if (rule
->l3mdev
> 0)
779 /* Currently, [RoutingPolicyRule] does not explicitly set FRA_L3MDEV. So, if the flag
780 * is set, it is safe to treat the rule as created by kernel. */
783 for (size_t i
= 0; i
< ELEMENTSOF(kernel_rules
); i
++)
784 if (routing_policy_rule_equal(rule
, &kernel_rules
[i
]))
790 int manager_rtnl_process_rule(sd_netlink
*rtnl
, sd_netlink_message
*message
, Manager
*m
) {
791 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
792 RoutingPolicyRule
*rule
= NULL
;
793 const char *iif
= NULL
, *oif
= NULL
;
794 bool adjust_protocol
= false;
795 uint32_t suppress_prefixlen
;
803 if (sd_netlink_message_is_error(message
)) {
804 r
= sd_netlink_message_get_errno(message
);
806 log_message_warning_errno(message
, r
, "rtnl: failed to receive rule message, ignoring");
811 r
= sd_netlink_message_get_type(message
, &type
);
813 log_warning_errno(r
, "rtnl: could not get message type, ignoring: %m");
815 } else if (!IN_SET(type
, RTM_NEWRULE
, RTM_DELRULE
)) {
816 log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type
);
820 r
= routing_policy_rule_new(&tmp
);
826 r
= sd_rtnl_message_get_family(message
, &tmp
->family
);
828 log_warning_errno(r
, "rtnl: could not get rule family, ignoring: %m");
830 } else if (!IN_SET(tmp
->family
, AF_INET
, AF_INET6
)) {
831 log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp
->family
);
835 r
= netlink_message_read_in_addr_union(message
, FRA_SRC
, tmp
->family
, &tmp
->from
);
836 if (r
< 0 && r
!= -ENODATA
) {
837 log_warning_errno(r
, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
840 r
= sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(message
, &tmp
->from_prefixlen
);
842 log_warning_errno(r
, "rtnl: received rule message without valid source prefix length, ignoring: %m");
847 r
= netlink_message_read_in_addr_union(message
, FRA_DST
, tmp
->family
, &tmp
->to
);
848 if (r
< 0 && r
!= -ENODATA
) {
849 log_warning_errno(r
, "rtnl: could not get FRA_DST attribute, ignoring: %m");
852 r
= sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(message
, &tmp
->to_prefixlen
);
854 log_warning_errno(r
, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
859 r
= sd_rtnl_message_routing_policy_rule_get_flags(message
, &flags
);
861 log_warning_errno(r
, "rtnl: received rule message without valid flag, ignoring: %m");
864 tmp
->invert_rule
= flags
& FIB_RULE_INVERT
;
866 r
= sd_netlink_message_read_u32(message
, FRA_FWMARK
, &tmp
->fwmark
);
867 if (r
< 0 && r
!= -ENODATA
) {
868 log_warning_errno(r
, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m");
872 r
= sd_netlink_message_read_u32(message
, FRA_FWMASK
, &tmp
->fwmask
);
873 if (r
< 0 && r
!= -ENODATA
) {
874 log_warning_errno(r
, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m");
878 r
= sd_netlink_message_read_u32(message
, FRA_PRIORITY
, &tmp
->priority
);
879 if (r
< 0 && r
!= -ENODATA
) {
880 log_warning_errno(r
, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
884 r
= sd_netlink_message_read_u32(message
, FRA_TABLE
, &tmp
->table
);
885 if (r
< 0 && r
!= -ENODATA
) {
886 log_warning_errno(r
, "rtnl: could not get FRA_TABLE attribute, ignoring: %m");
890 r
= sd_rtnl_message_routing_policy_rule_get_tos(message
, &tmp
->tos
);
891 if (r
< 0 && r
!= -ENODATA
) {
892 log_warning_errno(r
, "rtnl: could not get FIB rule TOS, ignoring: %m");
896 r
= sd_rtnl_message_routing_policy_rule_get_fib_type(message
, &tmp
->type
);
897 if (r
< 0 && r
!= -ENODATA
) {
898 log_warning_errno(r
, "rtnl: could not get FIB rule type, ignoring: %m");
902 r
= sd_netlink_message_read_string(message
, FRA_IIFNAME
, &iif
);
903 if (r
< 0 && r
!= -ENODATA
) {
904 log_warning_errno(r
, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
907 r
= free_and_strdup(&tmp
->iif
, iif
);
911 r
= sd_netlink_message_read_string(message
, FRA_OIFNAME
, &oif
);
912 if (r
< 0 && r
!= -ENODATA
) {
913 log_warning_errno(r
, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m");
916 r
= free_and_strdup(&tmp
->oif
, oif
);
920 r
= sd_netlink_message_read_u8(message
, FRA_IP_PROTO
, &tmp
->ipproto
);
921 if (r
< 0 && r
!= -ENODATA
) {
922 log_warning_errno(r
, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
926 r
= sd_netlink_message_read_u8(message
, FRA_PROTOCOL
, &tmp
->protocol
);
928 /* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended.
929 * When the received message does not have FRA_PROTOCOL, then we need to adjust the
930 * protocol of the rule later. */
931 adjust_protocol
= true;
933 log_warning_errno(r
, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m");
937 r
= sd_netlink_message_read_u8(message
, FRA_L3MDEV
, &tmp
->l3mdev
);
938 if (r
< 0 && r
!= -ENODATA
) {
939 log_warning_errno(r
, "rtnl: could not get FRA_L3MDEV attribute, ignoring: %m");
943 r
= sd_netlink_message_read(message
, FRA_SPORT_RANGE
, sizeof(tmp
->sport
), &tmp
->sport
);
944 if (r
< 0 && r
!= -ENODATA
) {
945 log_warning_errno(r
, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
949 r
= sd_netlink_message_read(message
, FRA_DPORT_RANGE
, sizeof(tmp
->dport
), &tmp
->dport
);
950 if (r
< 0 && r
!= -ENODATA
) {
951 log_warning_errno(r
, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
955 r
= sd_netlink_message_read(message
, FRA_UID_RANGE
, sizeof(tmp
->uid_range
), &tmp
->uid_range
);
956 if (r
< 0 && r
!= -ENODATA
) {
957 log_warning_errno(r
, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m");
961 r
= sd_netlink_message_read_u32(message
, FRA_SUPPRESS_PREFIXLEN
, &suppress_prefixlen
);
962 if (r
< 0 && r
!= -ENODATA
) {
963 log_warning_errno(r
, "rtnl: could not get FRA_SUPPRESS_PREFIXLEN attribute, ignoring: %m");
967 tmp
->suppress_prefixlen
= (int) suppress_prefixlen
;
970 /* As .network files does not have setting to specify protocol, we can assume the
971 * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */
972 tmp
->protocol
= routing_policy_rule_is_created_by_kernel(tmp
) ? RTPROT_KERNEL
: RTPROT_STATIC
;
974 (void) routing_policy_rule_get(m
, tmp
, &rule
);
979 log_routing_policy_rule_debug(tmp
, tmp
->family
, "Received remembered", NULL
, m
);
981 log_routing_policy_rule_debug(tmp
, tmp
->family
, "Remembering foreign", NULL
, m
);
982 r
= routing_policy_rule_consume_foreign(m
, TAKE_PTR(tmp
));
984 log_warning_errno(r
, "Could not remember foreign rule, ignoring: %m");
989 log_routing_policy_rule_debug(tmp
, tmp
->family
, "Forgetting", NULL
, m
);
990 routing_policy_rule_free(rule
);
992 log_routing_policy_rule_debug(tmp
, tmp
->family
, "Kernel removed unknown", NULL
, m
);
996 assert_not_reached("Received invalid RTNL message type");
1002 static int parse_fwmark_fwmask(const char *s
, uint32_t *ret_fwmark
, uint32_t *ret_fwmask
) {
1003 _cleanup_free_
char *fwmark_str
= NULL
;
1004 uint32_t fwmark
, fwmask
= 0;
1012 slash
= strchr(s
, '/');
1014 fwmark_str
= strndup(s
, slash
- s
);
1019 r
= safe_atou32(fwmark_str
?: s
, &fwmark
);
1025 r
= safe_atou32(slash
+ 1, &fwmask
);
1029 fwmask
= UINT32_MAX
;
1032 *ret_fwmark
= fwmark
;
1033 *ret_fwmask
= fwmask
;
1038 int config_parse_routing_policy_rule_tos(
1040 const char *filename
,
1042 const char *section
,
1043 unsigned section_line
,
1050 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1051 Network
*network
= userdata
;
1060 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1064 r
= safe_atou8(rvalue
, &n
->tos
);
1066 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule TOS, ignoring: %s", rvalue
);
1074 int config_parse_routing_policy_rule_priority(
1076 const char *filename
,
1078 const char *section
,
1079 unsigned section_line
,
1086 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1087 Network
*network
= userdata
;
1096 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1100 r
= safe_atou32(rvalue
, &n
->priority
);
1102 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule priority, ignoring: %s", rvalue
);
1110 int config_parse_routing_policy_rule_table(
1112 const char *filename
,
1114 const char *section
,
1115 unsigned section_line
,
1122 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1123 Network
*network
= userdata
;
1132 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1136 r
= manager_get_route_table_from_string(network
->manager
, rvalue
, &n
->table
);
1138 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1139 "Could not parse RPDB rule route table number \"%s\", ignoring assignment: %m", rvalue
);
1147 int config_parse_routing_policy_rule_fwmark_mask(
1149 const char *filename
,
1151 const char *section
,
1152 unsigned section_line
,
1159 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1160 Network
*network
= userdata
;
1169 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1173 r
= parse_fwmark_fwmask(rvalue
, &n
->fwmark
, &n
->fwmask
);
1175 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue
);
1183 int config_parse_routing_policy_rule_prefix(
1185 const char *filename
,
1187 const char *section
,
1188 unsigned section_line
,
1195 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1196 Network
*network
= userdata
;
1197 union in_addr_union
*buffer
;
1207 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1211 if (streq(lvalue
, "To")) {
1213 prefixlen
= &n
->to_prefixlen
;
1216 prefixlen
= &n
->from_prefixlen
;
1219 if (n
->family
== AF_UNSPEC
)
1220 r
= in_addr_prefix_from_string_auto(rvalue
, &n
->family
, buffer
, prefixlen
);
1222 r
= in_addr_prefix_from_string(rvalue
, n
->family
, buffer
, prefixlen
);
1224 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue
);
1232 int config_parse_routing_policy_rule_device(
1234 const char *filename
,
1236 const char *section
,
1237 unsigned section_line
,
1244 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1245 Network
*network
= userdata
;
1254 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1258 if (!ifname_valid(rvalue
)) {
1259 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "Failed to parse '%s' interface name, ignoring: %s", lvalue
, rvalue
);
1263 if (streq(lvalue
, "IncomingInterface")) {
1264 r
= free_and_strdup(&n
->iif
, rvalue
);
1268 r
= free_and_strdup(&n
->oif
, rvalue
);
1277 int config_parse_routing_policy_rule_port_range(
1279 const char *filename
,
1281 const char *section
,
1282 unsigned section_line
,
1288 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1289 Network
*network
= userdata
;
1299 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1303 r
= parse_ip_port_range(rvalue
, &low
, &high
);
1305 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse routing policy rule port range '%s'", rvalue
);
1309 if (streq(lvalue
, "SourcePort")) {
1310 n
->sport
.start
= low
;
1311 n
->sport
.end
= high
;
1313 n
->dport
.start
= low
;
1314 n
->dport
.end
= high
;
1321 int config_parse_routing_policy_rule_ip_protocol(
1323 const char *filename
,
1325 const char *section
,
1326 unsigned section_line
,
1333 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1334 Network
*network
= userdata
;
1343 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1347 r
= parse_ip_protocol(rvalue
);
1349 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue
);
1359 int config_parse_routing_policy_rule_invert(
1361 const char *filename
,
1363 const char *section
,
1364 unsigned section_line
,
1371 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1372 Network
*network
= userdata
;
1381 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1385 r
= parse_boolean(rvalue
);
1387 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule invert, ignoring: %s", rvalue
);
1397 int config_parse_routing_policy_rule_family(
1399 const char *filename
,
1401 const char *section
,
1402 unsigned section_line
,
1409 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1410 Network
*network
= userdata
;
1420 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1424 a
= routing_policy_rule_address_family_from_string(rvalue
);
1426 log_syntax(unit
, LOG_WARNING
, filename
, line
, a
,
1427 "Invalid address family '%s', ignoring.", rvalue
);
1431 n
->address_family
= a
;
1437 int config_parse_routing_policy_rule_uid_range(
1439 const char *filename
,
1441 const char *section
,
1442 unsigned section_line
,
1449 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1450 Network
*network
= userdata
;
1460 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1464 r
= get_user_creds(&rvalue
, &start
, NULL
, NULL
, NULL
, 0);
1468 r
= parse_uid_range(rvalue
, &start
, &end
);
1470 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1471 "Invalid uid or uid range '%s', ignoring: %m", rvalue
);
1476 n
->uid_range
.start
= start
;
1477 n
->uid_range
.end
= end
;
1483 int config_parse_routing_policy_rule_suppress_prefixlen(
1485 const char *filename
,
1487 const char *section
,
1488 unsigned section_line
,
1495 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1496 Network
*network
= userdata
;
1505 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1509 r
= parse_ip_prefix_length(rvalue
, &n
->suppress_prefixlen
);
1511 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Prefix length outside of valid range 0-128, ignoring: %s", rvalue
);
1515 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", rvalue
);
1523 int config_parse_routing_policy_rule_type(
1525 const char *filename
,
1527 const char *section
,
1528 unsigned section_line
,
1535 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1536 Network
*network
= userdata
;
1545 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1549 t
= fr_act_type_from_string(rvalue
);
1551 log_syntax(unit
, LOG_WARNING
, filename
, line
, t
,
1552 "Could not parse FIB rule type \"%s\", ignoring assignment: %m", rvalue
);
1556 n
->type
= (uint8_t) t
;
1562 static int routing_policy_rule_section_verify(RoutingPolicyRule
*rule
) {
1563 if (section_is_invalid(rule
->section
))
1566 if ((rule
->family
== AF_INET
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) ||
1567 (rule
->family
== AF_INET6
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)))
1568 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1569 "%s: address family specified by Family= conflicts with the address "
1570 "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
1571 rule
->section
->filename
, rule
->section
->line
);
1573 if (rule
->family
== AF_UNSPEC
) {
1574 if (IN_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
, ADDRESS_FAMILY_NO
))
1575 rule
->family
= AF_INET
;
1576 else if (rule
->address_family
== ADDRESS_FAMILY_IPV6
)
1577 rule
->family
= AF_INET6
;
1578 /* rule->family can be AF_UNSPEC only when Family=both. */
1581 /* Currently, [RoutingPolicyRule] does not have a setting to set FRA_L3MDEV flag. Please also
1582 * update routing_policy_rule_is_created_by_kernel() when a new setting which sets the flag is
1583 * added in the future. */
1584 if (rule
->l3mdev
> 0)
1585 assert_not_reached("FRA_L3MDEV flag should not be configured.");
1590 void network_drop_invalid_routing_policy_rules(Network
*network
) {
1591 RoutingPolicyRule
*rule
;
1595 HASHMAP_FOREACH(rule
, network
->rules_by_section
)
1596 if (routing_policy_rule_section_verify(rule
) < 0)
1597 routing_policy_rule_free(rule
);