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 set_remove(rule
->manager
->rules
, rule
);
50 set_remove(rule
->manager
->rules_foreign
, rule
);
53 network_config_section_free(rule
->section
);
59 static void routing_policy_rule_hash_func(const void *b
, struct siphash
*state
) {
60 const RoutingPolicyRule
*rule
= b
;
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(&rule
->tos
, sizeof(rule
->tos
), state
);
77 siphash24_compress(&rule
->fwmark
, sizeof(rule
->fwmark
), state
);
78 siphash24_compress(&rule
->table
, sizeof(rule
->table
), state
);
80 siphash24_compress(&rule
->protocol
, sizeof(rule
->protocol
), state
);
81 siphash24_compress(&rule
->sport
, sizeof(rule
->sport
), state
);
82 siphash24_compress(&rule
->dport
, sizeof(rule
->dport
), state
);
85 siphash24_compress(rule
->iif
, strlen(rule
->iif
), state
);
88 siphash24_compress(rule
->oif
, strlen(rule
->oif
), state
);
92 /* treat any other address family as AF_UNSPEC */
97 static int routing_policy_rule_compare_func(const void *_a
, const void *_b
) {
98 const RoutingPolicyRule
*a
= _a
, *b
= _b
;
101 r
= CMP(a
->family
, b
->family
);
108 r
= CMP(a
->from_prefixlen
, b
->from_prefixlen
);
112 r
= CMP(a
->to_prefixlen
, b
->to_prefixlen
);
116 r
= CMP(a
->tos
, b
->tos
);
120 r
= CMP(a
->fwmask
, b
->fwmask
);
124 r
= CMP(a
->table
, b
->table
);
128 r
= strcmp_ptr(a
->iif
, b
->iif
);
132 r
= strcmp_ptr(a
->oif
, b
->oif
);
136 r
= CMP(a
->protocol
, b
->protocol
);
140 r
= memcmp(&a
->sport
, &b
->sport
, sizeof(a
->sport
));
144 r
= memcmp(&a
->dport
, &b
->dport
, sizeof(a
->dport
));
148 r
= memcmp(&a
->from
, &b
->from
, FAMILY_ADDRESS_SIZE(a
->family
));
152 return memcmp(&a
->to
, &b
->to
, FAMILY_ADDRESS_SIZE(a
->family
));
155 /* treat any other address family as AF_UNSPEC */
160 const struct hash_ops routing_policy_rule_hash_ops
= {
161 .hash
= routing_policy_rule_hash_func
,
162 .compare
= routing_policy_rule_compare_func
165 int routing_policy_rule_get(Manager
*m
,
167 const union in_addr_union
*from
,
168 uint8_t from_prefixlen
,
169 const union in_addr_union
*to
,
170 uint8_t to_prefixlen
,
177 struct fib_rule_port_range
*sport
,
178 struct fib_rule_port_range
*dport
,
179 RoutingPolicyRule
**ret
) {
181 RoutingPolicyRule rule
, *existing
;
183 assert_return(m
, -1);
185 rule
= (RoutingPolicyRule
) {
188 .from_prefixlen
= from_prefixlen
,
190 .to_prefixlen
= to_prefixlen
,
196 .protocol
= protocol
,
201 existing
= set_get(m
->rules
, &rule
);
208 existing
= set_get(m
->rules_foreign
, &rule
);
218 int routing_policy_rule_make_local(Manager
*m
, RoutingPolicyRule
*rule
) {
223 if (set_contains(m
->rules_foreign
, rule
)) {
224 set_remove(m
->rules_foreign
, rule
);
226 r
= set_ensure_allocated(&m
->rules
, &routing_policy_rule_hash_ops
);
230 return set_put(m
->rules
, rule
);
236 static int routing_policy_rule_add_internal(Manager
*m
,
239 const union in_addr_union
*from
,
240 uint8_t from_prefixlen
,
241 const union in_addr_union
*to
,
242 uint8_t to_prefixlen
,
249 const struct fib_rule_port_range
*sport
,
250 const struct fib_rule_port_range
*dport
,
251 RoutingPolicyRule
**ret
) {
253 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
254 _cleanup_free_
char *iif
= NULL
, *oif
= NULL
;
257 assert_return(rules
, -EINVAL
);
271 r
= routing_policy_rule_new(&rule
);
276 rule
->family
= family
;
278 rule
->from_prefixlen
= from_prefixlen
;
280 rule
->to_prefixlen
= to_prefixlen
;
282 rule
->fwmark
= fwmark
;
286 rule
->protocol
= protocol
;
287 rule
->sport
= *sport
;
288 rule
->dport
= *dport
;
290 r
= set_ensure_allocated(rules
, &routing_policy_rule_hash_ops
);
294 r
= set_put(*rules
, rule
);
307 int routing_policy_rule_add(Manager
*m
,
309 const union in_addr_union
*from
,
310 uint8_t from_prefixlen
,
311 const union in_addr_union
*to
,
312 uint8_t to_prefixlen
,
319 const struct fib_rule_port_range
*sport
,
320 const struct fib_rule_port_range
*dport
,
321 RoutingPolicyRule
**ret
) {
323 return routing_policy_rule_add_internal(m
, &m
->rules
, family
, from
, from_prefixlen
, to
, to_prefixlen
, tos
, fwmark
, table
, iif
, oif
, protocol
, sport
, dport
, ret
);
326 int routing_policy_rule_add_foreign(Manager
*m
,
328 const union in_addr_union
*from
,
329 uint8_t from_prefixlen
,
330 const union in_addr_union
*to
,
331 uint8_t to_prefixlen
,
338 const struct fib_rule_port_range
*sport
,
339 const struct fib_rule_port_range
*dport
,
340 RoutingPolicyRule
**ret
) {
341 return routing_policy_rule_add_internal(m
, &m
->rules_foreign
, family
, from
, from_prefixlen
, to
, to_prefixlen
, tos
, fwmark
, table
, iif
, oif
, protocol
, sport
, dport
, ret
);
344 static int routing_policy_rule_remove_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
345 Link
*link
= userdata
;
350 assert(link
->ifname
);
352 link
->routing_policy_rule_remove_messages
--;
354 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
357 r
= sd_netlink_message_get_errno(m
);
359 log_link_warning_errno(link
, r
, "Could not drop routing policy rule: %m");
364 int routing_policy_rule_remove(RoutingPolicyRule
*routing_policy_rule
, Link
*link
, sd_netlink_message_handler_t callback
) {
365 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
368 assert(routing_policy_rule
);
370 assert(link
->manager
);
371 assert(link
->manager
->rtnl
);
372 assert(link
->ifindex
> 0);
373 assert(IN_SET(routing_policy_rule
->family
, AF_INET
, AF_INET6
));
375 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_DELRULE
, routing_policy_rule
->family
);
377 return log_error_errno(r
, "Could not allocate RTM_DELRULE message: %m");
379 if (!in_addr_is_null(routing_policy_rule
->family
, &routing_policy_rule
->from
)) {
380 if (routing_policy_rule
->family
== AF_INET
)
381 r
= sd_netlink_message_append_in_addr(m
, FRA_SRC
, &routing_policy_rule
->from
.in
);
383 r
= sd_netlink_message_append_in6_addr(m
, FRA_SRC
, &routing_policy_rule
->from
.in6
);
386 return log_error_errno(r
, "Could not append FRA_SRC attribute: %m");
388 r
= sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m
, routing_policy_rule
->from_prefixlen
);
390 return log_error_errno(r
, "Could not set source prefix length: %m");
393 if (!in_addr_is_null(routing_policy_rule
->family
, &routing_policy_rule
->to
)) {
394 if (routing_policy_rule
->family
== AF_INET
)
395 r
= sd_netlink_message_append_in_addr(m
, FRA_DST
, &routing_policy_rule
->to
.in
);
397 r
= sd_netlink_message_append_in6_addr(m
, FRA_DST
, &routing_policy_rule
->to
.in6
);
400 return log_error_errno(r
, "Could not append FRA_DST attribute: %m");
402 r
= sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m
, routing_policy_rule
->to_prefixlen
);
404 return log_error_errno(r
, "Could not set destination prefix length: %m");
407 r
= sd_netlink_call_async(link
->manager
->rtnl
, NULL
, m
, callback
,
408 link_netlink_destroy_callback
, link
, 0, __func__
);
410 return log_error_errno(r
, "Could not send rtnetlink message: %m");
417 static int routing_policy_rule_new_static(Network
*network
, const char *filename
, unsigned section_line
, RoutingPolicyRule
**ret
) {
418 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
419 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
424 assert(!!filename
== (section_line
> 0));
427 r
= network_config_section_new(filename
, section_line
, &n
);
431 rule
= hashmap_get(network
->rules_by_section
, n
);
433 *ret
= TAKE_PTR(rule
);
439 r
= routing_policy_rule_new(&rule
);
443 rule
->network
= network
;
444 LIST_APPEND(rules
, network
->rules
, rule
);
448 rule
->section
= TAKE_PTR(n
);
450 r
= hashmap_ensure_allocated(&network
->rules_by_section
, &network_config_hash_ops
);
454 r
= hashmap_put(network
->rules_by_section
, rule
->section
, rule
);
459 *ret
= TAKE_PTR(rule
);
464 int link_routing_policy_rule_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
465 Link
*link
= userdata
;
471 assert(link
->ifname
);
472 assert(link
->routing_policy_rule_messages
> 0);
474 link
->routing_policy_rule_messages
--;
476 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
479 r
= sd_netlink_message_get_errno(m
);
480 if (r
< 0 && r
!= -EEXIST
)
481 log_link_warning_errno(link
, r
, "Could not add routing policy rule: %m");
483 if (link
->routing_policy_rule_messages
== 0) {
484 log_link_debug(link
, "Routing policy rule configured");
485 link
->routing_policy_rules_configured
= true;
486 link_check_ready(link
);
492 int routing_policy_rule_configure(RoutingPolicyRule
*rule
, Link
*link
, sd_netlink_message_handler_t callback
, bool update
) {
493 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
498 assert(link
->ifindex
> 0);
499 assert(link
->manager
);
500 assert(link
->manager
->rtnl
);
502 r
= sd_rtnl_message_new_routing_policy_rule(link
->manager
->rtnl
, &m
, RTM_NEWRULE
, rule
->family
);
504 return log_error_errno(r
, "Could not allocate RTM_NEWRULE message: %m");
506 if (!in_addr_is_null(rule
->family
, &rule
->from
)) {
507 if (rule
->family
== AF_INET
)
508 r
= sd_netlink_message_append_in_addr(m
, FRA_SRC
, &rule
->from
.in
);
510 r
= sd_netlink_message_append_in6_addr(m
, FRA_SRC
, &rule
->from
.in6
);
513 return log_error_errno(r
, "Could not append FRA_SRC attribute: %m");
515 r
= sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m
, rule
->from_prefixlen
);
517 return log_error_errno(r
, "Could not set source prefix length: %m");
520 if (!in_addr_is_null(rule
->family
, &rule
->to
)) {
521 if (rule
->family
== AF_INET
)
522 r
= sd_netlink_message_append_in_addr(m
, FRA_DST
, &rule
->to
.in
);
524 r
= sd_netlink_message_append_in6_addr(m
, FRA_DST
, &rule
->to
.in6
);
527 return log_error_errno(r
, "Could not append FRA_DST attribute: %m");
529 r
= sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m
, rule
->to_prefixlen
);
531 return log_error_errno(r
, "Could not set destination prefix length: %m");
534 r
= sd_netlink_message_append_u32(m
, FRA_PRIORITY
, rule
->priority
);
536 return log_error_errno(r
, "Could not append FRA_PRIORITY attribute: %m");
539 r
= sd_rtnl_message_routing_policy_rule_set_tos(m
, rule
->tos
);
541 return log_error_errno(r
, "Could not set ip rule tos: %m");
544 if (rule
->table
< 256) {
545 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, rule
->table
);
547 return log_error_errno(r
, "Could not set ip rule table: %m");
549 r
= sd_rtnl_message_routing_policy_rule_set_table(m
, RT_TABLE_UNSPEC
);
551 return log_error_errno(r
, "Could not set ip rule table: %m");
553 r
= sd_netlink_message_append_u32(m
, FRA_TABLE
, rule
->table
);
555 return log_error_errno(r
, "Could not append FRA_TABLE attribute: %m");
558 if (rule
->fwmark
> 0) {
559 r
= sd_netlink_message_append_u32(m
, FRA_FWMARK
, rule
->fwmark
);
561 return log_error_errno(r
, "Could not append FRA_FWMARK attribute: %m");
564 if (rule
->fwmask
> 0) {
565 r
= sd_netlink_message_append_u32(m
, FRA_FWMASK
, rule
->fwmask
);
567 return log_error_errno(r
, "Could not append FRA_FWMASK attribute: %m");
571 r
= sd_netlink_message_append_string(m
, FRA_IFNAME
, rule
->iif
);
573 return log_error_errno(r
, "Could not append FRA_IFNAME attribute: %m");
577 r
= sd_netlink_message_append_string(m
, FRA_OIFNAME
, rule
->oif
);
579 return log_error_errno(r
, "Could not append FRA_OIFNAME attribute: %m");
582 r
= sd_netlink_message_append_u8(m
, FRA_IP_PROTO
, rule
->protocol
);
584 return log_error_errno(r
, "Could not append FRA_IP_PROTO attribute: %m");
586 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
587 r
= sd_netlink_message_append_data(m
, FRA_SPORT_RANGE
, &rule
->sport
, sizeof(rule
->sport
));
589 return log_error_errno(r
, "Could not append FRA_SPORT_RANGE attribute: %m");
592 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
593 r
= sd_netlink_message_append_data(m
, FRA_DPORT_RANGE
, &rule
->dport
, sizeof(rule
->dport
));
595 return log_error_errno(r
, "Could not append FRA_DPORT_RANGE attribute: %m");
600 r
= sd_netlink_call_async(link
->manager
->rtnl
, NULL
, m
, callback
,
601 link_netlink_destroy_callback
, link
, 0, __func__
);
603 return log_error_errno(r
, "Could not send rtnetlink message: %m");
607 r
= routing_policy_rule_add(link
->manager
, rule
->family
, &rule
->from
, rule
->from_prefixlen
, &rule
->to
,
608 rule
->to_prefixlen
, rule
->tos
, rule
->fwmark
, rule
->table
, rule
->iif
, rule
->oif
, rule
->protocol
, &rule
->sport
, &rule
->dport
, NULL
);
610 return log_error_errno(r
, "Could not add rule: %m");
615 static int parse_fwmark_fwmask(const char *s
, uint32_t *fwmark
, uint32_t *fwmask
) {
616 _cleanup_free_
char *f
= NULL
;
630 r
= safe_atou32(f
, fwmark
);
632 return log_error_errno(r
, "Failed to parse RPDB rule firewall mark, ignoring: %s", f
);
635 r
= safe_atou32(p
, fwmask
);
637 return log_error_errno(r
, "Failed to parse RPDB rule mask, ignoring: %s", f
);
643 int config_parse_routing_policy_rule_tos(
645 const char *filename
,
648 unsigned section_line
,
655 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*n
= NULL
;
656 Network
*network
= userdata
;
665 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
669 r
= safe_atou8(rvalue
, &n
->tos
);
671 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule tos, ignoring: %s", rvalue
);
680 int config_parse_routing_policy_rule_priority(
682 const char *filename
,
685 unsigned section_line
,
692 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*n
= NULL
;
693 Network
*network
= userdata
;
702 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
706 r
= safe_atou32(rvalue
, &n
->priority
);
708 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule priority, ignoring: %s", rvalue
);
717 int config_parse_routing_policy_rule_table(
719 const char *filename
,
722 unsigned section_line
,
729 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*n
= NULL
;
730 Network
*network
= userdata
;
739 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
743 r
= safe_atou32(rvalue
, &n
->table
);
745 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule table, ignoring: %s", rvalue
);
754 int config_parse_routing_policy_rule_fwmark_mask(
756 const char *filename
,
759 unsigned section_line
,
766 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*n
= NULL
;
767 Network
*network
= userdata
;
776 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
780 r
= parse_fwmark_fwmask(rvalue
, &n
->fwmark
, &n
->fwmask
);
782 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue
);
791 int config_parse_routing_policy_rule_prefix(
793 const char *filename
,
796 unsigned section_line
,
803 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*n
= NULL
;
804 Network
*network
= userdata
;
805 union in_addr_union buffer
;
815 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
819 r
= in_addr_prefix_from_string(rvalue
, AF_INET
, &buffer
, &prefixlen
);
821 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, &buffer
, &prefixlen
);
823 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue
);
827 n
->family
= AF_INET6
;
831 if (streq(lvalue
, "To")) {
833 n
->to_prefixlen
= prefixlen
;
836 n
->from_prefixlen
= prefixlen
;
844 int config_parse_routing_policy_rule_device(
846 const char *filename
,
849 unsigned section_line
,
856 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*n
= NULL
;
857 Network
*network
= userdata
;
866 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
870 if (!ifname_valid(rvalue
)) {
871 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse '%s' interface name, ignoring: %s", lvalue
, rvalue
);
875 if (streq(lvalue
, "IncomingInterface")) {
876 r
= free_and_strdup(&n
->iif
, rvalue
);
880 r
= free_and_strdup(&n
->oif
, rvalue
);
890 int config_parse_routing_policy_rule_port_range(
892 const char *filename
,
895 unsigned section_line
,
901 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*n
= NULL
;
902 Network
*network
= userdata
;
912 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
916 r
= parse_ip_port_range(rvalue
, &low
, &high
);
918 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse routing policy rule port range '%s'", rvalue
);
922 if (streq(lvalue
, "SourcePort")) {
923 n
->sport
.start
= low
;
926 n
->dport
.start
= low
;
935 int config_parse_routing_policy_rule_protocol(
937 const char *filename
,
940 unsigned section_line
,
947 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*n
= NULL
;
948 Network
*network
= userdata
;
957 r
= routing_policy_rule_new_static(network
, filename
, section_line
, &n
);
961 r
= ip_protocol_from_name(rvalue
);
963 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse routing policy rule protocol, ignoring: %s", rvalue
);
967 if (!IN_SET(r
, IPPROTO_TCP
, IPPROTO_UDP
, IPPROTO_SCTP
)) {
968 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid protocol '%s'. Protocol should be tcp/udp/sctp, ignoring", rvalue
);
979 static int routing_policy_rule_read_full_file(const char *state_file
, char **ret
) {
980 _cleanup_free_
char *s
= NULL
;
986 r
= read_full_file(state_file
, &s
, &size
);
999 int routing_policy_serialize_rules(Set
*rules
, FILE *f
) {
1000 RoutingPolicyRule
*rule
= NULL
;
1006 SET_FOREACH(rule
, rules
, i
) {
1007 _cleanup_free_
char *from_str
= NULL
, *to_str
= NULL
;
1012 if (!in_addr_is_null(rule
->family
, &rule
->from
)) {
1013 r
= in_addr_to_string(rule
->family
, &rule
->from
, &from_str
);
1017 fprintf(f
, "from=%s/%hhu",
1018 from_str
, rule
->from_prefixlen
);
1022 if (!in_addr_is_null(rule
->family
, &rule
->to
)) {
1023 r
= in_addr_to_string(rule
->family
, &rule
->to
, &to_str
);
1027 fprintf(f
, "%sto=%s/%hhu",
1029 to_str
, rule
->to_prefixlen
);
1033 if (rule
->tos
!= 0) {
1034 fprintf(f
, "%stos=%hhu",
1040 if (rule
->fwmark
!= 0) {
1041 fprintf(f
, "%sfwmark=%"PRIu32
"/%"PRIu32
,
1043 rule
->fwmark
, rule
->fwmask
);
1048 fprintf(f
, "%siif=%s",
1055 fprintf(f
, "%soif=%s",
1061 if (rule
->protocol
!= 0) {
1062 fprintf(f
, "%sprotocol=%hhu",
1068 if (rule
->sport
.start
!= 0 || rule
->sport
.end
!= 0) {
1069 fprintf(f
, "%ssourcesport=%"PRIu16
"-%"PRIu16
,
1071 rule
->sport
.start
, rule
->sport
.end
);
1075 if (rule
->dport
.start
!= 0 || rule
->dport
.end
!= 0) {
1076 fprintf(f
, "%sdestinationport=%"PRIu16
"-%"PRIu16
,
1078 rule
->dport
.start
, rule
->dport
.end
);
1082 fprintf(f
, "%stable=%"PRIu32
"\n",
1090 int routing_policy_load_rules(const char *state_file
, Set
**rules
) {
1091 _cleanup_strv_free_
char **l
= NULL
;
1092 _cleanup_free_
char *data
= NULL
;
1093 uint16_t low
= 0, high
= 0;
1101 r
= routing_policy_rule_read_full_file(state_file
, &data
);
1105 l
= strv_split_newlines(data
);
1109 r
= set_ensure_allocated(rules
, &routing_policy_rule_hash_ops
);
1113 STRV_FOREACH(i
, l
) {
1114 _cleanup_(routing_policy_rule_freep
) RoutingPolicyRule
*rule
= NULL
;
1116 p
= startswith(*i
, "RULE=");
1120 r
= routing_policy_rule_new(&rule
);
1125 _cleanup_free_
char *word
= NULL
, *a
= NULL
, *b
= NULL
;
1126 union in_addr_union buffer
;
1129 r
= extract_first_word(&p
, &word
, NULL
, 0);
1135 r
= split_pair(word
, "=", &a
, &b
);
1139 if (STR_IN_SET(a
, "from", "to")) {
1141 r
= in_addr_prefix_from_string(b
, AF_INET
, &buffer
, &prefixlen
);
1143 r
= in_addr_prefix_from_string(b
, AF_INET6
, &buffer
, &prefixlen
);
1145 log_error_errno(r
, "RPDB rule prefix is invalid, ignoring assignment: %s", b
);
1149 rule
->family
= AF_INET6
;
1151 rule
->family
= AF_INET
;
1153 if (streq(a
, "to")) {
1155 rule
->to_prefixlen
= prefixlen
;
1157 rule
->from
= buffer
;
1158 rule
->from_prefixlen
= prefixlen
;
1160 } else if (streq(a
, "tos")) {
1161 r
= safe_atou8(b
, &rule
->tos
);
1163 log_error_errno(r
, "Failed to parse RPDB rule tos, ignoring: %s", b
);
1166 } else if (streq(a
, "table")) {
1167 r
= safe_atou32(b
, &rule
->table
);
1169 log_error_errno(r
, "Failed to parse RPDB rule table, ignoring: %s", b
);
1172 } else if (streq(a
, "fwmark")) {
1174 r
= parse_fwmark_fwmask(b
, &rule
->fwmark
, &rule
->fwmask
);
1176 log_error_errno(r
, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a
);
1179 } else if (streq(a
, "iif")) {
1181 if (free_and_strdup(&rule
->iif
, b
) < 0)
1184 } else if (streq(a
, "oif")) {
1186 if (free_and_strdup(&rule
->oif
, b
) < 0)
1188 } else if (streq(a
, "protocol")) {
1189 r
= safe_atou8(b
, &rule
->protocol
);
1191 log_error_errno(r
, "Failed to parse RPDB rule protocol, ignoring: %s", b
);
1194 } else if (streq(a
, "sourceport")) {
1196 r
= parse_ip_port_range(b
, &low
, &high
);
1198 log_error_errno(r
, "Invalid routing policy rule source port range, ignoring assignment:'%s'", b
);
1202 rule
->sport
.start
= low
;
1203 rule
->sport
.end
= high
;
1205 } else if (streq(a
, "destinationport")) {
1207 r
= parse_ip_port_range(b
, &low
, &high
);
1209 log_error_errno(r
, "Invalid routing policy rule destination port range, ignoring assignment:'%s'", b
);
1213 rule
->dport
.start
= low
;
1214 rule
->dport
.end
= high
;
1218 r
= set_put(*rules
, rule
);
1220 log_warning_errno(r
, "Failed to add RPDB rule to saved DB, ignoring: %s", p
);
1230 void routing_policy_rule_purge(Manager
*m
, Link
*link
) {
1231 RoutingPolicyRule
*rule
, *existing
;
1238 SET_FOREACH(rule
, m
->rules_saved
, i
) {
1239 existing
= set_get(m
->rules_foreign
, rule
);
1242 r
= routing_policy_rule_remove(rule
, link
, routing_policy_rule_remove_handler
);
1244 log_warning_errno(r
, "Could not remove routing policy rules: %m");
1248 link
->routing_policy_rule_remove_messages
++;