From: Slava Bacherikov Date: Thu, 4 Nov 2021 16:54:49 +0000 (+0200) Subject: network: Add SuppressInterfaceGroup= into routing policy X-Git-Tag: v250-rc1~256^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=af493fb742bece2cafcdbab9238c711ac9090c9f;p=thirdparty%2Fsystemd.git network: Add SuppressInterfaceGroup= into routing policy This adds SuppressInterfaceGroup= option in the [RoutingPolicyRule] section which has the same semantics as suppress_ifgroup in `ip rule` command. --- diff --git a/man/systemd.network.xml b/man/systemd.network.xml index dea600fbd6b..1bedc5b18bb 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1282,6 +1282,14 @@ Table=1234 unset. + + SuppressInterfaceGroup= + + Takes an integer in the range 0…2147483647 and rejects routing decisions that have + an interface with the same group id. It has the same meaning as + in ip rule. Defaults to unset. + + Type= diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 515a5b5bd95..525d0158bcc 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -171,6 +171,7 @@ RoutingPolicyRule.DestinationPort, config_parse_routing_policy_rule_po RoutingPolicyRule.InvertRule, config_parse_routing_policy_rule_invert, 0, 0 RoutingPolicyRule.Family, config_parse_routing_policy_rule_family, 0, 0 RoutingPolicyRule.User, config_parse_routing_policy_rule_uid_range, 0, 0 +RoutingPolicyRule.SuppressInterfaceGroup, config_parse_routing_policy_rule_suppress_ifgroup, 0, 0 RoutingPolicyRule.SuppressPrefixLength, config_parse_routing_policy_rule_suppress_prefixlen, 0, 0 RoutingPolicyRule.Type, config_parse_routing_policy_rule_type, 0, 0 Route.Gateway, config_parse_gateway, 0, 0 diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 35808b10f72..cbde514c98c 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -65,6 +65,7 @@ static int routing_policy_rule_new(RoutingPolicyRule **ret) { .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, + .suppress_ifgroup = -1, .protocol = RTPROT_UNSPEC, .type = FR_ACT_TO_TBL, }; @@ -165,6 +166,7 @@ void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash siphash24_compress(&rule->priority, sizeof(rule->priority), state); siphash24_compress(&rule->table, sizeof(rule->table), state); siphash24_compress(&rule->suppress_prefixlen, sizeof(rule->suppress_prefixlen), state); + siphash24_compress(&rule->suppress_ifgroup, sizeof(rule->suppress_ifgroup), state); siphash24_compress(&rule->ipproto, sizeof(rule->ipproto), state); siphash24_compress(&rule->protocol, sizeof(rule->protocol), state); @@ -240,6 +242,10 @@ int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPo if (r != 0) return r; + r = CMP(a->suppress_ifgroup, b->suppress_ifgroup); + if (r != 0) + return r; + r = CMP(a->ipproto, b->ipproto); if (r != 0) return r; @@ -534,6 +540,12 @@ static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule return log_link_error_errno(link, r, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m"); } + if (rule->suppress_ifgroup >= 0) { + r = sd_netlink_message_append_u32(m, FRA_SUPPRESS_IFGROUP, (uint32_t) rule->suppress_ifgroup); + if (r < 0) + return log_link_error_errno(link, r, "Could not append FRA_SUPPRESS_IFGROUP attribute: %m"); + } + r = sd_rtnl_message_routing_policy_rule_set_fib_type(m, rule->type); if (r < 0) return log_link_error_errno(link, r, "Could not append FIB rule type attribute: %m"); @@ -855,11 +867,11 @@ int request_process_routing_policy_rule(Request *req) { } static const RoutingPolicyRule kernel_rules[] = { - { .family = AF_INET, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, }, - { .family = AF_INET, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, }, - { .family = AF_INET, .priority_set = true, .priority = 32767, .table = RT_TABLE_DEFAULT, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, }, - { .family = AF_INET6, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, }, - { .family = AF_INET6, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, }, + { .family = AF_INET, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, + { .family = AF_INET, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, + { .family = AF_INET, .priority_set = true, .priority = 32767, .table = RT_TABLE_DEFAULT, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, + { .family = AF_INET6, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, + { .family = AF_INET6, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, }; static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule *rule) { @@ -1049,8 +1061,28 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man log_warning_errno(r, "rtnl: could not get FRA_SUPPRESS_PREFIXLEN attribute, ignoring: %m"); return 0; } - if (r >= 0) - tmp->suppress_prefixlen = (int) suppress_prefixlen; + if (r >= 0) { + /* kernel does not limit this value, but we do. */ + if (suppress_prefixlen > 128) { + log_warning("rtnl: received invalid FRA_SUPPRESS_PREFIXLEN attribute value %"PRIu32", ignoring.", suppress_prefixlen); + return 0; + } + tmp->suppress_prefixlen = (int32_t) suppress_prefixlen; + } + + uint32_t suppress_ifgroup; + r = sd_netlink_message_read_u32(message, FRA_SUPPRESS_IFGROUP, &suppress_ifgroup); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_SUPPRESS_IFGROUP attribute, ignoring: %m"); + return 0; + } + if (r >= 0) { + if (suppress_ifgroup > INT32_MAX) { + log_warning("rtnl: received invalid FRA_SUPPRESS_IFGROUP attribute value %"PRIu32", ignoring.", suppress_ifgroup); + return 0; + } + tmp->suppress_ifgroup = (int32_t) suppress_ifgroup; + } if (adjust_protocol) /* As .network files does not have setting to specify protocol, we can assume the @@ -1622,6 +1654,54 @@ int config_parse_routing_policy_rule_suppress_prefixlen( return 0; } +int config_parse_routing_policy_rule_suppress_ifgroup( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + int32_t suppress_ifgroup; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return log_oom(); + + if (isempty(rvalue)) { + n->suppress_ifgroup = -1; + return 0; + } + + r = safe_atoi32(rvalue, &suppress_ifgroup); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse SuppressInterfaceGroup=, ignoring assignment: %s", rvalue); + return 0; + } + if (suppress_ifgroup < 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Value of SuppressInterfaceGroup= must be in the range 0…2147483647, ignoring assignment: %s", rvalue); + return 0; + } + n->suppress_ifgroup = suppress_ifgroup; + TAKE_PTR(n); + return 0; +} + int config_parse_routing_policy_rule_type( const char *unit, const char *filename, diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 89f49fcb86c..ac65fe8af48 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -51,6 +51,7 @@ typedef struct RoutingPolicyRule { struct fib_rule_uid_range uid_range; int suppress_prefixlen; + int32_t suppress_ifgroup; } RoutingPolicyRule; RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule); @@ -88,4 +89,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_invert); CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_family); CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_uid_range); CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_suppress_prefixlen); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_suppress_ifgroup); CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_type); diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 26ab3931e07..5b5a4f8c60e 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -315,6 +315,7 @@ IPProtocol= InvertRule= Family= SuppressPrefixLength= +SuppressInterfaceGroup= User= Type= [IPv6SendRA] diff --git a/test/fuzz/fuzz-unit-file/directives-all.service b/test/fuzz/fuzz-unit-file/directives-all.service index 37a68708f70..c038ed87072 100644 --- a/test/fuzz/fuzz-unit-file/directives-all.service +++ b/test/fuzz/fuzz-unit-file/directives-all.service @@ -561,6 +561,7 @@ Scope= SendHostname= Source= SuppressPrefixLength= +SuppressInterfaceGroup= TCP6SegmentationOffload= TCPSegmentationOffload= TOS=