diff --git a/src/network/meson.build b/src/network/meson.build index 805007782c..5cd7613168 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -273,11 +273,6 @@ if conf.get('ENABLE_NETWORKD') == 1 [threads], '', '', [], network_include_dir], - [['src/network/test-routing-policy-rule.c'], - [libnetworkd_core, - libsystemd_network], - [], '', '', [], network_include_dir], - [['src/network/test-network-tables.c', test_tables_h], [libnetworkd_core, diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 7675f266e5..56ae6939a3 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1973,37 +1973,51 @@ static int link_enter_join_netdev(Link *link) { } static int link_drop_foreign_config(Link *link) { - int r; + int k, r; + + assert(link); + assert(link->manager); r = link_drop_foreign_addresses(link); - if (r < 0) - return r; - r = link_drop_foreign_neighbors(link); - if (r < 0) - return r; + k = link_drop_foreign_neighbors(link); + if (k < 0 && r >= 0) + r = k; - return link_drop_foreign_routes(link); + k = link_drop_foreign_routes(link); + if (k < 0 && r >= 0) + r = k; + + k = manager_drop_foreign_routing_policy_rules(link->manager); + if (k < 0 && r >= 0) + r = k; + + return r; } static int link_drop_config(Link *link) { - int r; + int k, r; + + assert(link); + assert(link->manager); r = link_drop_addresses(link); - if (r < 0) - return r; - r = link_drop_neighbors(link); - if (r < 0) - return r; + k = link_drop_neighbors(link); + if (k < 0 && r >= 0) + r = k; - r = link_drop_routes(link); - if (r < 0) - return r; + k = link_drop_routes(link); + if (k < 0 && r >= 0) + r = k; + + k = manager_drop_routing_policy_rules(link->manager, link); + if (k < 0 && r >= 0) + r = k; ndisc_flush(link); - return 0; + return r; } int link_configure(Link *link) { diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 4894d235b0..f775a3398a 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -707,10 +707,6 @@ static int manager_save(Manager *m) { ordered_set_print(f, "DOMAINS=", search_domains); ordered_set_print(f, "ROUTE_DOMAINS=", route_domains); - r = routing_policy_serialize_rules(m->rules, f); - if (r < 0) - goto fail; - r = fflush_and_check(f); if (r < 0) goto fail; @@ -851,8 +847,6 @@ int manager_new(Manager **ret) { m->duid.type = DUID_TYPE_EN; - (void) routing_policy_load_rules(m->state_file, &m->rules_saved); - *ret = TAKE_PTR(m); return 0; @@ -887,7 +881,6 @@ void manager_free(Manager *m) { * So, it is necessary to set NULL after the sets are freed. */ m->rules = set_free(m->rules); m->rules_foreign = set_free(m->rules_foreign); - set_free(m->rules_saved); sd_netlink_unref(m->rtnl); sd_netlink_unref(m->genl); diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 25fb080dc9..78ba2b0945 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -60,7 +60,6 @@ struct Manager { Set *rules; Set *rules_foreign; - Set *rules_saved; /* Manager stores routes without RTA_OIF attribute. */ Set *routes; diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 8c9565bda9..1f1e3e5b76 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -66,6 +66,7 @@ static int routing_policy_rule_new(RoutingPolicyRule **ret) { .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, + .protocol = RTPROT_UNSPEC, .type = FR_ACT_TO_TBL, }; @@ -99,6 +100,7 @@ static int routing_policy_rule_new_static(Network *network, const char *filename rule->network = network; rule->section = TAKE_PTR(n); + rule->protocol = RTPROT_STATIC; r = hashmap_ensure_allocated(&network->rules_by_section, &network_config_hash_ops); if (r < 0) @@ -144,6 +146,7 @@ static int routing_policy_rule_copy(RoutingPolicyRule *dest, RoutingPolicyRule * dest->table = src->table; dest->iif = TAKE_PTR(iif); dest->oif = TAKE_PTR(oif); + dest->ipproto = src->ipproto; dest->protocol = src->protocol; dest->sport = src->sport; dest->dport = src->dport; @@ -177,6 +180,7 @@ static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash24_compress(&rule->table, sizeof(rule->table), state); siphash24_compress(&rule->suppress_prefixlen, sizeof(rule->suppress_prefixlen), state); + siphash24_compress(&rule->ipproto, sizeof(rule->ipproto), state); siphash24_compress(&rule->protocol, sizeof(rule->protocol), state); siphash24_compress(&rule->sport, sizeof(rule->sport), state); siphash24_compress(&rule->dport, sizeof(rule->dport), state); @@ -250,6 +254,10 @@ static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const Ro if (r != 0) return r; + r = CMP(a->ipproto, b->ipproto); + if (r != 0) + return r; + r = CMP(a->protocol, b->protocol); if (r != 0) return r; @@ -458,10 +466,14 @@ static int routing_policy_rule_set_netlink_message(RoutingPolicyRule *rule, sd_n return log_link_error_errno(link, r, "Could not append FRA_OIFNAME attribute: %m"); } - r = sd_netlink_message_append_u8(m, FRA_IP_PROTO, rule->protocol); + r = sd_netlink_message_append_u8(m, FRA_IP_PROTO, rule->ipproto); if (r < 0) return log_link_error_errno(link, r, "Could not append FRA_IP_PROTO attribute: %m"); + r = sd_netlink_message_append_u8(m, FRA_PROTOCOL, rule->protocol); + if (r < 0) + return log_link_error_errno(link, r, "Could not append FRA_PROTOCOL attribute: %m"); + if (rule->sport.start != 0 || rule->sport.end != 0) { r = sd_netlink_message_append_data(m, FRA_SPORT_RANGE, &rule->sport, sizeof(rule->sport)); if (r < 0) @@ -628,7 +640,7 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) { return 0; } -static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) { +static bool links_have_routing_policy_rule(const Manager *m, const RoutingPolicyRule *rule, const Link *except) { Link *link; assert(m); @@ -637,6 +649,9 @@ static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule HASHMAP_FOREACH(link, m->links) { RoutingPolicyRule *link_rule; + if (link == except) + continue; + if (!link->network) continue; @@ -648,34 +663,29 @@ static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule return false; } -static void routing_policy_rule_purge(Manager *m) { +int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except) { RoutingPolicyRule *rule; - int r; + int k, r = 0; + Set *rules; assert(m); - SET_FOREACH(rule, m->rules_saved) { - RoutingPolicyRule *existing; - - existing = set_get(m->rules_foreign, rule); - if (!existing) - continue; /* Saved rule does not exist anymore. */ - - if (manager_links_have_routing_policy_rule(m, existing)) - continue; /* Existing links have the saved rule. */ - - /* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it - * later when it is requested. */ - - r = routing_policy_rule_remove(existing, m); - if (r < 0) { - log_warning_errno(r, "Could not remove routing policy rules: %m"); + rules = foreign ? m->rules_foreign : m->rules; + SET_FOREACH(rule, rules) { + /* Do not touch rules managed by kernel. */ + if (rule->protocol == RTPROT_KERNEL) continue; - } - assert_se(set_remove(m->rules_foreign, existing) == existing); - routing_policy_rule_free(existing); + /* The rule will be configured later, or already configured by a link. */ + if (links_have_routing_policy_rule(m, rule, except)) + continue; + + k = routing_policy_rule_remove(rule, m); + if (k < 0 && r >= 0) + r = k; } + + return r; } int link_set_routing_policy_rules(Link *link) { @@ -712,7 +722,6 @@ int link_set_routing_policy_rules(Link *link) { return log_link_warning_errno(link, r, "Could not set routing policy rule: %m"); } - routing_policy_rule_purge(link->manager); if (link->routing_policy_rule_messages == 0) link->routing_policy_rules_configured = true; else { @@ -723,10 +732,34 @@ int link_set_routing_policy_rules(Link *link) { return 0; } +static const RoutingPolicyRule kernel_rules[] = { + { .family = AF_INET, .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 = 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 = 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 = 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 = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, }, +}; + +static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule *rule) { + assert(rule); + + if (rule->l3mdev > 0) + /* Currently, [RoutingPolicyRule] does not explicitly set FRA_L3MDEV. So, if the flag + * is set, it is safe to treat the rule as created by kernel. */ + return true; + + for (size_t i = 0; i < ELEMENTSOF(kernel_rules); i++) + if (routing_policy_rule_equal(rule, &kernel_rules[i])) + return true; + + return false; +} + int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL; RoutingPolicyRule *rule = NULL; const char *iif = NULL, *oif = NULL; + bool adjust_protocol = false; uint32_t suppress_prefixlen; unsigned flags; uint16_t type; @@ -852,12 +885,29 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man if (r < 0) return log_oom(); - r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->protocol); + r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->ipproto); if (r < 0 && r != -ENODATA) { log_warning_errno(r, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m"); return 0; } + r = sd_netlink_message_read_u8(message, FRA_PROTOCOL, &tmp->protocol); + if (r == -ENODATA) + /* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended. + * When the received message does not have FRA_PROTOCOL, then we need to adjust the + * protocol of the rule later. */ + adjust_protocol = true; + else if (r < 0) { + log_warning_errno(r, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u8(message, FRA_L3MDEV, &tmp->l3mdev); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_L3MDEV attribute, ignoring: %m"); + return 0; + } + r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(tmp->sport), &tmp->sport); if (r < 0 && r != -ENODATA) { log_warning_errno(r, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m"); @@ -884,6 +934,11 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man if (r >= 0) tmp->suppress_prefixlen = (int) suppress_prefixlen; + if (adjust_protocol) + /* As .network files does not have setting to specify protocol, we can assume the + * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */ + tmp->protocol = routing_policy_rule_is_created_by_kernel(tmp) ? RTPROT_KERNEL : RTPROT_STATIC; + (void) routing_policy_rule_get(m, tmp, &rule); switch (type) { @@ -1271,7 +1326,7 @@ int config_parse_routing_policy_rule_ip_protocol( return 0; } - n->protocol = r; + n->ipproto = r; n = NULL; @@ -1497,6 +1552,12 @@ static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { if (rule->family == AF_UNSPEC && rule->address_family == ADDRESS_FAMILY_NO) rule->family = AF_INET; + /* Currently, [RoutingPolicyRule] does not have a setting to set FRA_L3MDEV flag. Please also + * update routing_policy_rule_is_created_by_kernel() when a new setting which sets the flag is + * added in the future. */ + if (rule->l3mdev > 0) + assert_not_reached("FRA_L3MDEV flag should not be configured."); + return 0; } @@ -1509,342 +1570,3 @@ void network_drop_invalid_routing_policy_rules(Network *network) { if (routing_policy_rule_section_verify(rule) < 0) routing_policy_rule_free(rule); } - -int routing_policy_serialize_rules(Set *rules, FILE *f) { - RoutingPolicyRule *rule; - int r; - - assert(f); - - SET_FOREACH(rule, rules) { - const char *family_str; - bool space = false; - - fputs("RULE=", f); - - family_str = af_to_name(rule->family); - if (family_str) { - fprintf(f, "family=%s", - family_str); - space = true; - } - - if (!in_addr_is_null(rule->family, &rule->from)) { - _cleanup_free_ char *str = NULL; - - r = in_addr_to_string(rule->family, &rule->from, &str); - if (r < 0) - return r; - - fprintf(f, "%sfrom=%s/%hhu", - space ? " " : "", - str, rule->from_prefixlen); - space = true; - } - - if (!in_addr_is_null(rule->family, &rule->to)) { - _cleanup_free_ char *str = NULL; - - r = in_addr_to_string(rule->family, &rule->to, &str); - if (r < 0) - return r; - - fprintf(f, "%sto=%s/%hhu", - space ? " " : "", - str, rule->to_prefixlen); - space = true; - } - - if (rule->tos != 0) { - fprintf(f, "%stos=%hhu", - space ? " " : "", - rule->tos); - space = true; - } - - if (rule->type != 0) { - fprintf(f, "%stype=%hhu", - space ? " " : "", - rule->type); - space = true; - } - - if (rule->priority != 0) { - fprintf(f, "%spriority=%"PRIu32, - space ? " " : "", - rule->priority); - space = true; - } - - if (rule->fwmark != 0) { - fprintf(f, "%sfwmark=%"PRIu32, - space ? " " : "", - rule->fwmark); - if (rule->fwmask != UINT32_MAX) - fprintf(f, "/%"PRIu32, rule->fwmask); - space = true; - } - - if (rule->iif) { - fprintf(f, "%siif=%s", - space ? " " : "", - rule->iif); - space = true; - } - - if (rule->oif) { - fprintf(f, "%soif=%s", - space ? " " : "", - rule->oif); - space = true; - } - - if (rule->protocol != 0) { - fprintf(f, "%sprotocol=%hhu", - space ? " " : "", - rule->protocol); - space = true; - } - - if (rule->sport.start != 0 || rule->sport.end != 0) { - fprintf(f, "%ssourcesport=%"PRIu16"-%"PRIu16, - space ? " " : "", - rule->sport.start, rule->sport.end); - space = true; - } - - if (rule->dport.start != 0 || rule->dport.end != 0) { - fprintf(f, "%sdestinationport=%"PRIu16"-%"PRIu16, - space ? " " : "", - rule->dport.start, rule->dport.end); - space = true; - } - - if (rule->uid_range.start != UID_INVALID && rule->uid_range.end != UID_INVALID) { - assert_cc(sizeof(uid_t) == sizeof(uint32_t)); - fprintf(f, "%suidrange="UID_FMT"-"UID_FMT, - space ? " " : "", - rule->uid_range.start, rule->uid_range.end); - space = true; - } - - if (rule->suppress_prefixlen >= 0) { - fprintf(f, "%ssuppress_prefixlen=%d", - space ? " " : "", - rule->suppress_prefixlen); - space = true; - } - - fprintf(f, "%sinvert_rule=%s table=%"PRIu32"\n", - space ? " " : "", - yes_no(rule->invert_rule), - rule->table); - } - - return 0; -} - -static int routing_policy_rule_read_full_file(const char *state_file, char ***ret) { - _cleanup_strv_free_ char **lines = NULL; - _cleanup_free_ char *s = NULL; - int r; - - assert(state_file); - - r = read_full_file(state_file, &s, NULL); - if (r == -ENOENT) { - *ret = NULL; - return 0; - } - if (r < 0) - return r; - - lines = strv_split_newlines(s); - if (!lines) - return -ENOMEM; - - *ret = TAKE_PTR(lines); - return 0; -} - -int routing_policy_load_rules(const char *state_file, Set **rules) { - _cleanup_strv_free_ char **data = NULL; - char **i; - int r; - - assert(state_file); - assert(rules); - - r = routing_policy_rule_read_full_file(state_file, &data); - if (r < 0) - return log_warning_errno(r, "Failed to read %s, ignoring: %m", state_file); - - STRV_FOREACH(i, data) { - _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; - const char *p; - - p = startswith(*i, "RULE="); - if (!p) - continue; - - r = routing_policy_rule_new(&rule); - if (r < 0) - return log_oom(); - - for (;;) { - _cleanup_free_ char *a = NULL; - char *b; - - r = extract_first_word(&p, &a, NULL, 0); - if (r < 0) - return log_oom(); - if (r == 0) - break; - - b = strchr(a, '='); - if (!b) { - log_warning_errno(r, "Failed to parse RPDB rule, ignoring: %s", a); - continue; - } - *b++ = '\0'; - - if (streq(a, "family")) { - r = af_from_name(b); - if (r < 0) { - log_warning_errno(r, "Failed to parse RPDB rule family, ignoring: %s", b); - continue; - } - if (rule->family != AF_UNSPEC && rule->family != r) { - log_warning("RPDB rule family is already specified, ignoring assignment: %s", b); - continue; - } - rule->family = r; - } else if (STR_IN_SET(a, "from", "to")) { - union in_addr_union *buffer; - uint8_t *prefixlen; - - if (streq(a, "to")) { - buffer = &rule->to; - prefixlen = &rule->to_prefixlen; - } else { - buffer = &rule->from; - prefixlen = &rule->from_prefixlen; - } - - if (rule->family == AF_UNSPEC) - r = in_addr_prefix_from_string_auto(b, &rule->family, buffer, prefixlen); - else - r = in_addr_prefix_from_string(b, rule->family, buffer, prefixlen); - if (r < 0) { - log_warning_errno(r, "RPDB rule prefix is invalid, ignoring assignment: %s", b); - continue; - } - } else if (streq(a, "tos")) { - r = safe_atou8(b, &rule->tos); - if (r < 0) { - log_warning_errno(r, "Failed to parse RPDB rule TOS, ignoring: %s", b); - continue; - } - } else if (streq(a, "type")) { - r = safe_atou8(b, &rule->type); - if (r < 0) { - log_warning_errno(r, "Failed to parse RPDB rule type, ignoring: %s", b); - continue; - } - } else if (streq(a, "table")) { - r = safe_atou32(b, &rule->table); - if (r < 0) { - log_warning_errno(r, "Failed to parse RPDB rule table, ignoring: %s", b); - continue; - } - } else if (streq(a, "priority")) { - r = safe_atou32(b, &rule->priority); - if (r < 0) { - log_warning_errno(r, "Failed to parse RPDB rule priority, ignoring: %s", b); - continue; - } - } else if (streq(a, "fwmark")) { - r = parse_fwmark_fwmask(b, &rule->fwmark, &rule->fwmask); - if (r < 0) { - log_warning_errno(r, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a); - continue; - } - } else if (streq(a, "iif")) { - if (free_and_strdup(&rule->iif, b) < 0) - return log_oom(); - - } else if (streq(a, "oif")) { - - if (free_and_strdup(&rule->oif, b) < 0) - return log_oom(); - } else if (streq(a, "protocol")) { - r = safe_atou8(b, &rule->protocol); - if (r < 0) { - log_warning_errno(r, "Failed to parse RPDB rule protocol, ignoring: %s", b); - continue; - } - } else if (streq(a, "sourceport")) { - uint16_t low, high; - - r = parse_ip_port_range(b, &low, &high); - if (r < 0) { - log_warning_errno(r, "Invalid routing policy rule source port range, ignoring assignment: '%s'", b); - continue; - } - - rule->sport.start = low; - rule->sport.end = high; - } else if (streq(a, "destinationport")) { - uint16_t low, high; - - r = parse_ip_port_range(b, &low, &high); - if (r < 0) { - log_warning_errno(r, "Invalid routing policy rule destination port range, ignoring assignment: '%s'", b); - continue; - } - - rule->dport.start = low; - rule->dport.end = high; - } else if (streq(a, "uidrange")) { - uid_t lower, upper; - - r = parse_uid_range(b, &lower, &upper); - if (r < 0) { - log_warning_errno(r, "Invalid routing policy rule uid range, ignoring assignment: '%s'", b); - continue; - } - - rule->uid_range.start = lower; - rule->uid_range.end = upper; - } else if (streq(a, "suppress_prefixlen")) { - r = parse_ip_prefix_length(b, &rule->suppress_prefixlen); - if (r == -ERANGE) { - log_warning_errno(r, "Prefix length outside of valid range 0-128, ignoring: %s", b); - continue; - } - if (r < 0) { - log_warning_errno(r, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", b); - continue; - } - } else if (streq(a, "invert_rule")) { - r = parse_boolean(b); - if (r < 0) { - log_warning_errno(r, "Failed to parse RPDB rule invert_rule, ignoring: %s", b); - continue; - } - rule->invert_rule = r; - } else - log_warning("Unknown RPDB rule, ignoring: %s", a); - } - - r = set_ensure_put(rules, &routing_policy_rule_hash_ops, rule); - if (r < 0) { - log_warning_errno(r, "Failed to add RPDB rule to saved DB, ignoring: %s", *i); - continue; - } - if (r > 0) - rule = NULL; - } - - return 0; -} diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 1b574452e2..dbda8c51b0 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -24,9 +24,11 @@ typedef struct RoutingPolicyRule { uint8_t tos; uint8_t type; - uint8_t protocol; + uint8_t ipproto; /* FRA_IP_PROTO */ + uint8_t protocol; /* FRA_PROTOCOL */ uint8_t to_prefixlen; uint8_t from_prefixlen; + uint8_t l3mdev; /* FRA_L3MDEV */ uint32_t table; uint32_t fwmark; @@ -56,9 +58,13 @@ void network_drop_invalid_routing_policy_rules(Network *network); int link_set_routing_policy_rules(Link *link); int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); - -int routing_policy_serialize_rules(Set *rules, FILE *f); -int routing_policy_load_rules(const char *state_file, Set **rules); +int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except); +static inline int manager_drop_foreign_routing_policy_rules(Manager *m) { + return manager_drop_routing_policy_rules_internal(m, true, NULL); +} +static inline int manager_drop_routing_policy_rules(Manager *m, const Link *except) { + return manager_drop_routing_policy_rules_internal(m, false, except); +} CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_tos); CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_table); diff --git a/src/network/test-routing-policy-rule.c b/src/network/test-routing-policy-rule.c deleted file mode 100644 index 4fed4fe8d9..0000000000 --- a/src/network/test-routing-policy-rule.c +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "fd-util.h" -#include "fileio.h" -#include "networkd-routing-policy-rule.h" -#include "string-util.h" -#include "tests.h" -#include "tmpfile-util.h" - -static void test_rule_serialization(const char *title, const char *ruleset, const char *expected) { - char pattern[] = "/tmp/systemd-test-routing-policy-rule.XXXXXX", - pattern2[] = "/tmp/systemd-test-routing-policy-rule.XXXXXX", - pattern3[] = "/tmp/systemd-test-routing-policy-rule.XXXXXX"; - const char *cmd; - int fd, fd2, fd3; - _cleanup_fclose_ FILE *f = NULL, *f2 = NULL, *f3 = NULL; - Set *rules = NULL; - _cleanup_free_ char *buf = NULL; - size_t buf_size; - - log_info("========== %s ==========", title); - log_info("put:\n%s\n", ruleset); - - fd = mkostemp_safe(pattern); - assert_se(fd >= 0); - assert_se(f = fdopen(fd, "a+")); - assert_se(write_string_stream(f, ruleset, 0) == 0); - - assert_se(routing_policy_load_rules(pattern, &rules) == 0); - - fd2 = mkostemp_safe(pattern2); - assert_se(fd2 >= 0); - assert_se(f2 = fdopen(fd2, "a+")); - - assert_se(routing_policy_serialize_rules(rules, f2) == 0); - assert_se(fflush_and_check(f2) == 0); - - assert_se(read_full_file(pattern2, &buf, &buf_size) == 0); - - log_info("got:\n%s", buf); - - fd3 = mkostemp_safe(pattern3); - assert_se(fd3 >= 0); - assert_se(f3 = fdopen(fd3, "w")); - assert_se(write_string_stream(f3, expected ?: ruleset, 0) == 0); - - cmd = strjoina("diff -u ", pattern3, " ", pattern2); - log_info("$ %s", cmd); - assert_se(system(cmd) == 0); - - set_free(rules); -} - -int main(int argc, char **argv) { - _cleanup_free_ char *p = NULL; - - test_setup_logging(LOG_DEBUG); - - test_rule_serialization("basic parsing", - "RULE=family=AF_INET from=1.2.3.4/32 to=2.3.4.5/32 tos=5 type=1 priority=10 fwmark=1/2 invert_rule=yes table=10", NULL); - - test_rule_serialization("ignored values", - "RULE=something=to=ignore from=1.2.3.4/32 from=1.2.3.4/32" - " \t to=2.3.4.5/24 to=2.3.4.5/32 tos=5 type=1 fwmark=2 fwmark=1 table=10 table=20", - "RULE=family=AF_INET from=1.2.3.4/32 to=2.3.4.5/32 tos=5 type=1 fwmark=1 invert_rule=no table=20"); - - test_rule_serialization("ipv6", - "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 invert_rule=yes table=6", NULL); - - assert_se(asprintf(&p, "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 invert_rule=no table=%d", RT_TABLE_MAIN) >= 0); - test_rule_serialization("default table", - "RULE=from=1::2/64 to=2::3/64", p); - - test_rule_serialization("incoming interface", - "RULE=from=1::2/64 to=2::3/64 table=1 iif=lo", - "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 iif=lo invert_rule=no table=1"); - - test_rule_serialization("outgoing interface", - "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 oif=eth0 invert_rule=no table=1", NULL); - - test_rule_serialization("freeing interface names", - "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 type=1 iif=e0 iif=e1 oif=e0 oif=e1 table=1", - "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 iif=e1 oif=e1 invert_rule=no table=1"); - - test_rule_serialization("ignoring invalid family", - "RULE=from=1::2/64 to=2::3/64 family=AF_UNSEPC family=AF_INET table=1", - "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 type=1 invert_rule=no table=1"); - - return 0; -} diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 1c4046d4f2..41d3e7036b 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3326,7 +3326,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities): output = check_output('ip rule list table 100') print(output) - self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100') + self.assertIn('0: from all to 8.8.8.8 lookup 100', output) class NetworkdLLDPTests(unittest.TestCase, Utilities): links = ['veth99']