1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <linux/fib_rules.h>
6 #include "alloc-util.h"
7 #include "conf-parser.h"
9 #include "ip-protocol-list.h"
10 #include "networkd-routing-policy-rule.h"
11 #include "netlink-util.h"
12 #include "networkd-manager.h"
13 #include "parse-util.h"
14 #include "socket-util.h"
15 #include "string-util.h"
18 int routing_policy_rule_new(RoutingPolicyRule
**ret
) {
19 RoutingPolicyRule
*rule
;
21 rule
= new(RoutingPolicyRule
, 1);
25 *rule
= (RoutingPolicyRule
) {
27 .table
= RT_TABLE_MAIN
,
34 void routing_policy_rule_free(RoutingPolicyRule
*rule
) {
40 LIST_REMOVE(rules
, rule
->network
->rules
, rule
);
41 assert(rule
->network
->n_rules
> 0);
42 rule
->network
->n_rules
--;
45 hashmap_remove(rule
->network
->rules_by_section
, rule
->section
);
49 if (set_get(rule
->manager
->rules
, rule
) == rule
)
50 set_remove(rule
->manager
->rules
, rule
);
51 if (set_get(rule
->manager
->rules_foreign
, rule
) == rule
)
52 set_remove(rule
->manager
->rules_foreign
, rule
);
55 network_config_section_free(rule
->section
);
61 static void routing_policy_rule_hash_func(const RoutingPolicyRule
*rule
, struct siphash
*state
) {
64 siphash24_compress(&rule
->family
, sizeof(rule
->family
), state
);
66 switch (rule
->family
) {
70 siphash24_compress(&rule
->from
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
71 siphash24_compress(&rule
->from_prefixlen
, sizeof(rule
->from_prefixlen
), state
);
73 siphash24_compress(&rule
->to
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
74 siphash24_compress(&rule
->to_prefixlen
, sizeof(rule
->to_prefixlen
), state
);
76 siphash24_compress_boolean(rule
->invert_rule
, state
);
78 siphash24_compress(&rule
->tos
, sizeof(rule
->tos
), state
);
79 siphash24_compress(&rule
->fwmark
, sizeof(rule
->fwmark
), state
);
80 siphash24_compress(&rule
->fwmask
, sizeof(rule
->fwmask
), state
);
81 siphash24_compress(&rule
->priority
, sizeof(rule
->priority
), state
);
82 siphash24_compress(&rule
->table
, sizeof(rule
->table
), state
);
84 siphash24_compress(&rule
->protocol
, sizeof(rule
->protocol
), state
);
85 siphash24_compress(&rule
->sport
, sizeof(rule
->sport
), state
);
86 siphash24_compress(&rule
->dport
, sizeof(rule
->dport
), state
);
89 siphash24_compress(rule
->iif
, strlen(rule
->iif
), state
);
92 siphash24_compress(rule
->oif
, strlen(rule
->oif
), state
);
96 /* treat any other address family as AF_UNSPEC */
101 static int routing_policy_rule_compare_func(const RoutingPolicyRule
*a
, const RoutingPolicyRule
*b
) {
104 r
= CMP(a
->family
, b
->family
);
111 r
= CMP(a
->from_prefixlen
, b
->from_prefixlen
);
115 r
= CMP(a
->to_prefixlen
, b
->to_prefixlen
);
119 r
= CMP(a
->invert_rule
, b
->invert_rule
);
123 r
= CMP(a
->tos
, b
->tos
);
127 r
= CMP(a
->fwmark
, b
->fwmark
);
131 r
= CMP(a
->fwmask
, b
->fwmask
);
135 r
= CMP(a
->priority
, b
->priority
);
139 r
= CMP(a
->table
, b
->table
);
143 r
= strcmp_ptr(a
->iif
, b
->iif
);
147 r
= strcmp_ptr(a
->oif
, b
->oif
);
151 r
= CMP(a
->protocol
, b
->protocol
);
155 r
= memcmp(&a
->sport
, &b
->sport
, sizeof(a
->sport
));
159 r
= memcmp(&a
->dport
, &b
->dport
, sizeof(a
->dport
));
163 r
= memcmp(&a
->from
, &b
->from
, FAMILY_ADDRESS_SIZE(a
->family
));
167 return memcmp(&a
->to
, &b
->to
, FAMILY_ADDRESS_SIZE(a
->family
));
170 /* treat any other address family as AF_UNSPEC */
175 DEFINE_PRIVATE_HASH_OPS(routing_policy_rule_hash_ops
, RoutingPolicyRule
, routing_policy_rule_hash_func
, routing_policy_rule_compare_func
);
177 int routing_policy_rule_get(Manager
*m
, RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
179 RoutingPolicyRule
*existing
;
183 existing
= set_get(m
->rules
, rule
);
190 existing
= set_get(m
->rules_foreign
, rule
);
200 int routing_policy_rule_make_local(Manager
*m
, RoutingPolicyRule
*rule
) {
205 if (set_contains(m
->rules_foreign
, rule
)) {
206 set_remove(m
->rules_foreign
, rule
);
208 r
= set_ensure_allocated(&m
->rules
, &routing_policy_rule_hash_ops
);
212 r
= set_put(m
->rules
, rule
);
216 routing_policy_rule_free(rule
);
222 static int routing_policy_rule_add_internal(Manager
*m
, Set
**rules
, RoutingPolicyRule
*in
, RoutingPolicyRule
**ret
) {
223 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
224 _cleanup_free_
char *iif
= NULL
, *oif
= NULL
;
232 iif
= strdup(in
->iif
);
238 oif
= strdup(in
->oif
);
243 r
= routing_policy_rule_new(&rule
);
248 rule
->family
= in
->family
;
249 rule
->from
= in
->from
;
250 rule
->from_prefixlen
= in
->from_prefixlen
;
252 rule
->to_prefixlen
= in
->to_prefixlen
;
253 rule
->invert_rule
= in
->invert_rule
;
255 rule
->fwmark
= in
->fwmark
;
256 rule
->fwmask
= in
->fwmask
;
257 rule
->priority
= in
->priority
;
258 rule
->table
= in
->table
;
259 rule
->iif
= TAKE_PTR(iif
);
260 rule
->oif
= TAKE_PTR(oif
);
261 rule
->protocol
= in
->protocol
;
262 rule
->sport
= in
->sport
;
263 rule
->dport
= in
->dport
;
265 r
= set_ensure_allocated(rules
, &routing_policy_rule_hash_ops
);
269 r
= set_put(*rules
, rule
);
282 static int routing_policy_rule_add(Manager
*m
, RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
283 return routing_policy_rule_add_internal(m
, &m
->rules
, rule
, ret
);
286 int routing_policy_rule_add_foreign(Manager
*m
, RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
287 return routing_policy_rule_add_internal(m
, &m
->rules_foreign
, rule
, ret
);
290 static int routing_policy_rule_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
295 assert(link
->ifname
);
297 link
->routing_policy_rule_remove_messages
--;
299 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
302 r
= sd_netlink_message_get_errno(m
);
304 log_link_warning_errno(link
, r
, "Could not drop routing policy rule: %m");
309 int routing_policy_rule_remove(RoutingPolicyRule
*routing_policy_rule
, Link
*link
, link_netlink_message_handler_t callback
) {
310 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
313 assert(routing_policy_rule
);
315 assert(link
->manager
);
316 assert(link
->manager
->rtnl
);
317 assert(link
->ifindex
> 0);
318 assert(IN_SET(routing_policy_rule
->family
, AF_INET
, AF_INET6
));
320 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_DELRULE
, routing_policy_rule
->family
);
322 return log_error_errno(r
, "Could not allocate RTM_DELRULE message: %m");
324 if (in_addr_is_null(routing_policy_rule
->family
, &routing_policy_rule
->from
) == 0) {
325 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, routing_policy_rule
->family
, &routing_policy_rule
->from
);
327 return log_error_errno(r
, "Could not append FRA_SRC attribute: %m");
329 r
= sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m
, routing_policy_rule
->from_prefixlen
);
331 return log_error_errno(r
, "Could not set source prefix length: %m");
334 if (in_addr_is_null(routing_policy_rule
->family
, &routing_policy_rule
->to
) == 0) {
335 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, routing_policy_rule
->family
, &routing_policy_rule
->to
);
337 return log_error_errno(r
, "Could not append FRA_DST attribute: %m");
339 r
= sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m
, routing_policy_rule
->to_prefixlen
);
341 return log_error_errno(r
, "Could not set destination prefix length: %m");
344 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
,
345 callback
?: routing_policy_rule_remove_handler
,
346 link_netlink_destroy_callback
, link
);
348 return log_error_errno(r
, "Could not send rtnetlink message: %m");
355 static int routing_policy_rule_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutingPolicyRule
**ret
) {
356 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
357 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
362 assert(!!filename
== (section_line
> 0));
365 r
= network_config_section_new(filename
, section_line
, &n
);
369 rule
= hashmap_get(network
->rules_by_section
, n
);
371 *ret
= TAKE_PTR(rule
);
377 r
= routing_policy_rule_new(&rule
);
381 rule
->network
= network
;
382 LIST_APPEND(rules
, network
->rules
, rule
);
386 rule
->section
= TAKE_PTR(n
);
388 r
= hashmap_ensure_allocated(&network
->rules_by_section
, &network_config_hash_ops
);
392 r
= hashmap_put(network
->rules_by_section
, rule
->section
, rule
);
397 *ret
= TAKE_PTR(rule
);
402 static int routing_policy_rule_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
408 assert(link
->ifname
);
409 assert(link
->routing_policy_rule_messages
> 0);
411 link
->routing_policy_rule_messages
--;
413 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
416 r
= sd_netlink_message_get_errno(m
);
417 if (r
< 0 && r
!= -EEXIST
) {
418 log_link_warning_errno(link
, r
, "Could not add routing policy rule: %m");
419 link_enter_failed(link
);
423 if (link
->routing_policy_rule_messages
== 0) {
424 log_link_debug(link
, "Routing policy rule configured");
425 link
->routing_policy_rules_configured
= true;
426 link_check_ready(link
);
432 int routing_policy_rule_configure(RoutingPolicyRule
*rule
, Link
*link
, link_netlink_message_handler_t callback
) {
433 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
438 assert(link
->ifindex
> 0);
439 assert(link
->manager
);
440 assert(link
->manager
->rtnl
);
442 if (rule
->family
== AF_INET6
&& link_sysctl_ipv6_enabled(link
) == 0) {
443 log_link_warning(link
, "An IPv6 routing policy rule is requested, but IPv6 is disabled by sysctl, ignoring.");
447 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_NEWRULE
, rule
->family
);
449 return log_error_errno(r
, "Could not allocate RTM_NEWRULE message: %m");
451 if (in_addr_is_null(rule
->family
, &rule
->from
) == 0) {
452 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, rule
->family
, &rule
->from
);
454 return log_error_errno(r
, "Could not append FRA_SRC attribute: %m");
456 r
= sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m
, rule
->from_prefixlen
);
458 return log_error_errno(r
, "Could not set source prefix length: %m");
461 if (in_addr_is_null(rule
->family
, &rule
->to
) == 0) {
462 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, rule
->family
, &rule
->to
);
464 return log_error_errno(r
, "Could not append FRA_DST attribute: %m");
466 r
= sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m
, rule
->to_prefixlen
);
468 return log_error_errno(r
, "Could not set destination prefix length: %m");
471 r
= sd_netlink_message_append_u32(m
, FRA_PRIORITY
, rule
->priority
);
473 return log_error_errno(r
, "Could not append FRA_PRIORITY attribute: %m");
476 r
= sd_rtnl_message_routing_policy_rule_set_tos(m
, rule
->tos
);
478 return log_error_errno(r
, "Could not set ip rule tos: %m");
481 if (rule
->table
< 256) {
482 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, rule
->table
);
484 return log_error_errno(r
, "Could not set ip rule table: %m");
486 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
488 return log_error_errno(r
, "Could not set ip rule table: %m");
490 r
= sd_netlink_message_append_u32(m
, FRA_TABLE
, rule
->table
);
492 return log_error_errno(r
, "Could not append FRA_TABLE attribute: %m");
495 if (rule
->fwmark
> 0) {
496 r
= sd_netlink_message_append_u32(m
, FRA_FWMARK
, rule
->fwmark
);
498 return log_error_errno(r
, "Could not append FRA_FWMARK attribute: %m");
501 if (rule
->fwmask
> 0) {
502 r
= sd_netlink_message_append_u32(m
, FRA_FWMASK
, rule
->fwmask
);
504 return log_error_errno(r
, "Could not append FRA_FWMASK attribute: %m");
508 r
= sd_netlink_message_append_string(m
, FRA_IFNAME
, rule
->iif
);
510 return log_error_errno(r
, "Could not append FRA_IFNAME attribute: %m");
514 r
= sd_netlink_message_append_string(m
, FRA_OIFNAME
, rule
->oif
);
516 return log_error_errno(r
, "Could not append FRA_OIFNAME attribute: %m");
519 r
= sd_netlink_message_append_u8(m
, FRA_IP_PROTO
, rule
->protocol
);
521 return log_error_errno(r
, "Could not append FRA_IP_PROTO attribute: %m");
523 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
524 r
= sd_netlink_message_append_data(m
, FRA_SPORT_RANGE
, &rule
->sport
, sizeof(rule
->sport
));
526 return log_error_errno(r
, "Could not append FRA_SPORT_RANGE attribute: %m");
529 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
530 r
= sd_netlink_message_append_data(m
, FRA_DPORT_RANGE
, &rule
->dport
, sizeof(rule
->dport
));
532 return log_error_errno(r
, "Could not append FRA_DPORT_RANGE attribute: %m");
535 if (rule
->invert_rule
) {
536 r
= sd_rtnl_message_routing_policy_rule_set_flags(m
, FIB_RULE_INVERT
);
538 return log_error_errno(r
, "Could not append FIB_RULE_INVERT attribute: %m");
543 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
,
544 callback
?: routing_policy_rule_handler
,
545 link_netlink_destroy_callback
, link
);
547 return log_error_errno(r
, "Could not send rtnetlink message: %m");
551 r
= routing_policy_rule_add(link
->manager
, rule
, NULL
);
553 return log_error_errno(r
, "Could not add rule: %m");
558 static int parse_fwmark_fwmask(const char *s
, uint32_t *fwmark
, uint32_t *fwmask
) {
559 _cleanup_free_
char *f
= NULL
;
573 r
= safe_atou32(f
, fwmark
);
575 return log_error_errno(r
, "Failed to parse RPDB rule firewall mark, ignoring: %s", f
);
578 r
= safe_atou32(p
, fwmask
);
580 return log_error_errno(r
, "Failed to parse RPDB rule mask, ignoring: %s", f
);
586 int config_parse_routing_policy_rule_tos(
588 const char *filename
,
591 unsigned section_line
,
598 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
599 Network
*network
= userdata
;
608 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
612 r
= safe_atou8(rvalue
, &n
->tos
);
614 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule tos, ignoring: %s", rvalue
);
623 int config_parse_routing_policy_rule_priority(
625 const char *filename
,
628 unsigned section_line
,
635 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
636 Network
*network
= userdata
;
645 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
649 r
= safe_atou32(rvalue
, &n
->priority
);
651 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule priority, ignoring: %s", rvalue
);
660 int config_parse_routing_policy_rule_table(
662 const char *filename
,
665 unsigned section_line
,
672 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
673 Network
*network
= userdata
;
682 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
686 r
= safe_atou32(rvalue
, &n
->table
);
688 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule table, ignoring: %s", rvalue
);
697 int config_parse_routing_policy_rule_fwmark_mask(
699 const char *filename
,
702 unsigned section_line
,
709 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
710 Network
*network
= userdata
;
719 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
723 r
= parse_fwmark_fwmask(rvalue
, &n
->fwmark
, &n
->fwmask
);
725 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue
);
734 int config_parse_routing_policy_rule_prefix(
736 const char *filename
,
739 unsigned section_line
,
746 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
747 Network
*network
= userdata
;
748 union in_addr_union
*buffer
;
758 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
762 if (streq(lvalue
, "To")) {
764 prefixlen
= &n
->to_prefixlen
;
767 prefixlen
= &n
->from_prefixlen
;
770 r
= in_addr_prefix_from_string_auto(rvalue
, &n
->family
, buffer
, prefixlen
);
772 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue
);
781 int config_parse_routing_policy_rule_device(
783 const char *filename
,
786 unsigned section_line
,
793 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
794 Network
*network
= userdata
;
803 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
807 if (!ifname_valid(rvalue
)) {
808 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse '%s' interface name, ignoring: %s", lvalue
, rvalue
);
812 if (streq(lvalue
, "IncomingInterface")) {
813 r
= free_and_strdup(&n
->iif
, rvalue
);
817 r
= free_and_strdup(&n
->oif
, rvalue
);
827 int config_parse_routing_policy_rule_port_range(
829 const char *filename
,
832 unsigned section_line
,
838 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
839 Network
*network
= userdata
;
849 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
853 r
= parse_ip_port_range(rvalue
, &low
, &high
);
855 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse routing policy rule port range '%s'", rvalue
);
859 if (streq(lvalue
, "SourcePort")) {
860 n
->sport
.start
= low
;
863 n
->dport
.start
= low
;
872 int config_parse_routing_policy_rule_ip_protocol(
874 const char *filename
,
877 unsigned section_line
,
884 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
885 Network
*network
= userdata
;
894 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
898 r
= parse_ip_protocol(rvalue
);
900 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue
);
911 int config_parse_routing_policy_rule_invert(
913 const char *filename
,
916 unsigned section_line
,
923 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
924 Network
*network
= userdata
;
933 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
937 r
= parse_boolean(rvalue
);
939 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule invert, ignoring: %s", rvalue
);
950 static int routing_policy_rule_read_full_file(const char *state_file
, char **ret
) {
951 _cleanup_free_
char *s
= NULL
;
957 r
= read_full_file(state_file
, &s
, &size
);
970 int routing_policy_serialize_rules(Set
*rules
, FILE *f
) {
971 RoutingPolicyRule
*rule
= NULL
;
977 SET_FOREACH(rule
, rules
, i
) {
978 _cleanup_free_
char *from_str
= NULL
, *to_str
= NULL
;
983 if (!in_addr_is_null(rule
->family
, &rule
->from
)) {
984 r
= in_addr_to_string(rule
->family
, &rule
->from
, &from_str
);
988 fprintf(f
, "from=%s/%hhu",
989 from_str
, rule
->from_prefixlen
);
993 if (!in_addr_is_null(rule
->family
, &rule
->to
)) {
994 r
= in_addr_to_string(rule
->family
, &rule
->to
, &to_str
);
998 fprintf(f
, "%sto=%s/%hhu",
1000 to_str
, rule
->to_prefixlen
);
1004 if (rule
->tos
!= 0) {
1005 fprintf(f
, "%stos=%hhu",
1011 if (rule
->fwmark
!= 0) {
1012 fprintf(f
, "%sfwmark=%"PRIu32
"/%"PRIu32
,
1014 rule
->fwmark
, rule
->fwmask
);
1019 fprintf(f
, "%siif=%s",
1026 fprintf(f
, "%soif=%s",
1032 if (rule
->protocol
!= 0) {
1033 fprintf(f
, "%sprotocol=%hhu",
1039 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
1040 fprintf(f
, "%ssourcesport=%"PRIu16
"-%"PRIu16
,
1042 rule
->sport
.start
, rule
->sport
.end
);
1046 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
1047 fprintf(f
, "%sdestinationport=%"PRIu16
"-%"PRIu16
,
1049 rule
->dport
.start
, rule
->dport
.end
);
1053 fprintf(f
, "%stable=%"PRIu32
"\n",
1061 int routing_policy_load_rules(const char *state_file
, Set
**rules
) {
1062 _cleanup_strv_free_
char **l
= NULL
;
1063 _cleanup_free_
char *data
= NULL
;
1064 uint16_t low
= 0, high
= 0;
1072 r
= routing_policy_rule_read_full_file(state_file
, &data
);
1076 l
= strv_split_newlines(data
);
1080 r
= set_ensure_allocated(rules
, &routing_policy_rule_hash_ops
);
1084 STRV_FOREACH(i
, l
) {
1085 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
1087 p
= startswith(*i
, "RULE=");
1091 r
= routing_policy_rule_new(&rule
);
1096 _cleanup_free_
char *word
= NULL
, *a
= NULL
, *b
= NULL
;
1098 r
= extract_first_word(&p
, &word
, NULL
, 0);
1104 r
= split_pair(word
, "=", &a
, &b
);
1108 if (STR_IN_SET(a
, "from", "to")) {
1109 union in_addr_union
*buffer
;
1112 if (streq(a
, "to")) {
1114 prefixlen
= &rule
->to_prefixlen
;
1116 buffer
= &rule
->from
;
1117 prefixlen
= &rule
->from_prefixlen
;
1120 r
= in_addr_prefix_from_string_auto(b
, &rule
->family
, buffer
, prefixlen
);
1122 log_error_errno(r
, "RPDB rule prefix is invalid, ignoring assignment: %s", b
);
1126 } else if (streq(a
, "tos")) {
1127 r
= safe_atou8(b
, &rule
->tos
);
1129 log_error_errno(r
, "Failed to parse RPDB rule tos, ignoring: %s", b
);
1132 } else if (streq(a
, "table")) {
1133 r
= safe_atou32(b
, &rule
->table
);
1135 log_error_errno(r
, "Failed to parse RPDB rule table, ignoring: %s", b
);
1138 } else if (streq(a
, "fwmark")) {
1140 r
= parse_fwmark_fwmask(b
, &rule
->fwmark
, &rule
->fwmask
);
1142 log_error_errno(r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a
);
1145 } else if (streq(a
, "iif")) {
1147 if (free_and_strdup(&rule
->iif
, b
) < 0)
1150 } else if (streq(a
, "oif")) {
1152 if (free_and_strdup(&rule
->oif
, b
) < 0)
1154 } else if (streq(a
, "protocol")) {
1155 r
= safe_atou8(b
, &rule
->protocol
);
1157 log_error_errno(r
, "Failed to parse RPDB rule protocol, ignoring: %s", b
);
1160 } else if (streq(a
, "sourceport")) {
1162 r
= parse_ip_port_range(b
, &low
, &high
);
1164 log_error_errno(r
, "Invalid routing policy rule source port range, ignoring assignment:'%s'", b
);
1168 rule
->sport
.start
= low
;
1169 rule
->sport
.end
= high
;
1171 } else if (streq(a
, "destinationport")) {
1173 r
= parse_ip_port_range(b
, &low
, &high
);
1175 log_error_errno(r
, "Invalid routing policy rule destination port range, ignoring assignment:'%s'", b
);
1179 rule
->dport
.start
= low
;
1180 rule
->dport
.end
= high
;
1184 r
= set_put(*rules
, rule
);
1186 log_warning_errno(r
, "Failed to add RPDB rule to saved DB, ignoring: %s", p
);
1196 static bool manager_links_have_routing_policy_rule(Manager
*m
, RoutingPolicyRule
*rule
) {
1197 RoutingPolicyRule
*link_rule
;
1204 HASHMAP_FOREACH(link
, m
->links
, i
) {
1208 LIST_FOREACH(rules
, link_rule
, link
->network
->rules
)
1209 if (routing_policy_rule_compare_func(link_rule
, rule
) == 0)
1216 void routing_policy_rule_purge(Manager
*m
, Link
*link
) {
1217 RoutingPolicyRule
*rule
, *existing
;
1224 SET_FOREACH(rule
, m
->rules_saved
, i
) {
1225 existing
= set_get(m
->rules_foreign
, rule
);
1227 continue; /* Saved rule does not exist anymore. */
1229 if (manager_links_have_routing_policy_rule(m
, existing
))
1230 continue; /* Existing links have the saved rule. */
1232 /* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it
1233 * later when it is requested. */
1235 r
= routing_policy_rule_remove(existing
, link
, NULL
);
1237 log_warning_errno(r
, "Could not remove routing policy rules: %m");
1241 link
->routing_policy_rule_remove_messages
++;
1243 assert_se(set_remove(m
->rules_foreign
, existing
) == existing
);
1244 routing_policy_rule_free(existing
);