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 "ip-protocol-list.h"
11 #include "networkd-routing-policy-rule.h"
12 #include "netlink-util.h"
13 #include "networkd-manager.h"
14 #include "networkd-util.h"
15 #include "parse-util.h"
16 #include "socket-util.h"
17 #include "string-util.h"
20 int routing_policy_rule_new(RoutingPolicyRule
**ret
) {
21 RoutingPolicyRule
*rule
;
23 rule
= new(RoutingPolicyRule
, 1);
27 *rule
= (RoutingPolicyRule
) {
28 .table
= RT_TABLE_MAIN
,
35 void routing_policy_rule_free(RoutingPolicyRule
*rule
) {
41 LIST_REMOVE(rules
, rule
->network
->rules
, rule
);
42 assert(rule
->network
->n_rules
> 0);
43 rule
->network
->n_rules
--;
46 hashmap_remove(rule
->network
->rules_by_section
, rule
->section
);
50 if (set_get(rule
->manager
->rules
, rule
) == rule
)
51 set_remove(rule
->manager
->rules
, rule
);
52 if (set_get(rule
->manager
->rules_foreign
, rule
) == rule
)
53 set_remove(rule
->manager
->rules_foreign
, rule
);
56 network_config_section_free(rule
->section
);
62 static int routing_policy_rule_copy(RoutingPolicyRule
*dest
, RoutingPolicyRule
*src
) {
63 _cleanup_free_
char *iif
= NULL
, *oif
= NULL
;
69 iif
= strdup(src
->iif
);
75 oif
= strdup(src
->oif
);
80 dest
->family
= src
->family
;
81 dest
->from
= src
->from
;
82 dest
->from_prefixlen
= src
->from_prefixlen
;
84 dest
->to_prefixlen
= src
->to_prefixlen
;
85 dest
->invert_rule
= src
->invert_rule
;
87 dest
->fwmark
= src
->fwmark
;
88 dest
->fwmask
= src
->fwmask
;
89 dest
->priority
= src
->priority
;
90 dest
->table
= src
->table
;
91 dest
->iif
= TAKE_PTR(iif
);
92 dest
->oif
= TAKE_PTR(oif
);
93 dest
->protocol
= src
->protocol
;
94 dest
->sport
= src
->sport
;
95 dest
->dport
= src
->dport
;
100 static void routing_policy_rule_hash_func(const RoutingPolicyRule
*rule
, struct siphash
*state
) {
103 siphash24_compress(&rule
->family
, sizeof(rule
->family
), state
);
105 switch (rule
->family
) {
109 siphash24_compress(&rule
->from
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
110 siphash24_compress(&rule
->from_prefixlen
, sizeof(rule
->from_prefixlen
), state
);
112 siphash24_compress(&rule
->to
, FAMILY_ADDRESS_SIZE(rule
->family
), state
);
113 siphash24_compress(&rule
->to_prefixlen
, sizeof(rule
->to_prefixlen
), state
);
115 siphash24_compress_boolean(rule
->invert_rule
, state
);
117 siphash24_compress(&rule
->tos
, sizeof(rule
->tos
), state
);
118 siphash24_compress(&rule
->fwmark
, sizeof(rule
->fwmark
), state
);
119 siphash24_compress(&rule
->fwmask
, sizeof(rule
->fwmask
), state
);
120 siphash24_compress(&rule
->priority
, sizeof(rule
->priority
), state
);
121 siphash24_compress(&rule
->table
, sizeof(rule
->table
), state
);
123 siphash24_compress(&rule
->protocol
, sizeof(rule
->protocol
), state
);
124 siphash24_compress(&rule
->sport
, sizeof(rule
->sport
), state
);
125 siphash24_compress(&rule
->dport
, sizeof(rule
->dport
), state
);
128 siphash24_compress(rule
->iif
, strlen(rule
->iif
), state
);
131 siphash24_compress(rule
->oif
, strlen(rule
->oif
), state
);
135 /* treat any other address family as AF_UNSPEC */
140 static int routing_policy_rule_compare_func(const RoutingPolicyRule
*a
, const RoutingPolicyRule
*b
) {
143 r
= CMP(a
->family
, b
->family
);
150 r
= CMP(a
->from_prefixlen
, b
->from_prefixlen
);
154 r
= CMP(a
->to_prefixlen
, b
->to_prefixlen
);
158 r
= CMP(a
->invert_rule
, b
->invert_rule
);
162 r
= CMP(a
->tos
, b
->tos
);
166 r
= CMP(a
->fwmark
, b
->fwmark
);
170 r
= CMP(a
->fwmask
, b
->fwmask
);
174 r
= CMP(a
->priority
, b
->priority
);
178 r
= CMP(a
->table
, b
->table
);
182 r
= strcmp_ptr(a
->iif
, b
->iif
);
186 r
= strcmp_ptr(a
->oif
, b
->oif
);
190 r
= CMP(a
->protocol
, b
->protocol
);
194 r
= memcmp(&a
->sport
, &b
->sport
, sizeof(a
->sport
));
198 r
= memcmp(&a
->dport
, &b
->dport
, sizeof(a
->dport
));
202 r
= memcmp(&a
->from
, &b
->from
, FAMILY_ADDRESS_SIZE(a
->family
));
206 return memcmp(&a
->to
, &b
->to
, FAMILY_ADDRESS_SIZE(a
->family
));
209 /* treat any other address family as AF_UNSPEC */
214 DEFINE_PRIVATE_HASH_OPS(routing_policy_rule_hash_ops
, RoutingPolicyRule
, routing_policy_rule_hash_func
, routing_policy_rule_compare_func
);
216 int routing_policy_rule_get(Manager
*m
, RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
218 RoutingPolicyRule
*existing
;
222 existing
= set_get(m
->rules
, rule
);
229 existing
= set_get(m
->rules_foreign
, rule
);
239 int routing_policy_rule_make_local(Manager
*m
, RoutingPolicyRule
*rule
) {
244 if (set_contains(m
->rules_foreign
, rule
)) {
245 set_remove(m
->rules_foreign
, rule
);
247 r
= set_ensure_allocated(&m
->rules
, &routing_policy_rule_hash_ops
);
251 r
= set_put(m
->rules
, rule
);
255 routing_policy_rule_free(rule
);
261 static int routing_policy_rule_add_internal(Manager
*m
, Set
**rules
, RoutingPolicyRule
*in
, RoutingPolicyRule
**ret
) {
262 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
269 r
= routing_policy_rule_new(&rule
);
275 r
= routing_policy_rule_copy(rule
, in
);
279 r
= set_ensure_allocated(rules
, &routing_policy_rule_hash_ops
);
283 r
= set_put(*rules
, rule
);
296 static int routing_policy_rule_add(Manager
*m
, RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
297 return routing_policy_rule_add_internal(m
, &m
->rules
, rule
, ret
);
300 int routing_policy_rule_add_foreign(Manager
*m
, RoutingPolicyRule
*rule
, RoutingPolicyRule
**ret
) {
301 return routing_policy_rule_add_internal(m
, &m
->rules_foreign
, rule
, ret
);
304 static int routing_policy_rule_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
309 assert(link
->ifname
);
311 link
->routing_policy_rule_remove_messages
--;
313 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
316 r
= sd_netlink_message_get_errno(m
);
318 log_link_warning_errno(link
, r
, "Could not drop routing policy rule: %m");
323 int routing_policy_rule_remove(RoutingPolicyRule
*routing_policy_rule
, Link
*link
, link_netlink_message_handler_t callback
) {
324 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
327 assert(routing_policy_rule
);
329 assert(link
->manager
);
330 assert(link
->manager
->rtnl
);
331 assert(link
->ifindex
> 0);
332 assert(IN_SET(routing_policy_rule
->family
, AF_INET
, AF_INET6
));
334 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_DELRULE
, routing_policy_rule
->family
);
336 return log_error_errno(r
, "Could not allocate RTM_DELRULE message: %m");
338 if (in_addr_is_null(routing_policy_rule
->family
, &routing_policy_rule
->from
) == 0) {
339 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, routing_policy_rule
->family
, &routing_policy_rule
->from
);
341 return log_error_errno(r
, "Could not append FRA_SRC attribute: %m");
343 r
= sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m
, routing_policy_rule
->from_prefixlen
);
345 return log_error_errno(r
, "Could not set source prefix length: %m");
348 if (in_addr_is_null(routing_policy_rule
->family
, &routing_policy_rule
->to
) == 0) {
349 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, routing_policy_rule
->family
, &routing_policy_rule
->to
);
351 return log_error_errno(r
, "Could not append FRA_DST attribute: %m");
353 r
= sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m
, routing_policy_rule
->to_prefixlen
);
355 return log_error_errno(r
, "Could not set destination prefix length: %m");
358 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
,
359 callback
?: routing_policy_rule_remove_handler
,
360 link_netlink_destroy_callback
, link
);
362 return log_error_errno(r
, "Could not send rtnetlink message: %m");
369 static int routing_policy_rule_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutingPolicyRule
**ret
) {
370 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
371 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
376 assert(!!filename
== (section_line
> 0));
379 r
= network_config_section_new(filename
, section_line
, &n
);
383 rule
= hashmap_get(network
->rules_by_section
, n
);
385 *ret
= TAKE_PTR(rule
);
391 r
= routing_policy_rule_new(&rule
);
395 rule
->network
= network
;
396 LIST_APPEND(rules
, network
->rules
, rule
);
400 rule
->section
= TAKE_PTR(n
);
402 r
= hashmap_ensure_allocated(&network
->rules_by_section
, &network_config_hash_ops
);
406 r
= hashmap_put(network
->rules_by_section
, rule
->section
, rule
);
411 *ret
= TAKE_PTR(rule
);
416 static int routing_policy_rule_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
422 assert(link
->ifname
);
423 assert(link
->routing_policy_rule_messages
> 0);
425 link
->routing_policy_rule_messages
--;
427 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
430 r
= sd_netlink_message_get_errno(m
);
431 if (r
< 0 && r
!= -EEXIST
) {
432 log_link_warning_errno(link
, r
, "Could not add routing policy rule: %m");
433 link_enter_failed(link
);
437 if (link
->routing_policy_rule_messages
== 0) {
438 log_link_debug(link
, "Routing policy rule configured");
439 link
->routing_policy_rules_configured
= true;
440 link_check_ready(link
);
446 int routing_policy_rule_configure(RoutingPolicyRule
*rule
, Link
*link
, link_netlink_message_handler_t callback
) {
447 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
452 assert(link
->ifindex
> 0);
453 assert(link
->manager
);
454 assert(link
->manager
->rtnl
);
456 if (rule
->family
== AF_INET6
&& link_sysctl_ipv6_enabled(link
) == 0) {
457 log_link_warning(link
, "An IPv6 routing policy rule is requested, but IPv6 is disabled by sysctl, ignoring.");
461 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_NEWRULE
, rule
->family
);
463 return log_error_errno(r
, "Could not allocate RTM_NEWRULE message: %m");
465 if (in_addr_is_null(rule
->family
, &rule
->from
) == 0) {
466 r
= netlink_message_append_in_addr_union(m
, FRA_SRC
, rule
->family
, &rule
->from
);
468 return log_error_errno(r
, "Could not append FRA_SRC attribute: %m");
470 r
= sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m
, rule
->from_prefixlen
);
472 return log_error_errno(r
, "Could not set source prefix length: %m");
475 if (in_addr_is_null(rule
->family
, &rule
->to
) == 0) {
476 r
= netlink_message_append_in_addr_union(m
, FRA_DST
, rule
->family
, &rule
->to
);
478 return log_error_errno(r
, "Could not append FRA_DST attribute: %m");
480 r
= sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m
, rule
->to_prefixlen
);
482 return log_error_errno(r
, "Could not set destination prefix length: %m");
485 r
= sd_netlink_message_append_u32(m
, FRA_PRIORITY
, rule
->priority
);
487 return log_error_errno(r
, "Could not append FRA_PRIORITY attribute: %m");
490 r
= sd_rtnl_message_routing_policy_rule_set_tos(m
, rule
->tos
);
492 return log_error_errno(r
, "Could not set ip rule tos: %m");
495 if (rule
->table
< 256) {
496 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, rule
->table
);
498 return log_error_errno(r
, "Could not set ip rule table: %m");
500 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
502 return log_error_errno(r
, "Could not set ip rule table: %m");
504 r
= sd_netlink_message_append_u32(m
, FRA_TABLE
, rule
->table
);
506 return log_error_errno(r
, "Could not append FRA_TABLE attribute: %m");
509 if (rule
->fwmark
> 0) {
510 r
= sd_netlink_message_append_u32(m
, FRA_FWMARK
, rule
->fwmark
);
512 return log_error_errno(r
, "Could not append FRA_FWMARK attribute: %m");
515 if (rule
->fwmask
> 0) {
516 r
= sd_netlink_message_append_u32(m
, FRA_FWMASK
, rule
->fwmask
);
518 return log_error_errno(r
, "Could not append FRA_FWMASK attribute: %m");
522 r
= sd_netlink_message_append_string(m
, FRA_IFNAME
, rule
->iif
);
524 return log_error_errno(r
, "Could not append FRA_IFNAME attribute: %m");
528 r
= sd_netlink_message_append_string(m
, FRA_OIFNAME
, rule
->oif
);
530 return log_error_errno(r
, "Could not append FRA_OIFNAME attribute: %m");
533 r
= sd_netlink_message_append_u8(m
, FRA_IP_PROTO
, rule
->protocol
);
535 return log_error_errno(r
, "Could not append FRA_IP_PROTO attribute: %m");
537 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
538 r
= sd_netlink_message_append_data(m
, FRA_SPORT_RANGE
, &rule
->sport
, sizeof(rule
->sport
));
540 return log_error_errno(r
, "Could not append FRA_SPORT_RANGE attribute: %m");
543 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
544 r
= sd_netlink_message_append_data(m
, FRA_DPORT_RANGE
, &rule
->dport
, sizeof(rule
->dport
));
546 return log_error_errno(r
, "Could not append FRA_DPORT_RANGE attribute: %m");
549 if (rule
->invert_rule
) {
550 r
= sd_rtnl_message_routing_policy_rule_set_flags(m
, FIB_RULE_INVERT
);
552 return log_error_errno(r
, "Could not append FIB_RULE_INVERT attribute: %m");
557 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
,
558 callback
?: routing_policy_rule_handler
,
559 link_netlink_destroy_callback
, link
);
561 return log_error_errno(r
, "Could not send rtnetlink message: %m");
565 r
= routing_policy_rule_add(link
->manager
, rule
, NULL
);
567 return log_error_errno(r
, "Could not add rule: %m");
572 int routing_policy_rule_section_verify(RoutingPolicyRule
*rule
) {
575 if (section_is_invalid(rule
->section
))
578 if ((rule
->family
== AF_INET
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
)) ||
579 (rule
->family
== AF_INET6
&& FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
)))
580 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
581 "%s: address family specified by Family= conflicts with the address "
582 "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
583 rule
->section
->filename
, rule
->section
->line
);
585 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV4
| ADDRESS_FAMILY_IPV6
)) {
586 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule6
= NULL
;
588 assert(rule
->family
== AF_UNSPEC
);
590 /* When Family=both, we need to copy the section, AF_INET and AF_INET6. */
592 r
= routing_policy_rule_new_static(rule
->network
, NULL
, 0, &rule6
);
596 r
= routing_policy_rule_copy(rule6
, rule
);
600 rule
->family
= AF_INET
;
601 rule6
->family
= AF_INET6
;
606 if (rule
->family
== AF_UNSPEC
) {
607 if (FLAGS_SET(rule
->address_family
, ADDRESS_FAMILY_IPV6
))
608 rule
->family
= AF_INET6
;
610 rule
->family
= AF_INET
;
616 static int parse_fwmark_fwmask(const char *s
, uint32_t *fwmark
, uint32_t *fwmask
) {
617 _cleanup_free_
char *f
= NULL
;
631 r
= safe_atou32(f
, fwmark
);
633 return log_error_errno(r
, "Failed to parse RPDB rule firewall mark, ignoring: %s", f
);
636 r
= safe_atou32(p
, fwmask
);
638 return log_error_errno(r
, "Failed to parse RPDB rule mask, ignoring: %s", f
);
644 int config_parse_routing_policy_rule_tos(
646 const char *filename
,
649 unsigned section_line
,
656 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
657 Network
*network
= userdata
;
666 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
670 r
= safe_atou8(rvalue
, &n
->tos
);
672 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule tos, ignoring: %s", rvalue
);
681 int config_parse_routing_policy_rule_priority(
683 const char *filename
,
686 unsigned section_line
,
693 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
694 Network
*network
= userdata
;
703 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
707 r
= safe_atou32(rvalue
, &n
->priority
);
709 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule priority, ignoring: %s", rvalue
);
718 int config_parse_routing_policy_rule_table(
720 const char *filename
,
723 unsigned section_line
,
730 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
731 Network
*network
= userdata
;
740 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
744 r
= safe_atou32(rvalue
, &n
->table
);
746 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule table, ignoring: %s", rvalue
);
755 int config_parse_routing_policy_rule_fwmark_mask(
757 const char *filename
,
760 unsigned section_line
,
767 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
768 Network
*network
= userdata
;
777 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
781 r
= parse_fwmark_fwmask(rvalue
, &n
->fwmark
, &n
->fwmask
);
783 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue
);
792 int config_parse_routing_policy_rule_prefix(
794 const char *filename
,
797 unsigned section_line
,
804 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
805 Network
*network
= userdata
;
806 union in_addr_union
*buffer
;
816 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
820 if (streq(lvalue
, "To")) {
822 prefixlen
= &n
->to_prefixlen
;
825 prefixlen
= &n
->from_prefixlen
;
828 if (n
->family
== AF_UNSPEC
)
829 r
= in_addr_prefix_from_string_auto(rvalue
, &n
->family
, buffer
, prefixlen
);
831 r
= in_addr_prefix_from_string(rvalue
, n
->family
, buffer
, prefixlen
);
833 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue
);
842 int config_parse_routing_policy_rule_device(
844 const char *filename
,
847 unsigned section_line
,
854 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
855 Network
*network
= userdata
;
864 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
868 if (!ifname_valid(rvalue
)) {
869 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse '%s' interface name, ignoring: %s", lvalue
, rvalue
);
873 if (streq(lvalue
, "IncomingInterface")) {
874 r
= free_and_strdup(&n
->iif
, rvalue
);
878 r
= free_and_strdup(&n
->oif
, rvalue
);
888 int config_parse_routing_policy_rule_port_range(
890 const char *filename
,
893 unsigned section_line
,
899 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
900 Network
*network
= userdata
;
910 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
914 r
= parse_ip_port_range(rvalue
, &low
, &high
);
916 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse routing policy rule port range '%s'", rvalue
);
920 if (streq(lvalue
, "SourcePort")) {
921 n
->sport
.start
= low
;
924 n
->dport
.start
= low
;
933 int config_parse_routing_policy_rule_ip_protocol(
935 const char *filename
,
938 unsigned section_line
,
945 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
946 Network
*network
= userdata
;
955 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
959 r
= parse_ip_protocol(rvalue
);
961 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue
);
972 int config_parse_routing_policy_rule_invert(
974 const char *filename
,
977 unsigned section_line
,
984 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
985 Network
*network
= userdata
;
994 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
998 r
= parse_boolean(rvalue
);
1000 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule invert, ignoring: %s", rvalue
);
1011 int config_parse_routing_policy_rule_family(
1013 const char *filename
,
1015 const char *section
,
1016 unsigned section_line
,
1023 _cleanup_(routing_policy_rule_free_or_set_invalidp
) RoutingPolicyRule
*n
= NULL
;
1024 Network
*network
= userdata
;
1034 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
1038 a
= routing_policy_rule_address_family_from_string(rvalue
);
1040 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
1041 "Invalid address family '%s', ignoring.", rvalue
);
1045 n
->address_family
= a
;
1051 static int routing_policy_rule_read_full_file(const char *state_file
, char **ret
) {
1052 _cleanup_free_
char *s
= NULL
;
1058 r
= read_full_file(state_file
, &s
, &size
);
1071 int routing_policy_serialize_rules(Set
*rules
, FILE *f
) {
1072 RoutingPolicyRule
*rule
= NULL
;
1078 SET_FOREACH(rule
, rules
, i
) {
1079 _cleanup_free_
char *from_str
= NULL
, *to_str
= NULL
;
1081 const char *family_str
;
1085 if (!in_addr_is_null(rule
->family
, &rule
->from
)) {
1086 r
= in_addr_to_string(rule
->family
, &rule
->from
, &from_str
);
1090 fprintf(f
, "from=%s/%hhu",
1091 from_str
, rule
->from_prefixlen
);
1095 if (!in_addr_is_null(rule
->family
, &rule
->to
)) {
1096 r
= in_addr_to_string(rule
->family
, &rule
->to
, &to_str
);
1100 fprintf(f
, "%sto=%s/%hhu",
1102 to_str
, rule
->to_prefixlen
);
1106 family_str
= af_to_name(rule
->family
);
1108 fprintf(f
, "%sfamily=%s",
1112 if (rule
->tos
!= 0) {
1113 fprintf(f
, "%stos=%hhu",
1119 fprintf(f
, "%spriority=%"PRIu32
,
1123 if (rule
->fwmark
!= 0) {
1124 fprintf(f
, "%sfwmark=%"PRIu32
"/%"PRIu32
,
1126 rule
->fwmark
, rule
->fwmask
);
1131 fprintf(f
, "%siif=%s",
1138 fprintf(f
, "%soif=%s",
1144 if (rule
->protocol
!= 0) {
1145 fprintf(f
, "%sprotocol=%hhu",
1151 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
1152 fprintf(f
, "%ssourcesport=%"PRIu16
"-%"PRIu16
,
1154 rule
->sport
.start
, rule
->sport
.end
);
1158 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
1159 fprintf(f
, "%sdestinationport=%"PRIu16
"-%"PRIu16
,
1161 rule
->dport
.start
, rule
->dport
.end
);
1165 fprintf(f
, "%stable=%"PRIu32
"\n",
1173 int routing_policy_load_rules(const char *state_file
, Set
**rules
) {
1174 _cleanup_strv_free_
char **l
= NULL
;
1175 _cleanup_free_
char *data
= NULL
;
1176 uint16_t low
= 0, high
= 0;
1184 r
= routing_policy_rule_read_full_file(state_file
, &data
);
1188 l
= strv_split_newlines(data
);
1192 r
= set_ensure_allocated(rules
, &routing_policy_rule_hash_ops
);
1196 STRV_FOREACH(i
, l
) {
1197 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
1199 p
= startswith(*i
, "RULE=");
1203 r
= routing_policy_rule_new(&rule
);
1208 _cleanup_free_
char *word
= NULL
, *a
= NULL
, *b
= NULL
;
1210 r
= extract_first_word(&p
, &word
, NULL
, 0);
1216 r
= split_pair(word
, "=", &a
, &b
);
1220 if (STR_IN_SET(a
, "from", "to")) {
1221 union in_addr_union
*buffer
;
1224 if (streq(a
, "to")) {
1226 prefixlen
= &rule
->to_prefixlen
;
1228 buffer
= &rule
->from
;
1229 prefixlen
= &rule
->from_prefixlen
;
1232 r
= in_addr_prefix_from_string_auto(b
, &rule
->family
, buffer
, prefixlen
);
1234 log_error_errno(r
, "RPDB rule prefix is invalid, ignoring assignment: %s", b
);
1238 } else if (streq(a
, "family")) {
1239 r
= af_from_name(b
);
1241 log_error_errno(r
, "Failed to parse RPDB rule family, ignoring: %s", b
);
1245 } else if (streq(a
, "tos")) {
1246 r
= safe_atou8(b
, &rule
->tos
);
1248 log_error_errno(r
, "Failed to parse RPDB rule tos, ignoring: %s", b
);
1251 } else if (streq(a
, "table")) {
1252 r
= safe_atou32(b
, &rule
->table
);
1254 log_error_errno(r
, "Failed to parse RPDB rule table, ignoring: %s", b
);
1257 } else if (streq(a
, "priority")) {
1258 r
= safe_atou32(b
, &rule
->priority
);
1260 log_error_errno(r
, "Failed to parse RPDB rule priority, ignoring: %s", b
);
1263 } else if (streq(a
, "fwmark")) {
1265 r
= parse_fwmark_fwmask(b
, &rule
->fwmark
, &rule
->fwmask
);
1267 log_error_errno(r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a
);
1270 } else if (streq(a
, "iif")) {
1272 if (free_and_strdup(&rule
->iif
, b
) < 0)
1275 } else if (streq(a
, "oif")) {
1277 if (free_and_strdup(&rule
->oif
, b
) < 0)
1279 } else if (streq(a
, "protocol")) {
1280 r
= safe_atou8(b
, &rule
->protocol
);
1282 log_error_errno(r
, "Failed to parse RPDB rule protocol, ignoring: %s", b
);
1285 } else if (streq(a
, "sourceport")) {
1287 r
= parse_ip_port_range(b
, &low
, &high
);
1289 log_error_errno(r
, "Invalid routing policy rule source port range, ignoring assignment:'%s'", b
);
1293 rule
->sport
.start
= low
;
1294 rule
->sport
.end
= high
;
1296 } else if (streq(a
, "destinationport")) {
1298 r
= parse_ip_port_range(b
, &low
, &high
);
1300 log_error_errno(r
, "Invalid routing policy rule destination port range, ignoring assignment:'%s'", b
);
1304 rule
->dport
.start
= low
;
1305 rule
->dport
.end
= high
;
1309 r
= set_put(*rules
, rule
);
1311 log_warning_errno(r
, "Failed to add RPDB rule to saved DB, ignoring: %s", p
);
1321 static bool manager_links_have_routing_policy_rule(Manager
*m
, RoutingPolicyRule
*rule
) {
1322 RoutingPolicyRule
*link_rule
;
1329 HASHMAP_FOREACH(link
, m
->links
, i
) {
1333 LIST_FOREACH(rules
, link_rule
, link
->network
->rules
)
1334 if (routing_policy_rule_compare_func(link_rule
, rule
) == 0)
1341 void routing_policy_rule_purge(Manager
*m
, Link
*link
) {
1342 RoutingPolicyRule
*rule
, *existing
;
1349 SET_FOREACH(rule
, m
->rules_saved
, i
) {
1350 existing
= set_get(m
->rules_foreign
, rule
);
1352 continue; /* Saved rule does not exist anymore. */
1354 if (manager_links_have_routing_policy_rule(m
, existing
))
1355 continue; /* Existing links have the saved rule. */
1357 /* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it
1358 * later when it is requested. */
1360 r
= routing_policy_rule_remove(existing
, link
, NULL
);
1362 log_warning_errno(r
, "Could not remove routing policy rules: %m");
1366 link
->routing_policy_rule_remove_messages
++;
1368 assert_se(set_remove(m
->rules_foreign
, existing
) == existing
);
1369 routing_policy_rule_free(existing
);