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 static 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 static 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
;
326 assert(IN_SET(in
->family
, AF_INET
, AF_INET6
));
328 r
= routing_policy_rule_dup(in
, &rule
);
332 r
= routing_policy_rule_get(m
, rule
, &existing
);
334 /* Rule does not exist, use a new one. */
335 r
= set_ensure_put(&m
->rules
, &routing_policy_rule_hash_ops
, rule
);
341 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
);
352 /* Already exists, do nothing. */
362 static int routing_policy_rule_consume_foreign(Manager
*m
, RoutingPolicyRule
*rule
) {
367 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
369 r
= set_ensure_consume(&m
->rules_foreign
, &routing_policy_rule_hash_ops
, rule
);
378 static void log_routing_policy_rule_debug(const RoutingPolicyRule
*rule
, const char *str
, const Link
*link
, const Manager
*m
) {
379 _cleanup_free_
char *from
= NULL
, *to
= NULL
, *table
= NULL
;
382 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
386 /* link may be NULL. */
391 (void) in_addr_prefix_to_string(rule
->family
, &rule
->from
, rule
->from_prefixlen
, &from
);
392 (void) in_addr_prefix_to_string(rule
->family
, &rule
->to
, rule
->to_prefixlen
, &to
);
393 (void) manager_get_route_table_to_string(m
, rule
->table
, &table
);
396 "%s routing policy rule: priority: %"PRIu32
", %s -> %s, iif: %s, oif: %s, table: %s",
397 str
, rule
->priority
, strna(from
), strna(to
),
398 strna(rule
->iif
), strna(rule
->oif
), strna(table
));
401 static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule
*rule
, sd_netlink_message
*m
, Link
*link
) {
407 /* link may be NULL. */
409 if (in_addr_is_set(rule
->family
, &rule
->from
)) {
410 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, rule
->family
, &rule
->from
);
412 return log_link_error_errno(link
, r
, "Could not append FRA_SRC attribute: %m");
414 r
= sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(m
, rule
->from_prefixlen
);
416 return log_link_error_errno(link
, r
, "Could not set source prefix length: %m");
419 if (in_addr_is_set(rule
->family
, &rule
->to
)) {
420 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, rule
->family
, &rule
->to
);
422 return log_link_error_errno(link
, r
, "Could not append FRA_DST attribute: %m");
424 r
= sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(m
, rule
->to_prefixlen
);
426 return log_link_error_errno(link
, r
, "Could not set destination prefix length: %m");
429 r
= sd_netlink_message_append_u32(m
, FRA_PRIORITY
, rule
->priority
);
431 return log_link_error_errno(link
, r
, "Could not append FRA_PRIORITY attribute: %m");
434 r
= sd_rtnl_message_routing_policy_rule_set_tos(m
, rule
->tos
);
436 return log_link_error_errno(link
, r
, "Could not set IP rule TOS: %m");
439 if (rule
->table
< 256) {
440 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, rule
->table
);
442 return log_link_error_errno(link
, r
, "Could not set IP rule table: %m");
444 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
446 return log_link_error_errno(link
, r
, "Could not set IP rule table: %m");
448 r
= sd_netlink_message_append_u32(m
, FRA_TABLE
, rule
->table
);
450 return log_link_error_errno(link
, r
, "Could not append FRA_TABLE attribute: %m");
453 if (rule
->fwmark
> 0) {
454 r
= sd_netlink_message_append_u32(m
, FRA_FWMARK
, rule
->fwmark
);
456 return log_link_error_errno(link
, r
, "Could not append FRA_FWMARK attribute: %m");
458 r
= sd_netlink_message_append_u32(m
, FRA_FWMASK
, rule
->fwmask
);
460 return log_link_error_errno(link
, r
, "Could not append FRA_FWMASK attribute: %m");
464 r
= sd_netlink_message_append_string(m
, FRA_IIFNAME
, rule
->iif
);
466 return log_link_error_errno(link
, r
, "Could not append FRA_IIFNAME attribute: %m");
470 r
= sd_netlink_message_append_string(m
, FRA_OIFNAME
, rule
->oif
);
472 return log_link_error_errno(link
, r
, "Could not append FRA_OIFNAME attribute: %m");
475 r
= sd_netlink_message_append_u8(m
, FRA_IP_PROTO
, rule
->ipproto
);
477 return log_link_error_errno(link
, r
, "Could not append FRA_IP_PROTO attribute: %m");
479 r
= sd_netlink_message_append_u8(m
, FRA_PROTOCOL
, rule
->protocol
);
481 return log_link_error_errno(link
, r
, "Could not append FRA_PROTOCOL attribute: %m");
483 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
484 r
= sd_netlink_message_append_data(m
, FRA_SPORT_RANGE
, &rule
->sport
, sizeof(rule
->sport
));
486 return log_link_error_errno(link
, r
, "Could not append FRA_SPORT_RANGE attribute: %m");
489 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
490 r
= sd_netlink_message_append_data(m
, FRA_DPORT_RANGE
, &rule
->dport
, sizeof(rule
->dport
));
492 return log_link_error_errno(link
, r
, "Could not append FRA_DPORT_RANGE attribute: %m");
495 if (rule
->uid_range
.start
!= UID_INVALID
&& rule
->uid_range
.end
!= UID_INVALID
) {
496 r
= sd_netlink_message_append_data(m
, FRA_UID_RANGE
, &rule
->uid_range
, sizeof(rule
->uid_range
));
498 return log_link_error_errno(link
, r
, "Could not append FRA_UID_RANGE attribute: %m");
501 if (rule
->invert_rule
) {
502 r
= sd_rtnl_message_routing_policy_rule_set_flags(m
, FIB_RULE_INVERT
);
504 return log_link_error_errno(link
, r
, "Could not append FIB_RULE_INVERT attribute: %m");
507 if (rule
->suppress_prefixlen
>= 0) {
508 r
= sd_netlink_message_append_u32(m
, FRA_SUPPRESS_PREFIXLEN
, (uint32_t) rule
->suppress_prefixlen
);
510 return log_link_error_errno(link
, r
, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m");
513 if (rule
->type
!= FR_ACT_TO_TBL
) {
514 r
= sd_rtnl_message_routing_policy_rule_set_fib_type(m
, rule
->type
);
516 return log_link_error_errno(link
, r
, "Could not append FIB rule type attribute: %m");
522 static int routing_policy_rule_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Manager
*manager
) {
527 assert(manager
->routing_policy_rule_remove_messages
> 0);
529 manager
->routing_policy_rule_remove_messages
--;
531 r
= sd_netlink_message_get_errno(m
);
533 log_message_warning_errno(m
, r
, "Could not drop routing policy rule");
538 static int routing_policy_rule_remove(const RoutingPolicyRule
*rule
, Manager
*manager
) {
539 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
544 assert(manager
->rtnl
);
545 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
547 log_routing_policy_rule_debug(rule
, "Removing", NULL
, manager
);
549 r
= sd_rtnl_message_new_routing_policy_rule(manager
->rtnl
, &m
, RTM_DELRULE
, rule
->family
);
551 return log_error_errno(r
, "Could not allocate RTM_DELRULE message: %m");
553 r
= routing_policy_rule_set_netlink_message(rule
, m
, NULL
);
557 r
= netlink_call_async(manager
->rtnl
, NULL
, m
,
558 routing_policy_rule_remove_handler
,
561 return log_error_errno(r
, "Could not send rtnetlink message: %m");
563 manager
->routing_policy_rule_remove_messages
++;
568 static int routing_policy_rule_configure(
569 const RoutingPolicyRule
*rule
,
571 link_netlink_message_handler_t callback
,
572 RoutingPolicyRule
**ret
) {
574 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
578 assert(IN_SET(rule
->family
, AF_INET
, AF_INET6
));
580 assert(link
->ifindex
> 0);
581 assert(link
->manager
);
582 assert(link
->manager
->rtnl
);
585 log_routing_policy_rule_debug(rule
, "Configuring", link
, link
->manager
);
587 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_NEWRULE
, rule
->family
);
589 return log_link_error_errno(link
, r
, "Could not allocate RTM_NEWRULE message: %m");
591 r
= routing_policy_rule_set_netlink_message(rule
, m
, link
);
595 r
= routing_policy_rule_add(link
->manager
, rule
, ret
);
597 return log_link_error_errno(link
, r
, "Could not add rule: %m");
599 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
, callback
,
600 link_netlink_destroy_callback
, link
);
602 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
609 static int links_have_routing_policy_rule(const Manager
*m
, const RoutingPolicyRule
*rule
, const Link
*except
) {
616 HASHMAP_FOREACH(link
, m
->links
) {
617 RoutingPolicyRule
*link_rule
;
625 HASHMAP_FOREACH(link_rule
, link
->network
->rules_by_section
)
626 if (IN_SET(link_rule
->family
, AF_INET
, AF_INET6
)) {
627 if (routing_policy_rule_equal(link_rule
, rule
))
630 /* The case Family=both. */
631 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
633 r
= routing_policy_rule_dup(link_rule
, &tmp
);
637 tmp
->family
= AF_INET
;
638 if (routing_policy_rule_equal(tmp
, rule
))
641 tmp
->family
= AF_INET6
;
642 if (routing_policy_rule_equal(tmp
, rule
))
650 int manager_drop_routing_policy_rules_internal(Manager
*m
, bool foreign
, const Link
*except
) {
651 RoutingPolicyRule
*rule
;
657 rules
= foreign
? m
->rules_foreign
: m
->rules
;
658 SET_FOREACH(rule
, rules
) {
659 /* Do not touch rules managed by kernel. */
660 if (rule
->protocol
== RTPROT_KERNEL
)
663 /* The rule will be configured later, or already configured by a link. */
664 k
= links_have_routing_policy_rule(m
, rule
, except
);
671 k
= routing_policy_rule_remove(rule
, m
);
679 static int static_routing_policy_rule_configure_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
685 assert(link
->ifname
);
686 assert(link
->static_routing_policy_rule_messages
> 0);
688 link
->static_routing_policy_rule_messages
--;
690 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
693 r
= sd_netlink_message_get_errno(m
);
694 if (r
< 0 && r
!= -EEXIST
) {
695 log_link_message_warning_errno(link
, m
, r
, "Could not add routing policy rule");
696 link_enter_failed(link
);
700 if (link
->static_routing_policy_rule_messages
== 0) {
701 log_link_debug(link
, "Routing policy rule configured");
702 link
->static_routing_policy_rules_configured
= true;
703 link_check_ready(link
);
709 static int link_request_routing_policy_rule(
711 RoutingPolicyRule
*rule
,
713 unsigned *message_counter
,
714 link_netlink_message_handler_t netlink_handler
,
718 assert(link
->manager
);
721 log_routing_policy_rule_debug(rule
, "Requesting", link
, link
->manager
);
722 return link_queue_request(link
, REQUEST_TYPE_ROUTING_POLICY_RULE
, rule
, consume_object
,
723 message_counter
, netlink_handler
, ret
);
726 static int link_request_static_routing_policy_rule(Link
*link
, RoutingPolicyRule
*rule
) {
729 if (IN_SET(rule
->family
, AF_INET
, AF_INET6
))
730 return link_request_routing_policy_rule(link
, rule
, false,
731 &link
->static_routing_policy_rule_messages
,
732 static_routing_policy_rule_configure_handler
,
735 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)) {
736 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
738 r
= routing_policy_rule_dup(rule
, &tmp
);
742 tmp
->family
= AF_INET
;
744 r
= link_request_routing_policy_rule(link
, TAKE_PTR(tmp
), true,
745 &link
->static_routing_policy_rule_messages
,
746 static_routing_policy_rule_configure_handler
,
752 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) {
753 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
755 r
= routing_policy_rule_dup(rule
, &tmp
);
759 tmp
->family
= AF_INET6
;
761 r
= link_request_routing_policy_rule(link
, TAKE_PTR(tmp
), true,
762 &link
->static_routing_policy_rule_messages
,
763 static_routing_policy_rule_configure_handler
,
772 int link_request_static_routing_policy_rules(Link
*link
) {
773 RoutingPolicyRule
*rule
;
777 assert(link
->network
);
779 link
->static_routing_policy_rules_configured
= false;
781 HASHMAP_FOREACH(rule
, link
->network
->rules_by_section
) {
782 r
= link_request_static_routing_policy_rule(link
, rule
);
784 return log_link_warning_errno(link
, r
, "Could not request routing policy rule: %m");
787 if (link
->static_routing_policy_rule_messages
== 0) {
788 link
->static_routing_policy_rules_configured
= true;
789 link_check_ready(link
);
791 log_link_debug(link
, "Requesting routing policy rules");
792 link_set_state(link
, LINK_STATE_CONFIGURING
);
798 int request_process_routing_policy_rule(Request
*req
) {
799 RoutingPolicyRule
*ret
= NULL
; /* avoid false maybe-uninitialized warning */
805 assert(req
->type
== REQUEST_TYPE_ROUTING_POLICY_RULE
);
807 if (!link_is_ready_to_configure(req
->link
, false))
810 if (req
->link
->manager
->routing_policy_rule_remove_messages
> 0)
813 r
= routing_policy_rule_configure(req
->rule
, req
->link
, req
->netlink_handler
, &ret
);
817 /* To prevent a double decrement on failure in after_configure(). */
818 req
->message_counter
= NULL
;
820 if (req
->after_configure
) {
821 r
= req
->after_configure(req
, ret
);
829 static const RoutingPolicyRule kernel_rules
[] = {
830 { .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, },
831 { .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, },
832 { .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, },
833 { .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, },
834 { .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, },
837 static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule
*rule
) {
840 if (rule
->l3mdev
> 0)
841 /* Currently, [RoutingPolicyRule] does not explicitly set FRA_L3MDEV. So, if the flag
842 * is set, it is safe to treat the rule as created by kernel. */
845 for (size_t i
= 0; i
< ELEMENTSOF(kernel_rules
); i
++)
846 if (routing_policy_rule_equal(rule
, &kernel_rules
[i
]))
852 int manager_rtnl_process_rule(sd_netlink
*rtnl
, sd_netlink_message
*message
, Manager
*m
) {
853 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*tmp
= NULL
;
854 RoutingPolicyRule
*rule
= NULL
;
855 const char *iif
= NULL
, *oif
= NULL
;
856 bool adjust_protocol
= false;
857 uint32_t suppress_prefixlen
;
865 if (sd_netlink_message_is_error(message
)) {
866 r
= sd_netlink_message_get_errno(message
);
868 log_message_warning_errno(message
, r
, "rtnl: failed to receive rule message, ignoring");
873 r
= sd_netlink_message_get_type(message
, &type
);
875 log_warning_errno(r
, "rtnl: could not get message type, ignoring: %m");
877 } else if (!IN_SET(type
, RTM_NEWRULE
, RTM_DELRULE
)) {
878 log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type
);
882 r
= routing_policy_rule_new(&tmp
);
888 r
= sd_rtnl_message_get_family(message
, &tmp
->family
);
890 log_warning_errno(r
, "rtnl: could not get rule family, ignoring: %m");
892 } else if (!IN_SET(tmp
->family
, AF_INET
, AF_INET6
)) {
893 log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp
->family
);
897 r
= netlink_message_read_in_addr_union(message
, FRA_SRC
, tmp
->family
, &tmp
->from
);
898 if (r
< 0 && r
!= -ENODATA
) {
899 log_warning_errno(r
, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
902 r
= sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(message
, &tmp
->from_prefixlen
);
904 log_warning_errno(r
, "rtnl: received rule message without valid source prefix length, ignoring: %m");
909 r
= netlink_message_read_in_addr_union(message
, FRA_DST
, tmp
->family
, &tmp
->to
);
910 if (r
< 0 && r
!= -ENODATA
) {
911 log_warning_errno(r
, "rtnl: could not get FRA_DST attribute, ignoring: %m");
914 r
= sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(message
, &tmp
->to_prefixlen
);
916 log_warning_errno(r
, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
921 r
= sd_rtnl_message_routing_policy_rule_get_flags(message
, &flags
);
923 log_warning_errno(r
, "rtnl: received rule message without valid flag, ignoring: %m");
926 tmp
->invert_rule
= flags
& FIB_RULE_INVERT
;
928 r
= sd_netlink_message_read_u32(message
, FRA_FWMARK
, &tmp
->fwmark
);
929 if (r
< 0 && r
!= -ENODATA
) {
930 log_warning_errno(r
, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m");
934 r
= sd_netlink_message_read_u32(message
, FRA_FWMASK
, &tmp
->fwmask
);
935 if (r
< 0 && r
!= -ENODATA
) {
936 log_warning_errno(r
, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m");
940 r
= sd_netlink_message_read_u32(message
, FRA_PRIORITY
, &tmp
->priority
);
941 if (r
< 0 && r
!= -ENODATA
) {
942 log_warning_errno(r
, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
946 r
= sd_netlink_message_read_u32(message
, FRA_TABLE
, &tmp
->table
);
947 if (r
< 0 && r
!= -ENODATA
) {
948 log_warning_errno(r
, "rtnl: could not get FRA_TABLE attribute, ignoring: %m");
952 r
= sd_rtnl_message_routing_policy_rule_get_tos(message
, &tmp
->tos
);
953 if (r
< 0 && r
!= -ENODATA
) {
954 log_warning_errno(r
, "rtnl: could not get FIB rule TOS, ignoring: %m");
958 r
= sd_rtnl_message_routing_policy_rule_get_fib_type(message
, &tmp
->type
);
959 if (r
< 0 && r
!= -ENODATA
) {
960 log_warning_errno(r
, "rtnl: could not get FIB rule type, ignoring: %m");
964 r
= sd_netlink_message_read_string(message
, FRA_IIFNAME
, &iif
);
965 if (r
< 0 && r
!= -ENODATA
) {
966 log_warning_errno(r
, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
969 r
= free_and_strdup(&tmp
->iif
, iif
);
973 r
= sd_netlink_message_read_string(message
, FRA_OIFNAME
, &oif
);
974 if (r
< 0 && r
!= -ENODATA
) {
975 log_warning_errno(r
, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m");
978 r
= free_and_strdup(&tmp
->oif
, oif
);
982 r
= sd_netlink_message_read_u8(message
, FRA_IP_PROTO
, &tmp
->ipproto
);
983 if (r
< 0 && r
!= -ENODATA
) {
984 log_warning_errno(r
, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
988 r
= sd_netlink_message_read_u8(message
, FRA_PROTOCOL
, &tmp
->protocol
);
990 /* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended.
991 * When the received message does not have FRA_PROTOCOL, then we need to adjust the
992 * protocol of the rule later. */
993 adjust_protocol
= true;
995 log_warning_errno(r
, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m");
999 r
= sd_netlink_message_read_u8(message
, FRA_L3MDEV
, &tmp
->l3mdev
);
1000 if (r
< 0 && r
!= -ENODATA
) {
1001 log_warning_errno(r
, "rtnl: could not get FRA_L3MDEV attribute, ignoring: %m");
1005 r
= sd_netlink_message_read(message
, FRA_SPORT_RANGE
, sizeof(tmp
->sport
), &tmp
->sport
);
1006 if (r
< 0 && r
!= -ENODATA
) {
1007 log_warning_errno(r
, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
1011 r
= sd_netlink_message_read(message
, FRA_DPORT_RANGE
, sizeof(tmp
->dport
), &tmp
->dport
);
1012 if (r
< 0 && r
!= -ENODATA
) {
1013 log_warning_errno(r
, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
1017 r
= sd_netlink_message_read(message
, FRA_UID_RANGE
, sizeof(tmp
->uid_range
), &tmp
->uid_range
);
1018 if (r
< 0 && r
!= -ENODATA
) {
1019 log_warning_errno(r
, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m");
1023 r
= sd_netlink_message_read_u32(message
, FRA_SUPPRESS_PREFIXLEN
, &suppress_prefixlen
);
1024 if (r
< 0 && r
!= -ENODATA
) {
1025 log_warning_errno(r
, "rtnl: could not get FRA_SUPPRESS_PREFIXLEN attribute, ignoring: %m");
1029 tmp
->suppress_prefixlen
= (int) suppress_prefixlen
;
1031 if (adjust_protocol
)
1032 /* As .network files does not have setting to specify protocol, we can assume the
1033 * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */
1034 tmp
->protocol
= routing_policy_rule_is_created_by_kernel(tmp
) ? RTPROT_KERNEL
: RTPROT_STATIC
;
1036 (void) routing_policy_rule_get(m
, tmp
, &rule
);
1041 log_routing_policy_rule_debug(tmp
, "Received remembered", NULL
, m
);
1042 else if (!m
->manage_foreign_routes
)
1043 log_routing_policy_rule_debug(tmp
, "Ignoring received foreign", NULL
, m
);
1045 log_routing_policy_rule_debug(tmp
, "Remembering foreign", NULL
, m
);
1046 r
= routing_policy_rule_consume_foreign(m
, TAKE_PTR(tmp
));
1048 log_warning_errno(r
, "Could not remember foreign rule, ignoring: %m");
1053 log_routing_policy_rule_debug(tmp
, "Forgetting", NULL
, m
);
1054 routing_policy_rule_free(rule
);
1056 log_routing_policy_rule_debug(tmp
, "Kernel removed unknown", NULL
, m
);
1060 assert_not_reached("Received invalid RTNL message type");
1066 static int parse_fwmark_fwmask(const char *s
, uint32_t *ret_fwmark
, uint32_t *ret_fwmask
) {
1067 _cleanup_free_
char *fwmark_str
= NULL
;
1068 uint32_t fwmark
, fwmask
= 0;
1076 slash
= strchr(s
, '/');
1078 fwmark_str
= strndup(s
, slash
- s
);
1083 r
= safe_atou32(fwmark_str
?: s
, &fwmark
);
1089 r
= safe_atou32(slash
+ 1, &fwmask
);
1093 fwmask
= UINT32_MAX
;
1096 *ret_fwmark
= fwmark
;
1097 *ret_fwmask
= fwmask
;
1102 int config_parse_routing_policy_rule_tos(
1104 const char *filename
,
1106 const char *section
,
1107 unsigned section_line
,
1114 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1115 Network
*network
= userdata
;
1124 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1128 r
= safe_atou8(rvalue
, &n
->tos
);
1130 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule TOS, ignoring: %s", rvalue
);
1138 int config_parse_routing_policy_rule_priority(
1140 const char *filename
,
1142 const char *section
,
1143 unsigned section_line
,
1150 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1151 Network
*network
= userdata
;
1160 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1164 r
= safe_atou32(rvalue
, &n
->priority
);
1166 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule priority, ignoring: %s", rvalue
);
1174 int config_parse_routing_policy_rule_table(
1176 const char *filename
,
1178 const char *section
,
1179 unsigned section_line
,
1186 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1187 Network
*network
= userdata
;
1196 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1200 r
= manager_get_route_table_from_string(network
->manager
, rvalue
, &n
->table
);
1202 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1203 "Could not parse RPDB rule route table number \"%s\", ignoring assignment: %m", rvalue
);
1211 int config_parse_routing_policy_rule_fwmark_mask(
1213 const char *filename
,
1215 const char *section
,
1216 unsigned section_line
,
1223 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1224 Network
*network
= userdata
;
1233 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1237 r
= parse_fwmark_fwmask(rvalue
, &n
->fwmark
, &n
->fwmask
);
1239 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue
);
1247 int config_parse_routing_policy_rule_prefix(
1249 const char *filename
,
1251 const char *section
,
1252 unsigned section_line
,
1259 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1260 Network
*network
= userdata
;
1261 union in_addr_union
*buffer
;
1271 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1275 if (streq(lvalue
, "To")) {
1277 prefixlen
= &n
->to_prefixlen
;
1280 prefixlen
= &n
->from_prefixlen
;
1283 if (n
->family
== AF_UNSPEC
)
1284 r
= in_addr_prefix_from_string_auto(rvalue
, &n
->family
, buffer
, prefixlen
);
1286 r
= in_addr_prefix_from_string(rvalue
, n
->family
, buffer
, prefixlen
);
1288 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue
);
1296 int config_parse_routing_policy_rule_device(
1298 const char *filename
,
1300 const char *section
,
1301 unsigned section_line
,
1308 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1309 Network
*network
= userdata
;
1318 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1322 if (!ifname_valid(rvalue
)) {
1323 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1324 "Invalid interface name '%s' in %s=, ignoring assignment.", rvalue
, lvalue
);
1328 r
= free_and_strdup(streq(lvalue
, "IncomingInterface") ? &n
->iif
: &n
->oif
, rvalue
);
1336 int config_parse_routing_policy_rule_port_range(
1338 const char *filename
,
1340 const char *section
,
1341 unsigned section_line
,
1348 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1349 Network
*network
= userdata
;
1359 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1363 r
= parse_ip_port_range(rvalue
, &low
, &high
);
1365 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse routing policy rule port range '%s'", rvalue
);
1369 if (streq(lvalue
, "SourcePort")) {
1370 n
->sport
.start
= low
;
1371 n
->sport
.end
= high
;
1373 n
->dport
.start
= low
;
1374 n
->dport
.end
= high
;
1381 int config_parse_routing_policy_rule_ip_protocol(
1383 const char *filename
,
1385 const char *section
,
1386 unsigned section_line
,
1393 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1394 Network
*network
= userdata
;
1403 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1407 r
= parse_ip_protocol(rvalue
);
1409 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue
);
1419 int config_parse_routing_policy_rule_invert(
1421 const char *filename
,
1423 const char *section
,
1424 unsigned section_line
,
1431 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1432 Network
*network
= userdata
;
1441 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1445 r
= parse_boolean(rvalue
);
1447 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule invert, ignoring: %s", rvalue
);
1457 int config_parse_routing_policy_rule_family(
1459 const char *filename
,
1461 const char *section
,
1462 unsigned section_line
,
1469 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1470 Network
*network
= userdata
;
1480 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1484 a
= routing_policy_rule_address_family_from_string(rvalue
);
1486 log_syntax(unit
, LOG_WARNING
, filename
, line
, a
,
1487 "Invalid address family '%s', ignoring.", rvalue
);
1491 n
->address_family
= a
;
1497 int config_parse_routing_policy_rule_uid_range(
1499 const char *filename
,
1501 const char *section
,
1502 unsigned section_line
,
1509 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1510 Network
*network
= userdata
;
1520 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1524 r
= get_user_creds(&rvalue
, &start
, NULL
, NULL
, NULL
, 0);
1528 r
= parse_uid_range(rvalue
, &start
, &end
);
1530 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1531 "Invalid uid or uid range '%s', ignoring: %m", rvalue
);
1536 n
->uid_range
.start
= start
;
1537 n
->uid_range
.end
= end
;
1543 int config_parse_routing_policy_rule_suppress_prefixlen(
1545 const char *filename
,
1547 const char *section
,
1548 unsigned section_line
,
1555 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1556 Network
*network
= userdata
;
1565 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1569 r
= parse_ip_prefix_length(rvalue
, &n
->suppress_prefixlen
);
1571 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Prefix length outside of valid range 0-128, ignoring: %s", rvalue
);
1575 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", rvalue
);
1583 int config_parse_routing_policy_rule_type(
1585 const char *filename
,
1587 const char *section
,
1588 unsigned section_line
,
1595 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1596 Network
*network
= userdata
;
1605 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1609 t
= fr_act_type_from_string(rvalue
);
1611 log_syntax(unit
, LOG_WARNING
, filename
, line
, t
,
1612 "Could not parse FIB rule type \"%s\", ignoring assignment: %m", rvalue
);
1616 n
->type
= (uint8_t) t
;
1622 static int routing_policy_rule_section_verify(RoutingPolicyRule
*rule
) {
1623 if (section_is_invalid(rule
->section
))
1626 if ((rule
->family
== AF_INET
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) ||
1627 (rule
->family
== AF_INET6
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)))
1628 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1629 "%s: address family specified by Family= conflicts with the address "
1630 "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
1631 rule
->section
->filename
, rule
->section
->line
);
1633 if (rule
->family
== AF_UNSPEC
) {
1634 if (IN_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
, ADDRESS_FAMILY_NO
))
1635 rule
->family
= AF_INET
;
1636 else if (rule
->address_family
== ADDRESS_FAMILY_IPV6
)
1637 rule
->family
= AF_INET6
;
1638 /* rule->family can be AF_UNSPEC only when Family=both. */
1641 /* Currently, [RoutingPolicyRule] does not have a setting to set FRA_L3MDEV flag. Please also
1642 * update routing_policy_rule_is_created_by_kernel() when a new setting which sets the flag is
1643 * added in the future. */
1644 if (rule
->l3mdev
> 0)
1645 assert_not_reached("FRA_L3MDEV flag should not be configured.");
1650 void network_drop_invalid_routing_policy_rules(Network
*network
) {
1651 RoutingPolicyRule
*rule
;
1655 HASHMAP_FOREACH(rule
, network
->rules_by_section
)
1656 if (routing_policy_rule_section_verify(rule
) < 0)
1657 routing_policy_rule_free(rule
);