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.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 assert_cc(__FR_ACT_MAX
<= UINT8_MAX
);
33 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fr_act_type
, int);
35 RoutingPolicyRule
*routing_policy_rule_free(RoutingPolicyRule
*rule
) {
40 assert(rule
->section
);
41 hashmap_remove(rule
->network
->rules_by_section
, rule
->section
);
45 set_remove(rule
->manager
->rules
, rule
);
46 set_remove(rule
->manager
->rules_foreign
, rule
);
49 network_config_section_free(rule
->section
);
56 DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule
, routing_policy_rule_free
);
58 static int routing_policy_rule_new(RoutingPolicyRule
**ret
) {
59 RoutingPolicyRule
*rule
;
61 rule
= new(RoutingPolicyRule
, 1);
65 *rule
= (RoutingPolicyRule
) {
66 .table
= RT_TABLE_MAIN
,
67 .uid_range
.start
= UID_INVALID
,
68 .uid_range
.end
= UID_INVALID
,
69 .suppress_prefixlen
= -1,
70 .protocol
= RTPROT_UNSPEC
,
71 .type
= FR_ACT_TO_TBL
,
78 static int routing_policy_rule_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutingPolicyRule
**ret
) {
79 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
80 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
86 assert(section_line
> 0);
88 r
= network_config_section_new(filename
, section_line
, &n
);
92 rule
= hashmap_get(network
->rules_by_section
, n
);
94 *ret
= TAKE_PTR(rule
);
98 r
= routing_policy_rule_new(&rule
);
102 rule
->network
= network
;
103 rule
->section
= TAKE_PTR(n
);
104 rule
->protocol
= RTPROT_STATIC
;
106 r
= hashmap_ensure_put(&network
->rules_by_section
, &network_config_hash_ops
, rule
->section
, rule
);
110 *ret
= TAKE_PTR(rule
);
114 static int routing_policy_rule_dup(const RoutingPolicyRule
*src
, RoutingPolicyRule
**ret
) {
115 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*dest
= NULL
;
120 dest
= newdup(RoutingPolicyRule
, src
, 1);
124 /* Unset all pointers */
125 dest
->manager
= NULL
;
126 dest
->network
= NULL
;
127 dest
->section
= NULL
;
128 dest
->iif
= dest
->oif
= NULL
;
131 dest
->iif
= strdup(src
->iif
);
137 dest
->oif
= strdup(src
->oif
);
142 *ret
= TAKE_PTR(dest
);
146 void routing_policy_rule_hash_func(const RoutingPolicyRule
*rule
, struct siphash
*state
) {
149 siphash24_compress(&rule
->family
, sizeof(rule
->family
), state
);
151 switch (rule
->family
) {
154 siphash24_compress(&rule
->from
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
155 siphash24_compress(&rule
->from_prefixlen
, sizeof(rule
->from_prefixlen
), state
);
157 siphash24_compress(&rule
->to
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
158 siphash24_compress(&rule
->to_prefixlen
, sizeof(rule
->to_prefixlen
), state
);
160 siphash24_compress_boolean(rule
->invert_rule
, state
);
162 siphash24_compress(&rule
->tos
, sizeof(rule
->tos
), state
);
163 siphash24_compress(&rule
->type
, sizeof(rule
->type
), state
);
164 siphash24_compress(&rule
->fwmark
, sizeof(rule
->fwmark
), state
);
165 siphash24_compress(&rule
->fwmask
, sizeof(rule
->fwmask
), state
);
166 siphash24_compress(&rule
->priority
, sizeof(rule
->priority
), state
);
167 siphash24_compress(&rule
->table
, sizeof(rule
->table
), state
);
168 siphash24_compress(&rule
->suppress_prefixlen
, sizeof(rule
->suppress_prefixlen
), state
);
170 siphash24_compress(&rule
->ipproto
, sizeof(rule
->ipproto
), state
);
171 siphash24_compress(&rule
->protocol
, sizeof(rule
->protocol
), state
);
172 siphash24_compress(&rule
->sport
, sizeof(rule
->sport
), state
);
173 siphash24_compress(&rule
->dport
, sizeof(rule
->dport
), state
);
174 siphash24_compress(&rule
->uid_range
, sizeof(rule
->uid_range
), state
);
176 siphash24_compress_string(rule
->iif
, state
);
177 siphash24_compress_string(rule
->oif
, state
);
181 /* treat any other address family as AF_UNSPEC */
186 int routing_policy_rule_compare_func(const RoutingPolicyRule
*a
, const RoutingPolicyRule
*b
) {
189 r
= CMP(a
->family
, b
->family
);
196 r
= CMP(a
->from_prefixlen
, b
->from_prefixlen
);
200 r
= memcmp(&a
->from
, &b
->from
, FAMILY_ADDRESS_SIZE(a
->family
));
204 r
= CMP(a
->to_prefixlen
, b
->to_prefixlen
);
208 r
= memcmp(&a
->to
, &b
->to
, FAMILY_ADDRESS_SIZE(a
->family
));
212 r
= CMP(a
->invert_rule
, b
->invert_rule
);
216 r
= CMP(a
->tos
, b
->tos
);
220 r
= CMP(a
->type
, b
->type
);
224 r
= CMP(a
->fwmark
, b
->fwmark
);
228 r
= CMP(a
->fwmask
, b
->fwmask
);
232 r
= CMP(a
->priority
, b
->priority
);
236 r
= CMP(a
->table
, b
->table
);
240 r
= CMP(a
->suppress_prefixlen
, b
->suppress_prefixlen
);
244 r
= CMP(a
->ipproto
, b
->ipproto
);
248 r
= CMP(a
->protocol
, b
->protocol
);
252 r
= memcmp(&a
->sport
, &b
->sport
, sizeof(a
->sport
));
256 r
= memcmp(&a
->dport
, &b
->dport
, sizeof(a
->dport
));
260 r
= memcmp(&a
->uid_range
, &b
->uid_range
, sizeof(a
->uid_range
));
264 r
= strcmp_ptr(a
->iif
, b
->iif
);
268 r
= strcmp_ptr(a
->oif
, b
->oif
);
274 /* treat any other address family as AF_UNSPEC */
279 static bool routing_policy_rule_equal(const RoutingPolicyRule
*rule1
, const RoutingPolicyRule
*rule2
) {
283 if (!rule1
|| !rule2
)
286 return routing_policy_rule_compare_func(rule1
, rule2
) == 0;
289 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
290 routing_policy_rule_hash_ops
,
292 routing_policy_rule_hash_func
,
293 routing_policy_rule_compare_func
,
294 routing_policy_rule_free
);
296 static int routing_policy_rule_get(Manager
*m
, const RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
297 RoutingPolicyRule
*existing
;
301 existing
= set_get(m
->rules
, rule
);
308 existing
= set_get(m
->rules_foreign
, rule
);
318 static int routing_policy_rule_add(Manager
*m
, const RoutingPolicyRule
*in
, RoutingPolicyRule
**ret
) {
319 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
320 RoutingPolicyRule
*existing
;
325 assert(IN_SET(in
->family
, AF_INET
, AF_INET6
));
327 r
= routing_policy_rule_dup(in
, &rule
);
331 r
= routing_policy_rule_get(m
, rule
, &existing
);
333 /* Rule does not exist, use a new one. */
334 r
= set_ensure_put(&m
->rules
, &routing_policy_rule_hash_ops
, rule
);
340 existing
= TAKE_PTR(rule
);
344 /* Take over a foreign rule. */
345 r
= set_ensure_put(&m
->rules
, &routing_policy_rule_hash_ops
, existing
);
350 set_remove(m
->rules_foreign
, existing
);
351 } /* else r > 0: already exists, do nothing. */
358 static int routing_policy_rule_consume_foreign(Manager
*m
, RoutingPolicyRule
*rule
) {
363 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
365 r
= set_ensure_consume(&m
->rules_foreign
, &routing_policy_rule_hash_ops
, rule
);
374 static void log_routing_policy_rule_debug(const RoutingPolicyRule
*rule
, const char *str
, const Link
*link
, const Manager
*m
) {
375 _cleanup_free_
char *from
= NULL
, *to
= NULL
, *table
= NULL
;
378 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
382 /* link may be NULL. */
387 (void) in_addr_prefix_to_string(rule
->family
, &rule
->from
, rule
->from_prefixlen
, &from
);
388 (void) in_addr_prefix_to_string(rule
->family
, &rule
->to
, rule
->to_prefixlen
, &to
);
389 (void) manager_get_route_table_to_string(m
, rule
->table
, &table
);
392 "%s routing policy rule: priority: %"PRIu32
", %s -> %s, iif: %s, oif: %s, table: %s",
393 str
, rule
->priority
, strna(from
), strna(to
),
394 strna(rule
->iif
), strna(rule
->oif
), strna(table
));
397 static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule
*rule
, sd_netlink_message
*m
, Link
*link
) {
403 /* link may be NULL. */
405 if (rule
->from_prefixlen
> 0) {
406 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, rule
->family
, &rule
->from
);
408 return log_link_error_errno(link
, r
, "Could not append FRA_SRC attribute: %m");
410 r
= sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(m
, rule
->from_prefixlen
);
412 return log_link_error_errno(link
, r
, "Could not set source prefix length: %m");
415 if (rule
->to_prefixlen
> 0) {
416 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, rule
->family
, &rule
->to
);
418 return log_link_error_errno(link
, r
, "Could not append FRA_DST attribute: %m");
420 r
= sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(m
, rule
->to_prefixlen
);
422 return log_link_error_errno(link
, r
, "Could not set destination prefix length: %m");
425 r
= sd_netlink_message_append_u32(m
, FRA_PRIORITY
, rule
->priority
);
427 return log_link_error_errno(link
, r
, "Could not append FRA_PRIORITY attribute: %m");
430 r
= sd_rtnl_message_routing_policy_rule_set_tos(m
, rule
->tos
);
432 return log_link_error_errno(link
, r
, "Could not set IP rule TOS: %m");
435 if (rule
->table
< 256) {
436 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, rule
->table
);
438 return log_link_error_errno(link
, r
, "Could not set IP rule table: %m");
440 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
442 return log_link_error_errno(link
, r
, "Could not set IP rule table: %m");
444 r
= sd_netlink_message_append_u32(m
, FRA_TABLE
, rule
->table
);
446 return log_link_error_errno(link
, r
, "Could not append FRA_TABLE attribute: %m");
449 if (rule
->fwmark
> 0) {
450 r
= sd_netlink_message_append_u32(m
, FRA_FWMARK
, rule
->fwmark
);
452 return log_link_error_errno(link
, r
, "Could not append FRA_FWMARK attribute: %m");
454 r
= sd_netlink_message_append_u32(m
, FRA_FWMASK
, rule
->fwmask
);
456 return log_link_error_errno(link
, r
, "Could not append FRA_FWMASK attribute: %m");
460 r
= sd_netlink_message_append_string(m
, FRA_IIFNAME
, rule
->iif
);
462 return log_link_error_errno(link
, r
, "Could not append FRA_IIFNAME attribute: %m");
466 r
= sd_netlink_message_append_string(m
, FRA_OIFNAME
, rule
->oif
);
468 return log_link_error_errno(link
, r
, "Could not append FRA_OIFNAME attribute: %m");
471 r
= sd_netlink_message_append_u8(m
, FRA_IP_PROTO
, rule
->ipproto
);
473 return log_link_error_errno(link
, r
, "Could not append FRA_IP_PROTO attribute: %m");
475 r
= sd_netlink_message_append_u8(m
, FRA_PROTOCOL
, rule
->protocol
);
477 return log_link_error_errno(link
, r
, "Could not append FRA_PROTOCOL attribute: %m");
479 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
480 r
= sd_netlink_message_append_data(m
, FRA_SPORT_RANGE
, &rule
->sport
, sizeof(rule
->sport
));
482 return log_link_error_errno(link
, r
, "Could not append FRA_SPORT_RANGE attribute: %m");
485 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
486 r
= sd_netlink_message_append_data(m
, FRA_DPORT_RANGE
, &rule
->dport
, sizeof(rule
->dport
));
488 return log_link_error_errno(link
, r
, "Could not append FRA_DPORT_RANGE attribute: %m");
491 if (rule
->uid_range
.start
!= UID_INVALID
&& rule
->uid_range
.end
!= UID_INVALID
) {
492 r
= sd_netlink_message_append_data(m
, FRA_UID_RANGE
, &rule
->uid_range
, sizeof(rule
->uid_range
));
494 return log_link_error_errno(link
, r
, "Could not append FRA_UID_RANGE attribute: %m");
497 if (rule
->invert_rule
) {
498 r
= sd_rtnl_message_routing_policy_rule_set_flags(m
, FIB_RULE_INVERT
);
500 return log_link_error_errno(link
, r
, "Could not append FIB_RULE_INVERT attribute: %m");
503 if (rule
->suppress_prefixlen
>= 0) {
504 r
= sd_netlink_message_append_u32(m
, FRA_SUPPRESS_PREFIXLEN
, (uint32_t) rule
->suppress_prefixlen
);
506 return log_link_error_errno(link
, r
, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m");
509 r
= sd_rtnl_message_routing_policy_rule_set_fib_type(m
, rule
->type
);
511 return log_link_error_errno(link
, r
, "Could not append FIB rule type attribute: %m");
516 static int routing_policy_rule_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Manager
*manager
) {
521 assert(manager
->routing_policy_rule_remove_messages
> 0);
523 manager
->routing_policy_rule_remove_messages
--;
525 r
= sd_netlink_message_get_errno(m
);
527 log_message_warning_errno(m
, r
, "Could not drop routing policy rule");
532 static int routing_policy_rule_remove(const RoutingPolicyRule
*rule
, Manager
*manager
) {
533 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
538 assert(manager
->rtnl
);
539 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
541 log_routing_policy_rule_debug(rule
, "Removing", NULL
, manager
);
543 r
= sd_rtnl_message_new_routing_policy_rule(manager
->rtnl
, &m
, RTM_DELRULE
, rule
->family
);
545 return log_error_errno(r
, "Could not allocate RTM_DELRULE message: %m");
547 r
= routing_policy_rule_set_netlink_message(rule
, m
, NULL
);
551 r
= netlink_call_async(manager
->rtnl
, NULL
, m
,
552 routing_policy_rule_remove_handler
,
555 return log_error_errno(r
, "Could not send rtnetlink message: %m");
557 manager
->routing_policy_rule_remove_messages
++;
562 static int routing_policy_rule_configure(
563 const RoutingPolicyRule
*rule
,
565 link_netlink_message_handler_t callback
,
566 RoutingPolicyRule
**ret
) {
568 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
572 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
574 assert(link
->ifindex
> 0);
575 assert(link
->manager
);
576 assert(link
->manager
->rtnl
);
579 log_routing_policy_rule_debug(rule
, "Configuring", link
, link
->manager
);
581 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_NEWRULE
, rule
->family
);
583 return log_link_error_errno(link
, r
, "Could not allocate RTM_NEWRULE message: %m");
585 r
= routing_policy_rule_set_netlink_message(rule
, m
, link
);
589 r
= routing_policy_rule_add(link
->manager
, rule
, ret
);
591 return log_link_error_errno(link
, r
, "Could not add rule: %m");
593 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
, callback
,
594 link_netlink_destroy_callback
, link
);
596 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
603 static int links_have_routing_policy_rule(const Manager
*m
, const RoutingPolicyRule
*rule
, const Link
*except
) {
610 HASHMAP_FOREACH(link
, m
->links_by_index
) {
611 RoutingPolicyRule
*link_rule
;
619 HASHMAP_FOREACH(link_rule
, link
->network
->rules_by_section
)
620 if (IN_SET(link_rule
->family
, AF_INET
, AF_INET6
)) {
621 if (routing_policy_rule_equal(link_rule
, rule
))
624 /* The case Family=both. */
625 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
627 r
= routing_policy_rule_dup(link_rule
, &tmp
);
631 tmp
->family
= AF_INET
;
632 if (routing_policy_rule_equal(tmp
, rule
))
635 tmp
->family
= AF_INET6
;
636 if (routing_policy_rule_equal(tmp
, rule
))
644 int manager_drop_routing_policy_rules_internal(Manager
*m
, bool foreign
, const Link
*except
) {
645 RoutingPolicyRule
*rule
;
651 rules
= foreign
? m
->rules_foreign
: m
->rules
;
652 SET_FOREACH(rule
, rules
) {
653 /* Do not touch rules managed by kernel. */
654 if (rule
->protocol
== RTPROT_KERNEL
)
657 /* The rule will be configured later, or already configured by a link. */
658 k
= links_have_routing_policy_rule(m
, rule
, except
);
665 k
= routing_policy_rule_remove(rule
, m
);
673 static int static_routing_policy_rule_configure_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
679 assert(link
->ifname
);
680 assert(link
->static_routing_policy_rule_messages
> 0);
682 link
->static_routing_policy_rule_messages
--;
684 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
687 r
= sd_netlink_message_get_errno(m
);
688 if (r
< 0 && r
!= -EEXIST
) {
689 log_link_message_warning_errno(link
, m
, r
, "Could not add routing policy rule");
690 link_enter_failed(link
);
694 if (link
->static_routing_policy_rule_messages
== 0) {
695 log_link_debug(link
, "Routing policy rule configured");
696 link
->static_routing_policy_rules_configured
= true;
697 link_check_ready(link
);
703 static int link_request_routing_policy_rule(
705 RoutingPolicyRule
*rule
,
707 unsigned *message_counter
,
708 link_netlink_message_handler_t netlink_handler
,
712 assert(link
->manager
);
715 log_routing_policy_rule_debug(rule
, "Requesting", link
, link
->manager
);
716 return link_queue_request(link
, REQUEST_TYPE_ROUTING_POLICY_RULE
, rule
, consume_object
,
717 message_counter
, netlink_handler
, ret
);
720 static int link_request_static_routing_policy_rule(Link
*link
, RoutingPolicyRule
*rule
) {
723 if (IN_SET(rule
->family
, AF_INET
, AF_INET6
))
724 return link_request_routing_policy_rule(link
, rule
, false,
725 &link
->static_routing_policy_rule_messages
,
726 static_routing_policy_rule_configure_handler
,
729 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)) {
730 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
732 r
= routing_policy_rule_dup(rule
, &tmp
);
736 tmp
->family
= AF_INET
;
738 r
= link_request_routing_policy_rule(link
, TAKE_PTR(tmp
), true,
739 &link
->static_routing_policy_rule_messages
,
740 static_routing_policy_rule_configure_handler
,
746 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) {
747 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
749 r
= routing_policy_rule_dup(rule
, &tmp
);
753 tmp
->family
= AF_INET6
;
755 r
= link_request_routing_policy_rule(link
, TAKE_PTR(tmp
), true,
756 &link
->static_routing_policy_rule_messages
,
757 static_routing_policy_rule_configure_handler
,
766 int link_request_static_routing_policy_rules(Link
*link
) {
767 RoutingPolicyRule
*rule
;
771 assert(link
->network
);
773 link
->static_routing_policy_rules_configured
= false;
775 HASHMAP_FOREACH(rule
, link
->network
->rules_by_section
) {
776 r
= link_request_static_routing_policy_rule(link
, rule
);
778 return log_link_warning_errno(link
, r
, "Could not request routing policy rule: %m");
781 if (link
->static_routing_policy_rule_messages
== 0) {
782 link
->static_routing_policy_rules_configured
= true;
783 link_check_ready(link
);
785 log_link_debug(link
, "Requesting routing policy rules");
786 link_set_state(link
, LINK_STATE_CONFIGURING
);
792 int request_process_routing_policy_rule(Request
*req
) {
793 RoutingPolicyRule
*ret
= NULL
; /* avoid false maybe-uninitialized warning */
799 assert(req
->type
== REQUEST_TYPE_ROUTING_POLICY_RULE
);
801 if (!link_is_ready_to_configure(req
->link
, false))
804 if (req
->link
->manager
->routing_policy_rule_remove_messages
> 0)
807 r
= routing_policy_rule_configure(req
->rule
, req
->link
, req
->netlink_handler
, &ret
);
811 /* To prevent a double decrement on failure in after_configure(). */
812 req
->message_counter
= NULL
;
814 if (req
->after_configure
) {
815 r
= req
->after_configure(req
, ret
);
823 static const RoutingPolicyRule kernel_rules
[] = {
824 { .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, },
825 { .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, },
826 { .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, },
827 { .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, },
828 { .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, },
831 static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule
*rule
) {
834 if (rule
->l3mdev
> 0)
835 /* Currently, [RoutingPolicyRule] does not explicitly set FRA_L3MDEV. So, if the flag
836 * is set, it is safe to treat the rule as created by kernel. */
839 for (size_t i
= 0; i
< ELEMENTSOF(kernel_rules
); i
++)
840 if (routing_policy_rule_equal(rule
, &kernel_rules
[i
]))
846 int manager_rtnl_process_rule(sd_netlink
*rtnl
, sd_netlink_message
*message
, Manager
*m
) {
847 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
848 RoutingPolicyRule
*rule
= NULL
;
849 const char *iif
= NULL
, *oif
= NULL
;
850 bool adjust_protocol
= false;
851 uint32_t suppress_prefixlen
;
859 if (sd_netlink_message_is_error(message
)) {
860 r
= sd_netlink_message_get_errno(message
);
862 log_message_warning_errno(message
, r
, "rtnl: failed to receive rule message, ignoring");
867 r
= sd_netlink_message_get_type(message
, &type
);
869 log_warning_errno(r
, "rtnl: could not get message type, ignoring: %m");
871 } else if (!IN_SET(type
, RTM_NEWRULE
, RTM_DELRULE
)) {
872 log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type
);
876 r
= routing_policy_rule_new(&tmp
);
882 r
= sd_rtnl_message_get_family(message
, &tmp
->family
);
884 log_warning_errno(r
, "rtnl: could not get rule family, ignoring: %m");
886 } else if (!IN_SET(tmp
->family
, AF_INET
, AF_INET6
)) {
887 log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp
->family
);
891 r
= netlink_message_read_in_addr_union(message
, FRA_SRC
, tmp
->family
, &tmp
->from
);
892 if (r
< 0 && r
!= -ENODATA
) {
893 log_warning_errno(r
, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
896 r
= sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(message
, &tmp
->from_prefixlen
);
898 log_warning_errno(r
, "rtnl: received rule message without valid source prefix length, ignoring: %m");
903 r
= netlink_message_read_in_addr_union(message
, FRA_DST
, tmp
->family
, &tmp
->to
);
904 if (r
< 0 && r
!= -ENODATA
) {
905 log_warning_errno(r
, "rtnl: could not get FRA_DST attribute, ignoring: %m");
908 r
= sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(message
, &tmp
->to_prefixlen
);
910 log_warning_errno(r
, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
915 r
= sd_rtnl_message_routing_policy_rule_get_flags(message
, &flags
);
917 log_warning_errno(r
, "rtnl: received rule message without valid flag, ignoring: %m");
920 tmp
->invert_rule
= flags
& FIB_RULE_INVERT
;
922 r
= sd_netlink_message_read_u32(message
, FRA_FWMARK
, &tmp
->fwmark
);
923 if (r
< 0 && r
!= -ENODATA
) {
924 log_warning_errno(r
, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m");
928 r
= sd_netlink_message_read_u32(message
, FRA_FWMASK
, &tmp
->fwmask
);
929 if (r
< 0 && r
!= -ENODATA
) {
930 log_warning_errno(r
, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m");
934 r
= sd_netlink_message_read_u32(message
, FRA_PRIORITY
, &tmp
->priority
);
935 if (r
< 0 && r
!= -ENODATA
) {
936 log_warning_errno(r
, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
940 r
= sd_netlink_message_read_u32(message
, FRA_TABLE
, &tmp
->table
);
941 if (r
< 0 && r
!= -ENODATA
) {
942 log_warning_errno(r
, "rtnl: could not get FRA_TABLE attribute, ignoring: %m");
946 r
= sd_rtnl_message_routing_policy_rule_get_tos(message
, &tmp
->tos
);
947 if (r
< 0 && r
!= -ENODATA
) {
948 log_warning_errno(r
, "rtnl: could not get FIB rule TOS, ignoring: %m");
952 r
= sd_rtnl_message_routing_policy_rule_get_fib_type(message
, &tmp
->type
);
953 if (r
< 0 && r
!= -ENODATA
) {
954 log_warning_errno(r
, "rtnl: could not get FIB rule type, ignoring: %m");
958 r
= sd_netlink_message_read_string(message
, FRA_IIFNAME
, &iif
);
959 if (r
< 0 && r
!= -ENODATA
) {
960 log_warning_errno(r
, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
963 r
= free_and_strdup(&tmp
->iif
, iif
);
967 r
= sd_netlink_message_read_string(message
, FRA_OIFNAME
, &oif
);
968 if (r
< 0 && r
!= -ENODATA
) {
969 log_warning_errno(r
, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m");
972 r
= free_and_strdup(&tmp
->oif
, oif
);
976 r
= sd_netlink_message_read_u8(message
, FRA_IP_PROTO
, &tmp
->ipproto
);
977 if (r
< 0 && r
!= -ENODATA
) {
978 log_warning_errno(r
, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
982 r
= sd_netlink_message_read_u8(message
, FRA_PROTOCOL
, &tmp
->protocol
);
984 /* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended.
985 * When the received message does not have FRA_PROTOCOL, then we need to adjust the
986 * protocol of the rule later. */
987 adjust_protocol
= true;
989 log_warning_errno(r
, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m");
993 r
= sd_netlink_message_read_u8(message
, FRA_L3MDEV
, &tmp
->l3mdev
);
994 if (r
< 0 && r
!= -ENODATA
) {
995 log_warning_errno(r
, "rtnl: could not get FRA_L3MDEV attribute, ignoring: %m");
999 r
= sd_netlink_message_read(message
, FRA_SPORT_RANGE
, sizeof(tmp
->sport
), &tmp
->sport
);
1000 if (r
< 0 && r
!= -ENODATA
) {
1001 log_warning_errno(r
, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
1005 r
= sd_netlink_message_read(message
, FRA_DPORT_RANGE
, sizeof(tmp
->dport
), &tmp
->dport
);
1006 if (r
< 0 && r
!= -ENODATA
) {
1007 log_warning_errno(r
, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
1011 r
= sd_netlink_message_read(message
, FRA_UID_RANGE
, sizeof(tmp
->uid_range
), &tmp
->uid_range
);
1012 if (r
< 0 && r
!= -ENODATA
) {
1013 log_warning_errno(r
, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m");
1017 r
= sd_netlink_message_read_u32(message
, FRA_SUPPRESS_PREFIXLEN
, &suppress_prefixlen
);
1018 if (r
< 0 && r
!= -ENODATA
) {
1019 log_warning_errno(r
, "rtnl: could not get FRA_SUPPRESS_PREFIXLEN attribute, ignoring: %m");
1023 tmp
->suppress_prefixlen
= (int) suppress_prefixlen
;
1025 if (adjust_protocol
)
1026 /* As .network files does not have setting to specify protocol, we can assume the
1027 * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */
1028 tmp
->protocol
= routing_policy_rule_is_created_by_kernel(tmp
) ? RTPROT_KERNEL
: RTPROT_STATIC
;
1030 (void) routing_policy_rule_get(m
, tmp
, &rule
);
1035 log_routing_policy_rule_debug(tmp
, "Received remembered", NULL
, m
);
1036 else if (!m
->manage_foreign_routes
)
1037 log_routing_policy_rule_debug(tmp
, "Ignoring received foreign", NULL
, m
);
1039 log_routing_policy_rule_debug(tmp
, "Remembering foreign", NULL
, m
);
1040 r
= routing_policy_rule_consume_foreign(m
, TAKE_PTR(tmp
));
1042 log_warning_errno(r
, "Could not remember foreign rule, ignoring: %m");
1047 log_routing_policy_rule_debug(tmp
, "Forgetting", NULL
, m
);
1048 routing_policy_rule_free(rule
);
1050 log_routing_policy_rule_debug(tmp
, "Kernel removed unknown", NULL
, m
);
1054 assert_not_reached();
1060 static int parse_fwmark_fwmask(const char *s
, uint32_t *ret_fwmark
, uint32_t *ret_fwmask
) {
1061 _cleanup_free_
char *fwmark_str
= NULL
;
1062 uint32_t fwmark
, fwmask
= 0;
1070 slash
= strchr(s
, '/');
1072 fwmark_str
= strndup(s
, slash
- s
);
1077 r
= safe_atou32(fwmark_str
?: s
, &fwmark
);
1083 r
= safe_atou32(slash
+ 1, &fwmask
);
1087 fwmask
= UINT32_MAX
;
1090 *ret_fwmark
= fwmark
;
1091 *ret_fwmask
= fwmask
;
1096 int config_parse_routing_policy_rule_tos(
1098 const char *filename
,
1100 const char *section
,
1101 unsigned section_line
,
1108 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1109 Network
*network
= userdata
;
1118 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1122 r
= safe_atou8(rvalue
, &n
->tos
);
1124 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule TOS, ignoring: %s", rvalue
);
1132 int config_parse_routing_policy_rule_priority(
1134 const char *filename
,
1136 const char *section
,
1137 unsigned section_line
,
1144 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1145 Network
*network
= userdata
;
1154 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1158 r
= safe_atou32(rvalue
, &n
->priority
);
1160 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule priority, ignoring: %s", rvalue
);
1168 int config_parse_routing_policy_rule_table(
1170 const char *filename
,
1172 const char *section
,
1173 unsigned section_line
,
1180 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1181 Network
*network
= userdata
;
1190 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1194 r
= manager_get_route_table_from_string(network
->manager
, rvalue
, &n
->table
);
1196 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1197 "Could not parse RPDB rule route table number \"%s\", ignoring assignment: %m", rvalue
);
1205 int config_parse_routing_policy_rule_fwmark_mask(
1207 const char *filename
,
1209 const char *section
,
1210 unsigned section_line
,
1217 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1218 Network
*network
= userdata
;
1227 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1231 r
= parse_fwmark_fwmask(rvalue
, &n
->fwmark
, &n
->fwmask
);
1233 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue
);
1241 int config_parse_routing_policy_rule_prefix(
1243 const char *filename
,
1245 const char *section
,
1246 unsigned section_line
,
1253 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1254 Network
*network
= userdata
;
1255 union in_addr_union
*buffer
;
1265 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1269 if (streq(lvalue
, "To")) {
1271 prefixlen
= &n
->to_prefixlen
;
1274 prefixlen
= &n
->from_prefixlen
;
1277 if (n
->family
== AF_UNSPEC
)
1278 r
= in_addr_prefix_from_string_auto(rvalue
, &n
->family
, buffer
, prefixlen
);
1280 r
= in_addr_prefix_from_string(rvalue
, n
->family
, buffer
, prefixlen
);
1282 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue
);
1290 int config_parse_routing_policy_rule_device(
1292 const char *filename
,
1294 const char *section
,
1295 unsigned section_line
,
1302 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1303 Network
*network
= userdata
;
1312 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1316 if (!ifname_valid(rvalue
)) {
1317 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1318 "Invalid interface name '%s' in %s=, ignoring assignment.", rvalue
, lvalue
);
1322 r
= free_and_strdup(streq(lvalue
, "IncomingInterface") ? &n
->iif
: &n
->oif
, rvalue
);
1330 int config_parse_routing_policy_rule_port_range(
1332 const char *filename
,
1334 const char *section
,
1335 unsigned section_line
,
1342 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1343 Network
*network
= userdata
;
1353 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1357 r
= parse_ip_port_range(rvalue
, &low
, &high
);
1359 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse routing policy rule port range '%s'", rvalue
);
1363 if (streq(lvalue
, "SourcePort")) {
1364 n
->sport
.start
= low
;
1365 n
->sport
.end
= high
;
1367 n
->dport
.start
= low
;
1368 n
->dport
.end
= high
;
1375 int config_parse_routing_policy_rule_ip_protocol(
1377 const char *filename
,
1379 const char *section
,
1380 unsigned section_line
,
1387 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1388 Network
*network
= userdata
;
1397 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1401 r
= parse_ip_protocol(rvalue
);
1403 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue
);
1413 int config_parse_routing_policy_rule_invert(
1415 const char *filename
,
1417 const char *section
,
1418 unsigned section_line
,
1425 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1426 Network
*network
= userdata
;
1435 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1439 r
= parse_boolean(rvalue
);
1441 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule invert, ignoring: %s", rvalue
);
1451 int config_parse_routing_policy_rule_family(
1453 const char *filename
,
1455 const char *section
,
1456 unsigned section_line
,
1463 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1464 Network
*network
= userdata
;
1474 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1478 a
= routing_policy_rule_address_family_from_string(rvalue
);
1480 log_syntax(unit
, LOG_WARNING
, filename
, line
, a
,
1481 "Invalid address family '%s', ignoring.", rvalue
);
1485 n
->address_family
= a
;
1491 int config_parse_routing_policy_rule_uid_range(
1493 const char *filename
,
1495 const char *section
,
1496 unsigned section_line
,
1503 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1504 Network
*network
= userdata
;
1514 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1518 r
= get_user_creds(&rvalue
, &start
, NULL
, NULL
, NULL
, 0);
1522 r
= parse_uid_range(rvalue
, &start
, &end
);
1524 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1525 "Invalid uid or uid range '%s', ignoring: %m", rvalue
);
1530 n
->uid_range
.start
= start
;
1531 n
->uid_range
.end
= end
;
1537 int config_parse_routing_policy_rule_suppress_prefixlen(
1539 const char *filename
,
1541 const char *section
,
1542 unsigned section_line
,
1549 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1550 Network
*network
= userdata
;
1559 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1563 r
= parse_ip_prefix_length(rvalue
, &n
->suppress_prefixlen
);
1565 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Prefix length outside of valid range 0-128, ignoring: %s", rvalue
);
1569 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", rvalue
);
1577 int config_parse_routing_policy_rule_type(
1579 const char *filename
,
1581 const char *section
,
1582 unsigned section_line
,
1589 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1590 Network
*network
= userdata
;
1599 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1603 t
= fr_act_type_from_string(rvalue
);
1605 log_syntax(unit
, LOG_WARNING
, filename
, line
, t
,
1606 "Could not parse FIB rule type \"%s\", ignoring assignment: %m", rvalue
);
1610 n
->type
= (uint8_t) t
;
1616 static int routing_policy_rule_section_verify(RoutingPolicyRule
*rule
) {
1617 if (section_is_invalid(rule
->section
))
1620 if ((rule
->family
== AF_INET
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) ||
1621 (rule
->family
== AF_INET6
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)))
1622 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1623 "%s: address family specified by Family= conflicts with the address "
1624 "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
1625 rule
->section
->filename
, rule
->section
->line
);
1627 if (rule
->family
== AF_UNSPEC
) {
1628 if (IN_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
, ADDRESS_FAMILY_NO
))
1629 rule
->family
= AF_INET
;
1630 else if (rule
->address_family
== ADDRESS_FAMILY_IPV6
)
1631 rule
->family
= AF_INET6
;
1632 /* rule->family can be AF_UNSPEC only when Family=both. */
1635 /* Currently, [RoutingPolicyRule] does not have a setting to set FRA_L3MDEV flag. Please also
1636 * update routing_policy_rule_is_created_by_kernel() when a new setting which sets the flag is
1637 * added in the future. */
1638 if (rule
->l3mdev
> 0)
1639 assert_not_reached();
1644 void network_drop_invalid_routing_policy_rules(Network
*network
) {
1645 RoutingPolicyRule
*rule
;
1649 HASHMAP_FOREACH(rule
, network
->rules_by_section
)
1650 if (routing_policy_rule_section_verify(rule
) < 0)
1651 routing_policy_rule_free(rule
);