1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <linux/fib_rules.h>
7 #include "alloc-util.h"
8 #include "conf-parser.h"
10 #include "format-util.h"
11 #include "ip-protocol-list.h"
12 #include "networkd-routing-policy-rule.h"
13 #include "netlink-util.h"
14 #include "networkd-manager.h"
15 #include "networkd-util.h"
16 #include "parse-util.h"
17 #include "socket-util.h"
18 #include "string-util.h"
20 #include "user-util.h"
22 int routing_policy_rule_new(RoutingPolicyRule
**ret
) {
23 RoutingPolicyRule
*rule
;
25 rule
= new(RoutingPolicyRule
, 1);
29 *rule
= (RoutingPolicyRule
) {
30 .table
= RT_TABLE_MAIN
,
31 .uid_range
.start
= UID_INVALID
,
32 .uid_range
.end
= UID_INVALID
,
33 .suppress_prefixlen
= -1,
40 void routing_policy_rule_free(RoutingPolicyRule
*rule
) {
46 LIST_REMOVE(rules
, rule
->network
->rules
, rule
);
47 assert(rule
->network
->n_rules
> 0);
48 rule
->network
->n_rules
--;
51 hashmap_remove(rule
->network
->rules_by_section
, rule
->section
);
55 if (set_get(rule
->manager
->rules
, rule
) == rule
)
56 set_remove(rule
->manager
->rules
, rule
);
57 if (set_get(rule
->manager
->rules_foreign
, rule
) == rule
)
58 set_remove(rule
->manager
->rules_foreign
, rule
);
61 network_config_section_free(rule
->section
);
67 static int routing_policy_rule_copy(RoutingPolicyRule
*dest
, RoutingPolicyRule
*src
) {
68 _cleanup_free_
char *iif
= NULL
, *oif
= NULL
;
74 iif
= strdup(src
->iif
);
80 oif
= strdup(src
->oif
);
85 dest
->family
= src
->family
;
86 dest
->from
= src
->from
;
87 dest
->from_prefixlen
= src
->from_prefixlen
;
89 dest
->to_prefixlen
= src
->to_prefixlen
;
90 dest
->invert_rule
= src
->invert_rule
;
92 dest
->fwmark
= src
->fwmark
;
93 dest
->fwmask
= src
->fwmask
;
94 dest
->priority
= src
->priority
;
95 dest
->table
= src
->table
;
96 dest
->iif
= TAKE_PTR(iif
);
97 dest
->oif
= TAKE_PTR(oif
);
98 dest
->protocol
= src
->protocol
;
99 dest
->sport
= src
->sport
;
100 dest
->dport
= src
->dport
;
101 dest
->uid_range
= src
->uid_range
;
102 dest
->suppress_prefixlen
= src
->suppress_prefixlen
;
107 static void routing_policy_rule_hash_func(const RoutingPolicyRule
*rule
, struct siphash
*state
) {
110 siphash24_compress(&rule
->family
, sizeof(rule
->family
), state
);
112 switch (rule
->family
) {
115 siphash24_compress(&rule
->from
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
116 siphash24_compress(&rule
->from_prefixlen
, sizeof(rule
->from_prefixlen
), state
);
118 siphash24_compress(&rule
->to
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
119 siphash24_compress(&rule
->to_prefixlen
, sizeof(rule
->to_prefixlen
), state
);
121 siphash24_compress_boolean(rule
->invert_rule
, state
);
123 siphash24_compress(&rule
->tos
, sizeof(rule
->tos
), state
);
124 siphash24_compress(&rule
->fwmark
, sizeof(rule
->fwmark
), state
);
125 siphash24_compress(&rule
->fwmask
, sizeof(rule
->fwmask
), state
);
126 siphash24_compress(&rule
->priority
, sizeof(rule
->priority
), state
);
127 siphash24_compress(&rule
->table
, sizeof(rule
->table
), state
);
128 siphash24_compress(&rule
->suppress_prefixlen
, sizeof(rule
->suppress_prefixlen
), state
);
130 siphash24_compress(&rule
->protocol
, sizeof(rule
->protocol
), state
);
131 siphash24_compress(&rule
->sport
, sizeof(rule
->sport
), state
);
132 siphash24_compress(&rule
->dport
, sizeof(rule
->dport
), state
);
133 siphash24_compress(&rule
->uid_range
, sizeof(rule
->uid_range
), state
);
136 siphash24_compress(rule
->iif
, strlen(rule
->iif
), state
);
139 siphash24_compress(rule
->oif
, strlen(rule
->oif
), state
);
143 /* treat any other address family as AF_UNSPEC */
148 static int routing_policy_rule_compare_func(const RoutingPolicyRule
*a
, const RoutingPolicyRule
*b
) {
151 r
= CMP(a
->family
, b
->family
);
158 r
= CMP(a
->from_prefixlen
, b
->from_prefixlen
);
162 r
= memcmp(&a
->from
, &b
->from
, FAMILY_ADDRESS_SIZE(a
->family
));
166 r
= CMP(a
->to_prefixlen
, b
->to_prefixlen
);
170 r
= memcmp(&a
->to
, &b
->to
, FAMILY_ADDRESS_SIZE(a
->family
));
174 r
= CMP(a
->invert_rule
, b
->invert_rule
);
178 r
= CMP(a
->tos
, b
->tos
);
182 r
= CMP(a
->fwmark
, b
->fwmark
);
186 r
= CMP(a
->fwmask
, b
->fwmask
);
190 r
= CMP(a
->priority
, b
->priority
);
194 r
= CMP(a
->table
, b
->table
);
198 r
= CMP(a
->suppress_prefixlen
, b
->suppress_prefixlen
);
202 r
= CMP(a
->protocol
, b
->protocol
);
206 r
= memcmp(&a
->sport
, &b
->sport
, sizeof(a
->sport
));
210 r
= memcmp(&a
->dport
, &b
->dport
, sizeof(a
->dport
));
214 r
= memcmp(&a
->uid_range
, &b
->uid_range
, sizeof(a
->uid_range
));
218 r
= strcmp_ptr(a
->iif
, b
->iif
);
222 r
= strcmp_ptr(a
->oif
, b
->oif
);
228 /* treat any other address family as AF_UNSPEC */
233 DEFINE_PRIVATE_HASH_OPS(routing_policy_rule_hash_ops
, RoutingPolicyRule
, routing_policy_rule_hash_func
, routing_policy_rule_compare_func
);
235 int routing_policy_rule_get(Manager
*m
, RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
237 RoutingPolicyRule
*existing
;
241 existing
= set_get(m
->rules
, rule
);
248 existing
= set_get(m
->rules_foreign
, rule
);
258 int routing_policy_rule_make_local(Manager
*m
, RoutingPolicyRule
*rule
) {
263 if (set_contains(m
->rules_foreign
, rule
)) {
264 set_remove(m
->rules_foreign
, rule
);
266 r
= set_ensure_put(&m
->rules
, &routing_policy_rule_hash_ops
, rule
);
270 routing_policy_rule_free(rule
);
276 static int routing_policy_rule_add_internal(Manager
*m
, Set
**rules
, RoutingPolicyRule
*in
, RoutingPolicyRule
**ret
) {
277 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
284 r
= routing_policy_rule_new(&rule
);
290 r
= routing_policy_rule_copy(rule
, in
);
294 r
= set_ensure_put(rules
, &routing_policy_rule_hash_ops
, rule
);
307 static int routing_policy_rule_add(Manager
*m
, RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
308 return routing_policy_rule_add_internal(m
, &m
->rules
, rule
, ret
);
311 int routing_policy_rule_add_foreign(Manager
*m
, RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
312 return routing_policy_rule_add_internal(m
, &m
->rules_foreign
, rule
, ret
);
315 static int routing_policy_rule_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
320 assert(link
->ifname
);
322 link
->routing_policy_rule_remove_messages
--;
324 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
327 r
= sd_netlink_message_get_errno(m
);
329 log_link_message_warning_errno(link
, m
, r
, "Could not drop routing policy rule");
334 int routing_policy_rule_remove(RoutingPolicyRule
*routing_policy_rule
, Link
*link
, link_netlink_message_handler_t callback
) {
335 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
338 assert(routing_policy_rule
);
340 assert(link
->manager
);
341 assert(link
->manager
->rtnl
);
342 assert(link
->ifindex
> 0);
343 assert(IN_SET(routing_policy_rule
->family
, AF_INET
, AF_INET6
));
345 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_DELRULE
, routing_policy_rule
->family
);
347 return log_link_error_errno(link
, r
, "Could not allocate RTM_DELRULE message: %m");
349 if (in_addr_is_null(routing_policy_rule
->family
, &routing_policy_rule
->from
) == 0) {
350 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, routing_policy_rule
->family
, &routing_policy_rule
->from
);
352 return log_link_error_errno(link
, r
, "Could not append FRA_SRC attribute: %m");
354 r
= sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m
, routing_policy_rule
->from_prefixlen
);
356 return log_link_error_errno(link
, r
, "Could not set source prefix length: %m");
359 if (in_addr_is_null(routing_policy_rule
->family
, &routing_policy_rule
->to
) == 0) {
360 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, routing_policy_rule
->family
, &routing_policy_rule
->to
);
362 return log_link_error_errno(link
, r
, "Could not append FRA_DST attribute: %m");
364 r
= sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m
, routing_policy_rule
->to_prefixlen
);
366 return log_link_error_errno(link
, r
, "Could not set destination prefix length: %m");
369 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
,
370 callback
?: routing_policy_rule_remove_handler
,
371 link_netlink_destroy_callback
, link
);
373 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
380 static int routing_policy_rule_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutingPolicyRule
**ret
) {
381 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
382 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
387 assert(!!filename
== (section_line
> 0));
390 r
= network_config_section_new(filename
, section_line
, &n
);
394 rule
= hashmap_get(network
->rules_by_section
, n
);
396 *ret
= TAKE_PTR(rule
);
402 r
= routing_policy_rule_new(&rule
);
406 rule
->network
= network
;
407 LIST_APPEND(rules
, network
->rules
, rule
);
411 rule
->section
= TAKE_PTR(n
);
413 r
= hashmap_ensure_allocated(&network
->rules_by_section
, &network_config_hash_ops
);
417 r
= hashmap_put(network
->rules_by_section
, rule
->section
, rule
);
422 *ret
= TAKE_PTR(rule
);
427 static int routing_policy_rule_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
433 assert(link
->ifname
);
434 assert(link
->routing_policy_rule_messages
> 0);
436 link
->routing_policy_rule_messages
--;
438 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
441 r
= sd_netlink_message_get_errno(m
);
442 if (r
< 0 && r
!= -EEXIST
) {
443 log_link_message_warning_errno(link
, m
, r
, "Could not add routing policy rule");
444 link_enter_failed(link
);
448 if (link
->routing_policy_rule_messages
== 0) {
449 log_link_debug(link
, "Routing policy rule configured");
450 link
->routing_policy_rules_configured
= true;
451 link_check_ready(link
);
457 int routing_policy_rule_configure(RoutingPolicyRule
*rule
, Link
*link
, link_netlink_message_handler_t callback
) {
458 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
463 assert(link
->ifindex
> 0);
464 assert(link
->manager
);
465 assert(link
->manager
->rtnl
);
468 _cleanup_free_
char *from
= NULL
, *to
= NULL
;
470 (void) in_addr_to_string(rule
->family
, &rule
->from
, &from
);
471 (void) in_addr_to_string(rule
->family
, &rule
->to
, &to
);
474 "Configuring routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u",
475 from
, rule
->from_prefixlen
, to
, rule
->to_prefixlen
, strna(rule
->iif
), strna(rule
->oif
), rule
->table
);
478 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_NEWRULE
, rule
->family
);
480 return log_link_error_errno(link
, r
, "Could not allocate RTM_NEWRULE message: %m");
482 if (in_addr_is_null(rule
->family
, &rule
->from
) == 0) {
483 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, rule
->family
, &rule
->from
);
485 return log_link_error_errno(link
, r
, "Could not append FRA_SRC attribute: %m");
487 r
= sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m
, rule
->from_prefixlen
);
489 return log_link_error_errno(link
, r
, "Could not set source prefix length: %m");
492 if (in_addr_is_null(rule
->family
, &rule
->to
) == 0) {
493 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, rule
->family
, &rule
->to
);
495 return log_link_error_errno(link
, r
, "Could not append FRA_DST attribute: %m");
497 r
= sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m
, rule
->to_prefixlen
);
499 return log_link_error_errno(link
, r
, "Could not set destination prefix length: %m");
502 r
= sd_netlink_message_append_u32(m
, FRA_PRIORITY
, rule
->priority
);
504 return log_link_error_errno(link
, r
, "Could not append FRA_PRIORITY attribute: %m");
507 r
= sd_rtnl_message_routing_policy_rule_set_tos(m
, rule
->tos
);
509 return log_link_error_errno(link
, r
, "Could not set ip rule tos: %m");
512 if (rule
->table
< 256) {
513 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, rule
->table
);
515 return log_link_error_errno(link
, r
, "Could not set ip rule table: %m");
517 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
519 return log_link_error_errno(link
, r
, "Could not set ip rule table: %m");
521 r
= sd_netlink_message_append_u32(m
, FRA_TABLE
, rule
->table
);
523 return log_link_error_errno(link
, r
, "Could not append FRA_TABLE attribute: %m");
526 if (rule
->fwmark
> 0) {
527 r
= sd_netlink_message_append_u32(m
, FRA_FWMARK
, rule
->fwmark
);
529 return log_link_error_errno(link
, r
, "Could not append FRA_FWMARK attribute: %m");
532 if (rule
->fwmask
> 0) {
533 r
= sd_netlink_message_append_u32(m
, FRA_FWMASK
, rule
->fwmask
);
535 return log_link_error_errno(link
, r
, "Could not append FRA_FWMASK attribute: %m");
539 r
= sd_netlink_message_append_string(m
, FRA_IFNAME
, rule
->iif
);
541 return log_link_error_errno(link
, r
, "Could not append FRA_IFNAME attribute: %m");
545 r
= sd_netlink_message_append_string(m
, FRA_OIFNAME
, rule
->oif
);
547 return log_link_error_errno(link
, r
, "Could not append FRA_OIFNAME attribute: %m");
550 r
= sd_netlink_message_append_u8(m
, FRA_IP_PROTO
, rule
->protocol
);
552 return log_link_error_errno(link
, r
, "Could not append FRA_IP_PROTO attribute: %m");
554 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
555 r
= sd_netlink_message_append_data(m
, FRA_SPORT_RANGE
, &rule
->sport
, sizeof(rule
->sport
));
557 return log_link_error_errno(link
, r
, "Could not append FRA_SPORT_RANGE attribute: %m");
560 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
561 r
= sd_netlink_message_append_data(m
, FRA_DPORT_RANGE
, &rule
->dport
, sizeof(rule
->dport
));
563 return log_link_error_errno(link
, r
, "Could not append FRA_DPORT_RANGE attribute: %m");
566 if (rule
->uid_range
.start
!= UID_INVALID
&& rule
->uid_range
.end
!= UID_INVALID
) {
567 r
= sd_netlink_message_append_data(m
, FRA_UID_RANGE
, &rule
->uid_range
, sizeof(rule
->uid_range
));
569 return log_link_error_errno(link
, r
, "Could not append FRA_UID_RANGE attribute: %m");
572 if (rule
->invert_rule
) {
573 r
= sd_rtnl_message_routing_policy_rule_set_flags(m
, FIB_RULE_INVERT
);
575 return log_link_error_errno(link
, r
, "Could not append FIB_RULE_INVERT attribute: %m");
578 if (rule
->suppress_prefixlen
>= 0) {
579 r
= sd_netlink_message_append_u32(m
, FRA_SUPPRESS_PREFIXLEN
, (uint32_t) rule
->suppress_prefixlen
);
581 return log_link_error_errno(link
, r
, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m");
586 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
,
587 callback
?: routing_policy_rule_handler
,
588 link_netlink_destroy_callback
, link
);
590 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
594 r
= routing_policy_rule_add(link
->manager
, rule
, NULL
);
596 return log_link_error_errno(link
, r
, "Could not add rule: %m");
601 int routing_policy_rule_section_verify(RoutingPolicyRule
*rule
) {
604 if (section_is_invalid(rule
->section
))
607 if ((rule
->family
== AF_INET
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) ||
608 (rule
->family
== AF_INET6
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)))
609 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
610 "%s: address family specified by Family= conflicts with the address "
611 "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
612 rule
->section
->filename
, rule
->section
->line
);
614 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
| ADDRESS_FAMILY_IPV6
)) {
615 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule6
= NULL
;
617 assert(rule
->family
== AF_UNSPEC
);
619 /* When Family=both, we need to copy the section, AF_INET and AF_INET6. */
621 r
= routing_policy_rule_new_static(rule
->network
, NULL
, 0, &rule6
);
625 r
= routing_policy_rule_copy(rule6
, rule
);
629 rule
->family
= AF_INET
;
630 rule6
->family
= AF_INET6
;
635 if (rule
->family
== AF_UNSPEC
) {
636 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
))
637 rule
->family
= AF_INET6
;
639 rule
->family
= AF_INET
;
645 static int parse_fwmark_fwmask(const char *s
, uint32_t *fwmark
, uint32_t *fwmask
) {
646 _cleanup_free_
char *f
= NULL
;
660 r
= safe_atou32(f
, fwmark
);
662 return log_error_errno(r
, "Failed to parse RPDB rule firewall mark, ignoring: %s", f
);
665 r
= safe_atou32(p
, fwmask
);
667 return log_error_errno(r
, "Failed to parse RPDB rule mask, ignoring: %s", f
);
673 int config_parse_routing_policy_rule_tos(
675 const char *filename
,
678 unsigned section_line
,
685 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
686 Network
*network
= userdata
;
695 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
699 r
= safe_atou8(rvalue
, &n
->tos
);
701 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule tos, ignoring: %s", rvalue
);
710 int config_parse_routing_policy_rule_priority(
712 const char *filename
,
715 unsigned section_line
,
722 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
723 Network
*network
= userdata
;
732 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
736 r
= safe_atou32(rvalue
, &n
->priority
);
738 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule priority, ignoring: %s", rvalue
);
747 int config_parse_routing_policy_rule_table(
749 const char *filename
,
752 unsigned section_line
,
759 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
760 Network
*network
= userdata
;
769 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
773 r
= safe_atou32(rvalue
, &n
->table
);
775 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule table, ignoring: %s", rvalue
);
784 int config_parse_routing_policy_rule_fwmark_mask(
786 const char *filename
,
789 unsigned section_line
,
796 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
797 Network
*network
= userdata
;
806 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
810 r
= parse_fwmark_fwmask(rvalue
, &n
->fwmark
, &n
->fwmask
);
812 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue
);
821 int config_parse_routing_policy_rule_prefix(
823 const char *filename
,
826 unsigned section_line
,
833 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
834 Network
*network
= userdata
;
835 union in_addr_union
*buffer
;
845 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
849 if (streq(lvalue
, "To")) {
851 prefixlen
= &n
->to_prefixlen
;
854 prefixlen
= &n
->from_prefixlen
;
857 if (n
->family
== AF_UNSPEC
)
858 r
= in_addr_prefix_from_string_auto(rvalue
, &n
->family
, buffer
, prefixlen
);
860 r
= in_addr_prefix_from_string(rvalue
, n
->family
, buffer
, prefixlen
);
862 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue
);
871 int config_parse_routing_policy_rule_device(
873 const char *filename
,
876 unsigned section_line
,
883 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
884 Network
*network
= userdata
;
893 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
897 if (!ifname_valid(rvalue
)) {
898 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse '%s' interface name, ignoring: %s", lvalue
, rvalue
);
902 if (streq(lvalue
, "IncomingInterface")) {
903 r
= free_and_strdup(&n
->iif
, rvalue
);
907 r
= free_and_strdup(&n
->oif
, rvalue
);
917 int config_parse_routing_policy_rule_port_range(
919 const char *filename
,
922 unsigned section_line
,
928 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
929 Network
*network
= userdata
;
939 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
943 r
= parse_ip_port_range(rvalue
, &low
, &high
);
945 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse routing policy rule port range '%s'", rvalue
);
949 if (streq(lvalue
, "SourcePort")) {
950 n
->sport
.start
= low
;
953 n
->dport
.start
= low
;
962 int config_parse_routing_policy_rule_ip_protocol(
964 const char *filename
,
967 unsigned section_line
,
974 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
975 Network
*network
= userdata
;
984 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
988 r
= parse_ip_protocol(rvalue
);
990 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue
);
1001 int config_parse_routing_policy_rule_invert(
1003 const char *filename
,
1005 const char *section
,
1006 unsigned section_line
,
1013 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1014 Network
*network
= userdata
;
1023 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1027 r
= parse_boolean(rvalue
);
1029 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule invert, ignoring: %s", rvalue
);
1040 int config_parse_routing_policy_rule_family(
1042 const char *filename
,
1044 const char *section
,
1045 unsigned section_line
,
1052 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1053 Network
*network
= userdata
;
1063 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1067 a
= routing_policy_rule_address_family_from_string(rvalue
);
1069 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1070 "Invalid address family '%s', ignoring.", rvalue
);
1074 n
->address_family
= a
;
1080 int config_parse_routing_policy_rule_uid_range(
1082 const char *filename
,
1084 const char *section
,
1085 unsigned section_line
,
1092 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1093 Network
*network
= userdata
;
1103 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1107 r
= get_user_creds(&rvalue
, &start
, NULL
, NULL
, NULL
, 0);
1111 r
= parse_uid_range(rvalue
, &start
, &end
);
1113 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
1114 "Invalid uid or uid range '%s', ignoring: %m", rvalue
);
1119 n
->uid_range
.start
= start
;
1120 n
->uid_range
.end
= end
;
1126 int config_parse_routing_policy_rule_suppress_prefixlen(
1128 const char *filename
,
1130 const char *section
,
1131 unsigned section_line
,
1138 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1139 Network
*network
= userdata
;
1148 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1152 r
= parse_ip_prefix_length(rvalue
, &n
->suppress_prefixlen
);
1154 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Prefix length outside of valid range 0-128, ignoring: %s", rvalue
);
1158 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", rvalue
);
1167 static int routing_policy_rule_read_full_file(const char *state_file
, char **ret
) {
1168 _cleanup_free_
char *s
= NULL
;
1174 r
= read_full_file(state_file
, &s
, &size
);
1187 int routing_policy_serialize_rules(Set
*rules
, FILE *f
) {
1188 RoutingPolicyRule
*rule
= NULL
;
1194 SET_FOREACH(rule
, rules
, i
) {
1195 _cleanup_free_
char *from_str
= NULL
, *to_str
= NULL
;
1197 const char *family_str
;
1201 if (!in_addr_is_null(rule
->family
, &rule
->from
)) {
1202 r
= in_addr_to_string(rule
->family
, &rule
->from
, &from_str
);
1206 fprintf(f
, "from=%s/%hhu",
1207 from_str
, rule
->from_prefixlen
);
1211 if (!in_addr_is_null(rule
->family
, &rule
->to
)) {
1212 r
= in_addr_to_string(rule
->family
, &rule
->to
, &to_str
);
1216 fprintf(f
, "%sto=%s/%hhu",
1218 to_str
, rule
->to_prefixlen
);
1222 family_str
= af_to_name(rule
->family
);
1224 fprintf(f
, "%sfamily=%s",
1228 if (rule
->tos
!= 0) {
1229 fprintf(f
, "%stos=%hhu",
1235 fprintf(f
, "%spriority=%"PRIu32
,
1239 if (rule
->fwmark
!= 0) {
1240 fprintf(f
, "%sfwmark=%"PRIu32
"/%"PRIu32
,
1242 rule
->fwmark
, rule
->fwmask
);
1247 fprintf(f
, "%siif=%s",
1254 fprintf(f
, "%soif=%s",
1260 if (rule
->protocol
!= 0) {
1261 fprintf(f
, "%sprotocol=%hhu",
1267 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
1268 fprintf(f
, "%ssourcesport=%"PRIu16
"-%"PRIu16
,
1270 rule
->sport
.start
, rule
->sport
.end
);
1274 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
1275 fprintf(f
, "%sdestinationport=%"PRIu16
"-%"PRIu16
,
1277 rule
->dport
.start
, rule
->dport
.end
);
1281 if (rule
->uid_range
.start
!= UID_INVALID
&& rule
->uid_range
.end
!= UID_INVALID
) {
1282 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
1283 fprintf(f
, "%suidrange="UID_FMT
"-"UID_FMT
,
1285 rule
->uid_range
.start
, rule
->uid_range
.end
);
1289 if (rule
->suppress_prefixlen
>= 0) {
1290 fprintf(f
, "%ssuppress_prefixlen=%d",
1292 rule
->suppress_prefixlen
);
1296 fprintf(f
, "%stable=%"PRIu32
"\n",
1304 int routing_policy_load_rules(const char *state_file
, Set
**rules
) {
1305 _cleanup_strv_free_
char **l
= NULL
;
1306 _cleanup_free_
char *data
= NULL
;
1307 uint16_t low
= 0, high
= 0;
1315 r
= routing_policy_rule_read_full_file(state_file
, &data
);
1319 l
= strv_split_newlines(data
);
1323 STRV_FOREACH(i
, l
) {
1324 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
1326 p
= startswith(*i
, "RULE=");
1330 r
= routing_policy_rule_new(&rule
);
1335 _cleanup_free_
char *word
= NULL
, *a
= NULL
, *b
= NULL
;
1337 r
= extract_first_word(&p
, &word
, NULL
, 0);
1343 r
= split_pair(word
, "=", &a
, &b
);
1347 if (STR_IN_SET(a
, "from", "to")) {
1348 union in_addr_union
*buffer
;
1351 if (streq(a
, "to")) {
1353 prefixlen
= &rule
->to_prefixlen
;
1355 buffer
= &rule
->from
;
1356 prefixlen
= &rule
->from_prefixlen
;
1359 r
= in_addr_prefix_from_string_auto(b
, &rule
->family
, buffer
, prefixlen
);
1361 log_error_errno(r
, "RPDB rule prefix is invalid, ignoring assignment: %s", b
);
1365 } else if (streq(a
, "family")) {
1366 r
= af_from_name(b
);
1368 log_error_errno(r
, "Failed to parse RPDB rule family, ignoring: %s", b
);
1372 } else if (streq(a
, "tos")) {
1373 r
= safe_atou8(b
, &rule
->tos
);
1375 log_error_errno(r
, "Failed to parse RPDB rule tos, ignoring: %s", b
);
1378 } else if (streq(a
, "table")) {
1379 r
= safe_atou32(b
, &rule
->table
);
1381 log_error_errno(r
, "Failed to parse RPDB rule table, ignoring: %s", b
);
1384 } else if (streq(a
, "priority")) {
1385 r
= safe_atou32(b
, &rule
->priority
);
1387 log_error_errno(r
, "Failed to parse RPDB rule priority, ignoring: %s", b
);
1390 } else if (streq(a
, "fwmark")) {
1391 r
= parse_fwmark_fwmask(b
, &rule
->fwmark
, &rule
->fwmask
);
1393 log_error_errno(r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a
);
1396 } else if (streq(a
, "iif")) {
1397 if (free_and_strdup(&rule
->iif
, b
) < 0)
1400 } else if (streq(a
, "oif")) {
1402 if (free_and_strdup(&rule
->oif
, b
) < 0)
1404 } else if (streq(a
, "protocol")) {
1405 r
= safe_atou8(b
, &rule
->protocol
);
1407 log_error_errno(r
, "Failed to parse RPDB rule protocol, ignoring: %s", b
);
1410 } else if (streq(a
, "sourceport")) {
1411 r
= parse_ip_port_range(b
, &low
, &high
);
1413 log_error_errno(r
, "Invalid routing policy rule source port range, ignoring assignment: '%s'", b
);
1417 rule
->sport
.start
= low
;
1418 rule
->sport
.end
= high
;
1419 } else if (streq(a
, "destinationport")) {
1420 r
= parse_ip_port_range(b
, &low
, &high
);
1422 log_error_errno(r
, "Invalid routing policy rule destination port range, ignoring assignment: '%s'", b
);
1426 rule
->dport
.start
= low
;
1427 rule
->dport
.end
= high
;
1428 } else if (streq(a
, "uidrange")) {
1431 r
= parse_uid_range(b
, &lower
, &upper
);
1433 log_error_errno(r
, "Invalid routing policy rule uid range, ignoring assignment: '%s'", b
);
1437 rule
->uid_range
.start
= lower
;
1438 rule
->uid_range
.end
= upper
;
1439 } else if (streq(a
, "suppress_prefixlen")) {
1440 r
= parse_ip_prefix_length(b
, &rule
->suppress_prefixlen
);
1442 log_error_errno(r
, "Prefix length outside of valid range 0-128, ignoring: %s", b
);
1446 log_error_errno(r
, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", b
);
1452 r
= set_ensure_put(rules
, &routing_policy_rule_hash_ops
, rule
);
1454 log_warning_errno(r
, "Failed to add RPDB rule to saved DB, ignoring: %s", p
);
1464 static bool manager_links_have_routing_policy_rule(Manager
*m
, RoutingPolicyRule
*rule
) {
1465 RoutingPolicyRule
*link_rule
;
1472 HASHMAP_FOREACH(link
, m
->links
, i
) {
1476 LIST_FOREACH(rules
, link_rule
, link
->network
->rules
)
1477 if (routing_policy_rule_compare_func(link_rule
, rule
) == 0)
1484 void routing_policy_rule_purge(Manager
*m
, Link
*link
) {
1485 RoutingPolicyRule
*rule
, *existing
;
1492 SET_FOREACH(rule
, m
->rules_saved
, i
) {
1493 existing
= set_get(m
->rules_foreign
, rule
);
1495 continue; /* Saved rule does not exist anymore. */
1497 if (manager_links_have_routing_policy_rule(m
, existing
))
1498 continue; /* Existing links have the saved rule. */
1500 /* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it
1501 * later when it is requested. */
1503 r
= routing_policy_rule_remove(existing
, link
, NULL
);
1505 log_warning_errno(r
, "Could not remove routing policy rules: %m");
1509 link
->routing_policy_rule_remove_messages
++;
1511 assert_se(set_remove(m
->rules_foreign
, existing
) == existing
);
1512 routing_policy_rule_free(existing
);