From c0ec474675c7a0203628d803e86405a564e22657 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 14:17:27 +0900 Subject: [PATCH 001/138] network: move link_request_set_routing_policy() --- src/network/networkd-link.c | 37 +--------------------- src/network/networkd-routing-policy-rule.c | 35 ++++++++++++++++++++ src/network/networkd-routing-policy-rule.h | 2 ++ 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0cdd2b5121..685cbd34cf 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -925,41 +925,6 @@ static void link_enter_configured(Link *link) { link_dirty(link); } -static int link_request_set_routing_policy_rule(Link *link) { - RoutingPolicyRule *rule, *rrule = NULL; - int r; - - assert(link); - assert(link->network); - - link->routing_policy_rules_configured = false; - - LIST_FOREACH(rules, rule, link->network->rules) { - r = routing_policy_rule_get(link->manager, rule, &rrule); - if (r >= 0) { - if (r == 0) - (void) routing_policy_rule_make_local(link->manager, rrule); - continue; - } - - r = routing_policy_rule_configure(rule, link, NULL); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set routing policy rules: %m"); - if (r > 0) - link->routing_policy_rule_messages++; - } - - routing_policy_rule_purge(link->manager, link); - if (link->routing_policy_rule_messages == 0) - link->routing_policy_rules_configured = true; - else { - log_link_debug(link, "Setting routing policy rules"); - link_set_state(link, LINK_STATE_CONFIGURING); - } - - return 0; -} - static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -1066,7 +1031,7 @@ int link_request_set_routes(Link *link) { * the addresses now, let's not configure the routes either. */ return 0; - r = link_request_set_routing_policy_rule(link); + r = link_set_routing_policy_rules(link); if (r < 0) return r; diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 3b95ea76b0..9f356c6c24 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -609,6 +609,41 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl return 1; } +int link_set_routing_policy_rules(Link *link) { + RoutingPolicyRule *rule, *rrule = NULL; + int r; + + assert(link); + assert(link->network); + + link->routing_policy_rules_configured = false; + + LIST_FOREACH(rules, rule, link->network->rules) { + r = routing_policy_rule_get(link->manager, rule, &rrule); + if (r >= 0) { + if (r == 0) + (void) routing_policy_rule_make_local(link->manager, rrule); + continue; + } + + r = routing_policy_rule_configure(rule, link, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set routing policy rules: %m"); + if (r > 0) + link->routing_policy_rule_messages++; + } + + routing_policy_rule_purge(link->manager, link); + if (link->routing_policy_rule_messages == 0) + link->routing_policy_rules_configured = true; + else { + log_link_debug(link, "Setting routing policy rules"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { int r; diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index af954e8fb5..2168f87528 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -62,6 +62,8 @@ void routing_policy_rule_free(RoutingPolicyRule *rule); DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free); int routing_policy_rule_section_verify(RoutingPolicyRule *rule); +int link_set_routing_policy_rules(Link *link); + int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback); int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback); From 7532b88808fd54bb5a09a59f6c7ae19a0426d6e6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 14:28:21 +0900 Subject: [PATCH 002/138] network: make several functions static --- src/network/networkd-routing-policy-rule.c | 294 ++++++++++----------- src/network/networkd-routing-policy-rule.h | 5 - 2 files changed, 147 insertions(+), 152 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 9f356c6c24..e17151c8bf 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -37,6 +37,53 @@ int routing_policy_rule_new(RoutingPolicyRule **ret) { return 0; } +static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) { + _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + rule = hashmap_get(network->rules_by_section, n); + if (rule) { + *ret = TAKE_PTR(rule); + + return 0; + } + } + + r = routing_policy_rule_new(&rule); + if (r < 0) + return r; + + rule->network = network; + LIST_APPEND(rules, network->rules, rule); + network->n_rules++; + + if (filename) { + rule->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->rules_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->rules_by_section, rule->section, rule); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(rule); + + return 0; +} + void routing_policy_rule_free(RoutingPolicyRule *rule) { if (!rule) @@ -257,7 +304,7 @@ int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRu return -ENOENT; } -int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule) { +static int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule) { int r; assert(m); @@ -333,7 +380,7 @@ static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_messa return 1; } -int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback) { +static int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -380,7 +427,7 @@ int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink } r = netlink_call_async(link->manager->rtnl, NULL, m, - callback ?: routing_policy_rule_remove_handler, + routing_policy_rule_remove_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -390,53 +437,6 @@ int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink return 0; } -static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) { - _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; - _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; - int r; - - assert(network); - assert(ret); - assert(!!filename == (section_line > 0)); - - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; - - rule = hashmap_get(network->rules_by_section, n); - if (rule) { - *ret = TAKE_PTR(rule); - - return 0; - } - } - - r = routing_policy_rule_new(&rule); - if (r < 0) - return r; - - rule->network = network; - LIST_APPEND(rules, network->rules, rule); - network->n_rules++; - - if (filename) { - rule->section = TAKE_PTR(n); - - r = hashmap_ensure_allocated(&network->rules_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->rules_by_section, rule->section, rule); - if (r < 0) - return r; - } - - *ret = TAKE_PTR(rule); - - return 0; -} - static int routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -467,7 +467,7 @@ static int routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, return 1; } -int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback) { +static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -595,7 +595,7 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl rule->link = link; r = netlink_call_async(link->manager->rtnl, NULL, m, - callback ?: routing_policy_rule_handler, + routing_policy_rule_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -609,6 +609,56 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl return 1; } +static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) { + RoutingPolicyRule *link_rule; + Link *link; + + assert(m); + assert(rule); + + HASHMAP_FOREACH(link, m->links) { + if (!link->network) + continue; + + LIST_FOREACH(rules, link_rule, link->network->rules) + if (routing_policy_rule_compare_func(link_rule, rule) == 0) + return true; + } + + return false; +} + +static void routing_policy_rule_purge(Manager *m, Link *link) { + RoutingPolicyRule *rule, *existing; + int r; + + assert(m); + assert(link); + + SET_FOREACH(rule, m->rules_saved) { + 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, link); + if (r < 0) { + log_warning_errno(r, "Could not remove routing policy rules: %m"); + continue; + } + + link->routing_policy_rule_remove_messages++; + + assert_se(set_remove(m->rules_foreign, existing) == existing); + routing_policy_rule_free(existing); + } +} + int link_set_routing_policy_rules(Link *link) { RoutingPolicyRule *rule, *rrule = NULL; int r; @@ -626,7 +676,7 @@ int link_set_routing_policy_rules(Link *link) { continue; } - r = routing_policy_rule_configure(rule, link, NULL); + r = routing_policy_rule_configure(rule, link); if (r < 0) return log_link_warning_errno(link, r, "Could not set routing policy rules: %m"); if (r > 0) @@ -644,50 +694,6 @@ int link_set_routing_policy_rules(Link *link) { return 0; } -int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { - int r; - - if (section_is_invalid(rule->section)) - return -EINVAL; - - if ((rule->family == AF_INET && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) || - (rule->family == AF_INET6 && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4))) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: address family specified by Family= conflicts with the address " - "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.", - rule->section->filename, rule->section->line); - - if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6)) { - _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule6 = NULL; - - assert(rule->family == AF_UNSPEC); - - /* When Family=both, we need to copy the section, AF_INET and AF_INET6. */ - - r = routing_policy_rule_new_static(rule->network, NULL, 0, &rule6); - if (r < 0) - return r; - - r = routing_policy_rule_copy(rule6, rule); - if (r < 0) - return r; - - rule->family = AF_INET; - rule6->family = AF_INET6; - - TAKE_PTR(rule6); - } - - if (rule->family == AF_UNSPEC) { - if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) - rule->family = AF_INET6; - else - rule->family = AF_INET; - } - - return 0; -} - static int parse_fwmark_fwmask(const char *s, uint32_t *ret_fwmark, uint32_t *ret_fwmask) { _cleanup_free_ char *fwmark_str = NULL; uint32_t fwmark, fwmask = 0; @@ -1218,6 +1224,50 @@ int config_parse_routing_policy_rule_suppress_prefixlen( return 0; } +int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { + int r; + + if (section_is_invalid(rule->section)) + return -EINVAL; + + if ((rule->family == AF_INET && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) || + (rule->family == AF_INET6 && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4))) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: address family specified by Family= conflicts with the address " + "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.", + rule->section->filename, rule->section->line); + + if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6)) { + _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule6 = NULL; + + assert(rule->family == AF_UNSPEC); + + /* When Family=both, we need to copy the section, AF_INET and AF_INET6. */ + + r = routing_policy_rule_new_static(rule->network, NULL, 0, &rule6); + if (r < 0) + return r; + + r = routing_policy_rule_copy(rule6, rule); + if (r < 0) + return r; + + rule->family = AF_INET; + rule6->family = AF_INET6; + + TAKE_PTR(rule6); + } + + if (rule->family == AF_UNSPEC) { + if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) + rule->family = AF_INET6; + else + rule->family = AF_INET; + } + + return 0; +} + int routing_policy_serialize_rules(Set *rules, FILE *f) { RoutingPolicyRule *rule = NULL; int r; @@ -1539,53 +1589,3 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { return 0; } - -static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) { - RoutingPolicyRule *link_rule; - Link *link; - - assert(m); - assert(rule); - - HASHMAP_FOREACH(link, m->links) { - if (!link->network) - continue; - - LIST_FOREACH(rules, link_rule, link->network->rules) - if (routing_policy_rule_compare_func(link_rule, rule) == 0) - return true; - } - - return false; -} - -void routing_policy_rule_purge(Manager *m, Link *link) { - RoutingPolicyRule *rule, *existing; - int r; - - assert(m); - assert(link); - - SET_FOREACH(rule, m->rules_saved) { - 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, link, NULL); - if (r < 0) { - log_warning_errno(r, "Could not remove routing policy rules: %m"); - continue; - } - - link->routing_policy_rule_remove_messages++; - - assert_se(set_remove(m->rules_foreign, existing) == existing); - routing_policy_rule_free(existing); - } -} diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 2168f87528..4e8b191a16 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -64,15 +64,10 @@ int routing_policy_rule_section_verify(RoutingPolicyRule *rule); int link_set_routing_policy_rules(Link *link); -int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback); -int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback); - int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret); int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret); -int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule); int routing_policy_serialize_rules(Set *rules, FILE *f); int routing_policy_load_rules(const char *state_file, Set **rules); -void routing_policy_rule_purge(Manager *m, Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_tos); CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_table); From ddc9df3183042451138f5483337e62506b3a87b4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 14:41:01 +0900 Subject: [PATCH 003/138] network: drop routing_policy_rule_make_local() Its error handling was bogus... --- src/network/networkd-routing-policy-rule.c | 41 ++++++++-------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index e17151c8bf..c7ae18fee7 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -304,24 +304,6 @@ int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRu return -ENOENT; } -static int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule) { - int r; - - assert(m); - - if (set_contains(m->rules_foreign, rule)) { - set_remove(m->rules_foreign, rule); - - r = set_ensure_put(&m->rules, &routing_policy_rule_hash_ops, rule); - if (r < 0) - return r; - if (r == 0) - routing_policy_rule_free(rule); - } - - return -ENOENT; -} - static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPolicyRule *in, RoutingPolicyRule **ret) { _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; int r; @@ -660,7 +642,7 @@ static void routing_policy_rule_purge(Manager *m, Link *link) { } int link_set_routing_policy_rules(Link *link) { - RoutingPolicyRule *rule, *rrule = NULL; + RoutingPolicyRule *rule; int r; assert(link); @@ -669,18 +651,25 @@ int link_set_routing_policy_rules(Link *link) { link->routing_policy_rules_configured = false; LIST_FOREACH(rules, rule, link->network->rules) { - r = routing_policy_rule_get(link->manager, rule, &rrule); - if (r >= 0) { - if (r == 0) - (void) routing_policy_rule_make_local(link->manager, rrule); + RoutingPolicyRule *existing; + + r = routing_policy_rule_get(link->manager, rule, &existing); + if (r > 0) + continue; + if (r == 0) { + r = set_ensure_put(&link->manager->rules, &routing_policy_rule_hash_ops, existing); + if (r < 0) + return log_link_warning_errno(link, r, "Could not store existing routing policy rule: %m"); + + set_remove(link->manager->rules_foreign, existing); continue; } r = routing_policy_rule_configure(rule, link); if (r < 0) - return log_link_warning_errno(link, r, "Could not set routing policy rules: %m"); - if (r > 0) - link->routing_policy_rule_messages++; + return log_link_warning_errno(link, r, "Could not set routing policy rule: %m"); + + link->routing_policy_rule_messages++; } routing_policy_rule_purge(link->manager, link); From eb3445ce93c61d2efce0e6803d73e8f8b79f7082 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 14:42:56 +0900 Subject: [PATCH 004/138] network: reduce scope of variables --- src/network/networkd-routing-policy-rule.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index c7ae18fee7..c28c944140 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -611,13 +611,15 @@ static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule } static void routing_policy_rule_purge(Manager *m, Link *link) { - RoutingPolicyRule *rule, *existing; + RoutingPolicyRule *rule; int r; assert(m); assert(link); SET_FOREACH(rule, m->rules_saved) { + RoutingPolicyRule *existing; + existing = set_get(m->rules_foreign, rule); if (!existing) continue; /* Saved rule does not exist anymore. */ @@ -1258,13 +1260,12 @@ int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { } int routing_policy_serialize_rules(Set *rules, FILE *f) { - RoutingPolicyRule *rule = NULL; + RoutingPolicyRule *rule; int r; assert(f); SET_FOREACH(rule, rules) { - _cleanup_free_ char *from_str = NULL, *to_str = NULL; const char *family_str; bool space = false; @@ -1278,24 +1279,28 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) { } if (!in_addr_is_null(rule->family, &rule->from)) { - r = in_addr_to_string(rule->family, &rule->from, &from_str); + _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 ? " " : "", - from_str, rule->from_prefixlen); + str, rule->from_prefixlen); space = true; } if (!in_addr_is_null(rule->family, &rule->to)) { - r = in_addr_to_string(rule->family, &rule->to, &to_str); + _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 ? " " : "", - to_str, rule->to_prefixlen); + str, rule->to_prefixlen); space = true; } From 816ef8d1dad5d41c4f63f2761964ee4c41055c05 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 15:04:19 +0900 Subject: [PATCH 005/138] network: add more logs on loading routing policy rules failure And reduce scope of variables. --- src/network/networkd-routing-policy-rule.c | 47 +++++++++++----------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index c28c944140..ed13bd09b8 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -1386,31 +1386,31 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) { return 0; } -static int routing_policy_rule_read_full_file(const char *state_file, char **ret) { +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; - size_t size; int r; assert(state_file); - r = read_full_file(state_file, &s, &size); - if (r == -ENOENT) - return -ENODATA; + r = read_full_file(state_file, &s, NULL); + if (r == -ENOENT) { + *ret = NULL; + return 0; + } if (r < 0) return r; - if (size <= 0) - return -ENODATA; - *ret = TAKE_PTR(s); + lines = strv_split_newlines(s); + if (!lines) + return -ENOMEM; - return size; + *ret = TAKE_PTR(lines); + return 0; } int routing_policy_load_rules(const char *state_file, Set **rules) { - _cleanup_strv_free_ char **l = NULL; - _cleanup_free_ char *data = NULL; - uint16_t low = 0, high = 0; - const char *p; + _cleanup_strv_free_ char **data = NULL; char **i; int r; @@ -1418,15 +1418,12 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { assert(rules); r = routing_policy_rule_read_full_file(state_file, &data); - if (r <= 0) - return r; + if (r < 0) + return log_warning_errno(r, "Failed to read %s, ignoring: %m", state_file); - l = strv_split_newlines(data); - if (!l) - return -ENOMEM; - - STRV_FOREACH(i, l) { + STRV_FOREACH(i, data) { _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; + const char *p; p = startswith(*i, "RULE="); if (!p) @@ -1434,7 +1431,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { r = routing_policy_rule_new(&rule); if (r < 0) - return r; + return log_oom(); for (;;) { _cleanup_free_ char *a = NULL; @@ -1442,7 +1439,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { r = extract_first_word(&p, &a, NULL, 0); if (r < 0) - return r; + return log_oom(); if (r == 0) break; @@ -1523,6 +1520,8 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { 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); @@ -1532,6 +1531,8 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { 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); @@ -1574,7 +1575,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { 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", p); + log_warning_errno(r, "Failed to add RPDB rule to saved DB, ignoring: %s", *i); continue; } if (r > 0) From b0815fa4999c749d36f24d55a8f9dbcd0b869708 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 15:36:53 +0900 Subject: [PATCH 006/138] network: make routing_policy_rule_free() returns NULL --- src/network/networkd-routing-policy-rule.c | 8 ++++---- src/network/networkd-routing-policy-rule.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index ed13bd09b8..b3c9a7f3e8 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -84,10 +84,9 @@ static int routing_policy_rule_new_static(Network *network, const char *filename return 0; } -void routing_policy_rule_free(RoutingPolicyRule *rule) { - +RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) { if (!rule) - return; + return NULL; if (rule->network) { LIST_REMOVE(rules, rule->network->rules, rule); @@ -108,7 +107,8 @@ void routing_policy_rule_free(RoutingPolicyRule *rule) { network_config_section_free(rule->section); free(rule->iif); free(rule->oif); - free(rule); + + return mfree(rule); } static int routing_policy_rule_copy(RoutingPolicyRule *dest, RoutingPolicyRule *src) { diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 4e8b191a16..143711623f 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -57,7 +57,7 @@ struct RoutingPolicyRule { }; int routing_policy_rule_new(RoutingPolicyRule **ret); -void routing_policy_rule_free(RoutingPolicyRule *rule); +RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule); DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free); int routing_policy_rule_section_verify(RoutingPolicyRule *rule); From 02e9f4e536f79e8966ea638cd969d3d593f176e7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 23:14:08 +0900 Subject: [PATCH 007/138] network: do not duplicate rule if Family=both --- src/network/networkd-routing-policy-rule.c | 75 +++++++++++----------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index b3c9a7f3e8..45efe2c77f 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -304,13 +304,15 @@ int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRu return -ENOENT; } -static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPolicyRule *in, RoutingPolicyRule **ret) { +static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPolicyRule *in, int family, RoutingPolicyRule **ret) { _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; int r; assert(m); assert(rules); assert(in); + assert(IN_SET(family, AF_INET, AF_INET6)); + assert(in->family == AF_UNSPEC || in->family == family); r = routing_policy_rule_new(&rule); if (r < 0) @@ -322,6 +324,8 @@ static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPoli if (r < 0) return r; + rule->family = family; + r = set_ensure_put(rules, &routing_policy_rule_hash_ops, rule); if (r < 0) return r; @@ -335,12 +339,12 @@ static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPoli return 0; } -static int routing_policy_rule_add(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { - return routing_policy_rule_add_internal(m, &m->rules, rule, ret); +static int routing_policy_rule_add(Manager *m, RoutingPolicyRule *rule, int family, RoutingPolicyRule **ret) { + return routing_policy_rule_add_internal(m, &m->rules, rule, family, ret); } int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { - return routing_policy_rule_add_internal(m, &m->rules_foreign, rule, ret); + return routing_policy_rule_add_internal(m, &m->rules_foreign, rule, rule->family, ret); } static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { @@ -449,7 +453,7 @@ static int routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, return 1; } -static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) { +static int routing_policy_rule_configure_internal(RoutingPolicyRule *rule, int family, Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -462,15 +466,15 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) { if (DEBUG_LOGGING) { _cleanup_free_ char *from = NULL, *to = NULL; - (void) in_addr_to_string(rule->family, &rule->from, &from); - (void) in_addr_to_string(rule->family, &rule->to, &to); + (void) in_addr_to_string(family, &rule->from, &from); + (void) in_addr_to_string(family, &rule->to, &to); log_link_debug(link, "Configuring routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table); } - r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family); + r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, family); if (r < 0) return log_link_error_errno(link, r, "Could not allocate RTM_NEWRULE message: %m"); @@ -583,14 +587,36 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) { return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); + link->routing_policy_rule_messages++; - r = routing_policy_rule_add(link->manager, rule, NULL); + r = routing_policy_rule_add(link->manager, rule, family, NULL); if (r < 0) return log_link_error_errno(link, r, "Could not add rule: %m"); return 1; } +static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) { + int r; + + if (IN_SET(rule->family, AF_INET, AF_INET6)) + return routing_policy_rule_configure_internal(rule, rule->family, link); + + if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)) { + r = routing_policy_rule_configure_internal(rule, AF_INET, link); + if (r < 0) + return r; + } + + if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) { + r = routing_policy_rule_configure_internal(rule, AF_INET6, link); + if (r < 0) + return r; + } + + return 0; +} + static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) { RoutingPolicyRule *link_rule; Link *link; @@ -670,8 +696,6 @@ int link_set_routing_policy_rules(Link *link) { r = routing_policy_rule_configure(rule, link); if (r < 0) return log_link_warning_errno(link, r, "Could not set routing policy rule: %m"); - - link->routing_policy_rule_messages++; } routing_policy_rule_purge(link->manager, link); @@ -1216,8 +1240,6 @@ int config_parse_routing_policy_rule_suppress_prefixlen( } int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { - int r; - if (section_is_invalid(rule->section)) return -EINVAL; @@ -1228,33 +1250,8 @@ int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.", rule->section->filename, rule->section->line); - if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6)) { - _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule6 = NULL; - - assert(rule->family == AF_UNSPEC); - - /* When Family=both, we need to copy the section, AF_INET and AF_INET6. */ - - r = routing_policy_rule_new_static(rule->network, NULL, 0, &rule6); - if (r < 0) - return r; - - r = routing_policy_rule_copy(rule6, rule); - if (r < 0) - return r; - + if (rule->family == AF_UNSPEC && rule->address_family == ADDRESS_FAMILY_NO) rule->family = AF_INET; - rule6->family = AF_INET6; - - TAKE_PTR(rule6); - } - - if (rule->family == AF_UNSPEC) { - if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) - rule->family = AF_INET6; - else - rule->family = AF_INET; - } return 0; } From ca183bf8fd875499c65ef69b4b49e62c381daccc Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 15:29:56 +0900 Subject: [PATCH 008/138] network: drop list of static routing policy rules [RoutingPolicyRule] sections are managed by both LIST and Hashmap. Let's drop list. --- src/network/networkd-manager.c | 1 + src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 11 ++--- src/network/networkd-network.h | 3 -- src/network/networkd-routing-policy-rule.c | 57 +++++++++------------- src/network/networkd-routing-policy-rule.h | 17 ++----- src/network/test-routing-policy-rule.c | 9 +--- 7 files changed, 36 insertions(+), 63 deletions(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index dbbc6b64bc..9ded5fae0a 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -30,6 +30,7 @@ #include "networkd-manager-bus.h" #include "networkd-manager.h" #include "networkd-network-bus.h" +#include "networkd-routing-policy-rule.h" #include "networkd-speed-meter.h" #include "ordered-set.h" #include "path-lookup.h" diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 1258203adf..b3f3a22d07 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -15,6 +15,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "networkd-ipv4ll.h" #include "networkd-ndisc.h" #include "networkd-network.h" +#include "networkd-routing-policy-rule.h" #include "networkd-sriov.h" #include "qdisc.h" #include "tclass.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 49e6d62abb..78ccd9311d 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -16,6 +16,7 @@ #include "network-internal.h" #include "networkd-manager.h" #include "networkd-network.h" +#include "networkd-routing-policy-rule.h" #include "networkd-sriov.h" #include "parse-util.h" #include "path-lookup.h" @@ -149,7 +150,7 @@ static int network_resolve_stacked_netdevs(Network *network) { int network_verify(Network *network) { RoutePrefix *route_prefix, *route_prefix_next; - RoutingPolicyRule *rule, *rule_next; + RoutingPolicyRule *rule; Neighbor *neighbor, *neighbor_next; AddressLabel *label, *label_next; NextHop *nexthop, *nextnop_next; @@ -326,7 +327,7 @@ int network_verify(Network *network) { if (section_is_invalid(route_prefix->section)) route_prefix_free(route_prefix); - LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules) + HASHMAP_FOREACH(rule, network->rules_by_section) if (routing_policy_rule_section_verify(rule) < 0) routing_policy_rule_free(rule); @@ -646,7 +647,6 @@ failure: static Network *network_free(Network *network) { IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; RoutePrefix *route_prefix; - RoutingPolicyRule *rule; AddressLabel *label; FdbEntry *fdb_entry; MdbEntry *mdb_entry; @@ -741,9 +741,6 @@ static Network *network_free(Network *network) { while ((route_prefix = network->static_route_prefixes)) route_prefix_free(route_prefix); - while ((rule = network->rules)) - routing_policy_rule_free(rule); - hashmap_free(network->addresses_by_section); hashmap_free(network->routes_by_section); hashmap_free(network->nexthops_by_section); @@ -753,7 +750,7 @@ static Network *network_free(Network *network) { hashmap_free(network->address_labels_by_section); hashmap_free(network->prefixes_by_section); hashmap_free(network->route_prefixes_by_section); - hashmap_free(network->rules_by_section); + hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free); ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free); ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 5ba0bc705d..bc006944d7 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -29,7 +29,6 @@ #include "networkd-nexthop.h" #include "networkd-radv.h" #include "networkd-route.h" -#include "networkd-routing-policy-rule.h" #include "networkd-util.h" #include "ordered-set.h" #include "resolve-util.h" @@ -295,7 +294,6 @@ struct Network { LIST_HEAD(AddressLabel, address_labels); LIST_HEAD(Prefix, static_prefixes); LIST_HEAD(RoutePrefix, static_route_prefixes); - LIST_HEAD(RoutingPolicyRule, rules); unsigned n_static_addresses; unsigned n_static_routes; @@ -307,7 +305,6 @@ struct Network { unsigned n_address_labels; unsigned n_static_prefixes; unsigned n_static_route_prefixes; - unsigned n_rules; Hashmap *addresses_by_section; Hashmap *routes_by_section; diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 45efe2c77f..79568b7e14 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -9,9 +9,9 @@ #include "fileio.h" #include "format-util.h" #include "ip-protocol-list.h" -#include "networkd-routing-policy-rule.h" #include "netlink-util.h" #include "networkd-manager.h" +#include "networkd-routing-policy-rule.h" #include "networkd-util.h" #include "parse-util.h" #include "socket-util.h" @@ -44,19 +44,17 @@ static int routing_policy_rule_new_static(Network *network, const char *filename assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; - rule = hashmap_get(network->rules_by_section, n); - if (rule) { - *ret = TAKE_PTR(rule); - - return 0; - } + rule = hashmap_get(network->rules_by_section, n); + if (rule) { + *ret = TAKE_PTR(rule); + return 0; } r = routing_policy_rule_new(&rule); @@ -64,23 +62,17 @@ static int routing_policy_rule_new_static(Network *network, const char *filename return r; rule->network = network; - LIST_APPEND(rules, network->rules, rule); - network->n_rules++; + rule->section = TAKE_PTR(n); - if (filename) { - rule->section = TAKE_PTR(n); + r = hashmap_ensure_allocated(&network->rules_by_section, &network_config_hash_ops); + if (r < 0) + return r; - r = hashmap_ensure_allocated(&network->rules_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->rules_by_section, rule->section, rule); - if (r < 0) - return r; - } + r = hashmap_put(network->rules_by_section, rule->section, rule); + if (r < 0) + return r; *ret = TAKE_PTR(rule); - return 0; } @@ -89,12 +81,8 @@ RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) { return NULL; if (rule->network) { - LIST_REMOVE(rules, rule->network->rules, rule); - assert(rule->network->n_rules > 0); - rule->network->n_rules--; - - if (rule->section) - hashmap_remove(rule->network->rules_by_section, rule->section); + assert(rule->section); + hashmap_remove(rule->network->rules_by_section, rule->section); } if (rule->manager) { @@ -618,17 +606,18 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) { } static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) { - RoutingPolicyRule *link_rule; Link *link; assert(m); assert(rule); HASHMAP_FOREACH(link, m->links) { + RoutingPolicyRule *link_rule; + if (!link->network) continue; - LIST_FOREACH(rules, link_rule, link->network->rules) + HASHMAP_FOREACH(link_rule, link->network->rules_by_section) if (routing_policy_rule_compare_func(link_rule, rule) == 0) return true; } @@ -678,7 +667,7 @@ int link_set_routing_policy_rules(Link *link) { link->routing_policy_rules_configured = false; - LIST_FOREACH(rules, rule, link->network->rules) { + HASHMAP_FOREACH(rule, link->network->rules_by_section) { RoutingPolicyRule *existing; r = routing_policy_rule_get(link->manager, rule, &existing); diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 143711623f..431a3b6724 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -2,25 +2,20 @@ #pragma once #include -#include #include #include +#include -#include "in-addr-util.h" #include "conf-parser.h" - -typedef struct RoutingPolicyRule RoutingPolicyRule; - -#include "networkd-link.h" -#include "networkd-network.h" +#include "in-addr-util.h" #include "networkd-util.h" +#include "set.h" typedef struct Network Network; typedef struct Link Link; -typedef struct NetworkConfigSection NetworkConfigSection; typedef struct Manager Manager; -struct RoutingPolicyRule { +typedef struct RoutingPolicyRule { Manager *manager; Network *network; Link *link; @@ -52,9 +47,7 @@ struct RoutingPolicyRule { struct fib_rule_uid_range uid_range; int suppress_prefixlen; - - LIST_FIELDS(RoutingPolicyRule, rules); -}; +} RoutingPolicyRule; int routing_policy_rule_new(RoutingPolicyRule **ret); RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule); diff --git a/src/network/test-routing-policy-rule.c b/src/network/test-routing-policy-rule.c index 78755927c7..40341d6073 100644 --- a/src/network/test-routing-policy-rule.c +++ b/src/network/test-routing-policy-rule.c @@ -1,13 +1,8 @@ -/*** - SPDX-License-Identifier: LGPL-2.1+ -***/ +/* SPDX-License-Identifier: LGPL-2.1+ */ #include "fd-util.h" #include "fileio.h" -#include "log.h" -#include "macro.h" -#include "network-internal.h" -#include "networkd-manager.h" +#include "networkd-routing-policy-rule.h" #include "string-util.h" #include "tests.h" #include "tmpfile-util.h" From 0d7d377b800db19728e3b6cb707925e557f5a536 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 16:00:21 +0900 Subject: [PATCH 009/138] network: move log_message_warning_errno() to networkd-util.h --- src/network/networkd-manager.c | 7 ------- src/network/networkd-util.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 9ded5fae0a..ad1c97b83e 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -46,13 +46,6 @@ /* use 128 MB for receive socket kernel queue. */ #define RCVBUF_SIZE (128*1024*1024) -static int log_message_warning_errno(sd_netlink_message *m, int err, const char *msg) { - const char *err_msg = NULL; - - (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg); - return log_warning_errno(err, "%s: %s%s%m", msg, strempty(err_msg), err_msg ? " " : ""); -} - static int setup_default_address_pool(Manager *m) { AddressPool *p; int r; diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h index 0433f883a3..2b6541d57e 100644 --- a/src/network/networkd-util.h +++ b/src/network/networkd-util.h @@ -2,10 +2,13 @@ #pragma once #include "sd-dhcp-lease.h" +#include "sd-netlink.h" #include "conf-parser.h" #include "hash-funcs.h" +#include "log.h" #include "macro.h" +#include "string-util.h" typedef enum AddressFamily { /* This is a bitmask, though it usually doesn't feel that way! */ @@ -70,3 +73,10 @@ static inline bool section_is_invalid(NetworkConfigSection *section) { } \ DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \ DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid); + +static inline int log_message_warning_errno(sd_netlink_message *m, int err, const char *msg) { + const char *err_msg = NULL; + + (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg); + return log_warning_errno(err, "%s: %s%s%m", msg, strempty(err_msg), err_msg ? " " : ""); +} From 3d65f7c8630714b51420ee6caa9fc17714fae92c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 16:12:17 +0900 Subject: [PATCH 010/138] sd-netlink: fix typo and make netlink_add_match() take description --- src/libsystemd/sd-netlink/netlink-util.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h index ddf5686f13..8e99cd451d 100644 --- a/src/libsystemd/sd-netlink/netlink-util.h +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -77,14 +77,14 @@ int rtnl_log_create_error(int r); userdata, 0, __func__); \ }) -#define netlink_add_match(nl, ret_slot, metch, callback, destroy_callback, userdata) \ +#define netlink_add_match(nl, ret_slot, match, callback, destroy_callback, userdata, description) \ ({ \ int (*_callback_)(sd_netlink *, sd_netlink_message *, typeof(userdata)) = callback; \ void (*_destroy_)(typeof(userdata)) = destroy_callback; \ sd_netlink_add_match(nl, ret_slot, match, \ (sd_netlink_message_handler_t) _callback_, \ (sd_netlink_destroy_t) _destroy_, \ - userdata, __func__); \ + userdata, description); \ }) int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data); From 8dfed23d92ebf3144981dcb28765a24b4417e877 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 16:20:00 +0900 Subject: [PATCH 011/138] network: use typesafe macro netlink_add_match() --- src/network/networkd-manager.c | 43 ++++++++++++++-------------------- src/network/networkd-manager.h | 6 +---- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index ad1c97b83e..f24da90f33 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -283,10 +283,9 @@ static int manager_connect_udev(Manager *m) { return 0; } -int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { +static int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_(route_freep) Route *tmp = NULL; Route *route = NULL; - Manager *m = userdata; Link *link = NULL; uint32_t ifindex; uint16_t type; @@ -579,8 +578,7 @@ static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, uni return r; } -int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { - Manager *m = userdata; +static int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { Link *link = NULL; Neighbor *neighbor = NULL; int ifindex, family, r; @@ -719,9 +717,8 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, return 1; } -int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { +int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_free_ char *buf = NULL; - Manager *m = userdata; Link *link = NULL; uint16_t type; unsigned char flags, prefixlen, scope; @@ -882,8 +879,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, return 1; } -static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { - Manager *m = userdata; +static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { Link *link = NULL; NetDev *netdev = NULL; uint16_t type; @@ -970,20 +966,18 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa return 1; } -int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { +static int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL; _cleanup_free_ char *from = NULL, *to = NULL; RoutingPolicyRule *rule = NULL; const char *iif = NULL, *oif = NULL; uint32_t suppress_prefixlen; - Manager *m = userdata; unsigned flags; uint16_t type; int r; assert(rtnl); assert(message); - assert(m); if (sd_netlink_message_is_error(message)) { r = sd_netlink_message_get_errno(message); @@ -1202,11 +1196,10 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi return 1; } -int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { +static int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_(nexthop_freep) NextHop *tmp = NULL; _cleanup_free_ char *gateway = NULL; NextHop *nexthop = NULL; - Manager *m = userdata; Link *link = NULL; uint16_t type; int r; @@ -1387,51 +1380,51 @@ static int manager_connect_rtnl(Manager *m) { if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link"); + r = netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link"); + r = netlink_add_match(m->rtnl, NULL, RTM_DELLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address"); + r = netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address"); + r = netlink_add_match(m->rtnl, NULL, RTM_DELADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor"); + r = netlink_add_match(m->rtnl, NULL, RTM_NEWNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor"); + r = netlink_add_match(m->rtnl, NULL, RTM_DELNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route"); + r = netlink_add_match(m->rtnl, NULL, RTM_NEWROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route"); + r = netlink_add_match(m->rtnl, NULL, RTM_DELROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule"); + r = netlink_add_match(m->rtnl, NULL, RTM_NEWRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule"); + r = netlink_add_match(m->rtnl, NULL, RTM_DELRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop"); + r = netlink_add_match(m->rtnl, NULL, RTM_NEWNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop"); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop"); + r = netlink_add_match(m->rtnl, NULL, RTM_DELNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop"); if (r < 0) return r; diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 255a0d965f..1b6b7f785d 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -89,11 +89,7 @@ int manager_rtnl_enumerate_routes(Manager *m); int manager_rtnl_enumerate_rules(Manager *m); int manager_rtnl_enumerate_nexthop(Manager *m); -int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, void *userdata); -int manager_rtnl_process_neighbor(sd_netlink *nl, sd_netlink_message *message, void *userdata); -int manager_rtnl_process_route(sd_netlink *nl, sd_netlink_message *message, void *userdata); -int manager_rtnl_process_rule(sd_netlink *nl, sd_netlink_message *message, void *userdata); -int manager_rtnl_process_nexthop(sd_netlink *nl, sd_netlink_message *message, void *userdata); +int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); void manager_dirty(Manager *m); From 51a0dc4a151bb3e6e439b6a62b64f84717214e77 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 16:23:57 +0900 Subject: [PATCH 012/138] network: move manager_rtnl_process_rule() to networkd-routing-policy-rule.[ch] --- src/network/networkd-manager.c | 230 -------------------- src/network/networkd-routing-policy-rule.c | 234 ++++++++++++++++++++- src/network/networkd-routing-policy-rule.h | 4 +- 3 files changed, 234 insertions(+), 234 deletions(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index f24da90f33..faea2356b5 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -966,236 +966,6 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa return 1; } -static int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL; - _cleanup_free_ char *from = NULL, *to = NULL; - RoutingPolicyRule *rule = NULL; - const char *iif = NULL, *oif = NULL; - uint32_t suppress_prefixlen; - unsigned flags; - uint16_t type; - int r; - - assert(rtnl); - assert(message); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); - return 0; - } else if (!IN_SET(type, RTM_NEWRULE, RTM_DELRULE)) { - log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type); - return 0; - } - - r = routing_policy_rule_new(&tmp); - if (r < 0) { - log_oom(); - return 0; - } - - r = sd_rtnl_message_get_family(message, &tmp->family); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get rule family, ignoring: %m"); - return 0; - } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { - log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp->family); - return 0; - } - - switch (tmp->family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, FRA_SRC, &tmp->from.in); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m"); - return 0; - } else if (r >= 0) { - r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen); - if (r < 0) { - log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m"); - return 0; - } - } - - r = sd_netlink_message_read_in_addr(message, FRA_DST, &tmp->to.in); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m"); - return 0; - } else if (r >= 0) { - r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen); - if (r < 0) { - log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m"); - return 0; - } - } - - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, FRA_SRC, &tmp->from.in6); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m"); - return 0; - } else if (r >= 0) { - r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen); - if (r < 0) { - log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m"); - return 0; - } - } - - r = sd_netlink_message_read_in6_addr(message, FRA_DST, &tmp->to.in6); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m"); - return 0; - } else if (r >= 0) { - r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen); - if (r < 0) { - log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m"); - return 0; - } - } - - break; - - default: - assert_not_reached("Received rule message with unsupported address family"); - } - - r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags); - if (r < 0) { - log_warning_errno(r, "rtnl: received rule message without valid flag, ignoring: %m"); - return 0; - } - tmp->invert_rule = flags & FIB_RULE_INVERT; - - r = sd_netlink_message_read_u32(message, FRA_FWMARK, &tmp->fwmark); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, FRA_FWMASK, &tmp->fwmask); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, FRA_PRIORITY, &tmp->priority); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, FRA_TABLE, &tmp->table); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_TABLE attribute, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_routing_policy_rule_get_tos(message, &tmp->tos); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get ip rule TOS, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_string(message, FRA_IIFNAME, &iif); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m"); - return 0; - } - r = free_and_strdup(&tmp->iif, iif); - if (r < 0) - return log_oom(); - - r = sd_netlink_message_read_string(message, FRA_OIFNAME, &oif); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m"); - return 0; - } - r = free_and_strdup(&tmp->oif, oif); - if (r < 0) - return log_oom(); - - r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->protocol); - 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(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"); - return 0; - } - - r = sd_netlink_message_read(message, FRA_DPORT_RANGE, sizeof(tmp->dport), &tmp->dport); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read(message, FRA_UID_RANGE, sizeof(tmp->uid_range), &tmp->uid_range); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, FRA_SUPPRESS_PREFIXLEN, &suppress_prefixlen); - if (r < 0 && r != -ENODATA) { - 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; - - (void) routing_policy_rule_get(m, tmp, &rule); - - if (DEBUG_LOGGING) { - (void) in_addr_to_string(tmp->family, &tmp->from, &from); - (void) in_addr_to_string(tmp->family, &tmp->to, &to); - } - - switch (type) { - case RTM_NEWRULE: - if (rule) - log_debug("Received remembered routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, - tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); - else { - log_debug("Remembering foreign routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, - tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); - r = routing_policy_rule_add_foreign(m, tmp, &rule); - if (r < 0) { - log_warning_errno(r, "Could not remember foreign rule, ignoring: %m"); - return 0; - } - } - break; - case RTM_DELRULE: - if (rule) { - log_debug("Forgetting routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, - tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); - routing_policy_rule_free(rule); - } else - log_debug("Kernel removed a routing policy rule we don't remember: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32", ignoring.", - tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); - break; - - default: - assert_not_reached("Received invalid RTNL message type"); - } - - return 1; -} - static int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_(nexthop_freep) NextHop *tmp = NULL; _cleanup_free_ char *gateway = NULL; diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 79568b7e14..10b6a75cd7 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -269,7 +269,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( routing_policy_rule_compare_func, routing_policy_rule_free); -int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { +static int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { RoutingPolicyRule *existing; @@ -331,7 +331,7 @@ static int routing_policy_rule_add(Manager *m, RoutingPolicyRule *rule, int fami return routing_policy_rule_add_internal(m, &m->rules, rule, family, ret); } -int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { +static int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { return routing_policy_rule_add_internal(m, &m->rules_foreign, rule, rule->family, ret); } @@ -698,6 +698,236 @@ int link_set_routing_policy_rules(Link *link) { return 0; } +int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { + _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL; + _cleanup_free_ char *from = NULL, *to = NULL; + RoutingPolicyRule *rule = NULL; + const char *iif = NULL, *oif = NULL; + uint32_t suppress_prefixlen; + unsigned flags; + uint16_t type; + int r; + + assert(rtnl); + assert(message); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWRULE, RTM_DELRULE)) { + log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type); + return 0; + } + + r = routing_policy_rule_new(&tmp); + if (r < 0) { + log_oom(); + return 0; + } + + r = sd_rtnl_message_get_family(message, &tmp->family); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get rule family, ignoring: %m"); + return 0; + } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { + log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp->family); + return 0; + } + + switch (tmp->family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, FRA_SRC, &tmp->from.in); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m"); + return 0; + } else if (r >= 0) { + r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m"); + return 0; + } + } + + r = sd_netlink_message_read_in_addr(message, FRA_DST, &tmp->to.in); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m"); + return 0; + } else if (r >= 0) { + r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m"); + return 0; + } + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, FRA_SRC, &tmp->from.in6); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m"); + return 0; + } else if (r >= 0) { + r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m"); + return 0; + } + } + + r = sd_netlink_message_read_in6_addr(message, FRA_DST, &tmp->to.in6); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m"); + return 0; + } else if (r >= 0) { + r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m"); + return 0; + } + } + + break; + + default: + assert_not_reached("Received rule message with unsupported address family"); + } + + r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid flag, ignoring: %m"); + return 0; + } + tmp->invert_rule = flags & FIB_RULE_INVERT; + + r = sd_netlink_message_read_u32(message, FRA_FWMARK, &tmp->fwmark); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, FRA_FWMASK, &tmp->fwmask); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, FRA_PRIORITY, &tmp->priority); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, FRA_TABLE, &tmp->table); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_TABLE attribute, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_routing_policy_rule_get_tos(message, &tmp->tos); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get ip rule TOS, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_string(message, FRA_IIFNAME, &iif); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m"); + return 0; + } + r = free_and_strdup(&tmp->iif, iif); + if (r < 0) + return log_oom(); + + r = sd_netlink_message_read_string(message, FRA_OIFNAME, &oif); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m"); + return 0; + } + r = free_and_strdup(&tmp->oif, oif); + if (r < 0) + return log_oom(); + + r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->protocol); + 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(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"); + return 0; + } + + r = sd_netlink_message_read(message, FRA_DPORT_RANGE, sizeof(tmp->dport), &tmp->dport); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read(message, FRA_UID_RANGE, sizeof(tmp->uid_range), &tmp->uid_range); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, FRA_SUPPRESS_PREFIXLEN, &suppress_prefixlen); + if (r < 0 && r != -ENODATA) { + 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; + + (void) routing_policy_rule_get(m, tmp, &rule); + + if (DEBUG_LOGGING) { + (void) in_addr_to_string(tmp->family, &tmp->from, &from); + (void) in_addr_to_string(tmp->family, &tmp->to, &to); + } + + switch (type) { + case RTM_NEWRULE: + if (rule) + log_debug("Received remembered routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, + tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); + else { + log_debug("Remembering foreign routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, + tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); + r = routing_policy_rule_add_foreign(m, tmp, &rule); + if (r < 0) { + log_warning_errno(r, "Could not remember foreign rule, ignoring: %m"); + return 0; + } + } + break; + case RTM_DELRULE: + if (rule) { + log_debug("Forgetting routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, + tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); + routing_policy_rule_free(rule); + } else + log_debug("Kernel removed a routing policy rule we don't remember: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32", ignoring.", + tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + static int parse_fwmark_fwmask(const char *s, uint32_t *ret_fwmark, uint32_t *ret_fwmask) { _cleanup_free_ char *fwmark_str = NULL; uint32_t fwmark, fwmask = 0; diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 431a3b6724..1eaae2ec15 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -57,8 +57,8 @@ int routing_policy_rule_section_verify(RoutingPolicyRule *rule); int link_set_routing_policy_rules(Link *link); -int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret); -int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret); +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); From f1828a222a7b4a859d90567f4721f31dd7536cd1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 21:43:59 +0900 Subject: [PATCH 013/138] network: make routing_policy_rule_new() static --- src/network/networkd-routing-policy-rule.c | 50 +++++++++++----------- src/network/networkd-routing-policy-rule.h | 3 -- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 10b6a75cd7..386aa5789b 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -19,7 +19,32 @@ #include "strv.h" #include "user-util.h" -int routing_policy_rule_new(RoutingPolicyRule **ret) { +RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) { + if (!rule) + return NULL; + + if (rule->network) { + assert(rule->section); + hashmap_remove(rule->network->rules_by_section, rule->section); + } + + if (rule->manager) { + if (set_get(rule->manager->rules, rule) == rule) + set_remove(rule->manager->rules, rule); + if (set_get(rule->manager->rules_foreign, rule) == rule) + set_remove(rule->manager->rules_foreign, rule); + } + + network_config_section_free(rule->section); + free(rule->iif); + free(rule->oif); + + return mfree(rule); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free); + +static int routing_policy_rule_new(RoutingPolicyRule **ret) { RoutingPolicyRule *rule; rule = new(RoutingPolicyRule, 1); @@ -76,29 +101,6 @@ static int routing_policy_rule_new_static(Network *network, const char *filename return 0; } -RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) { - if (!rule) - return NULL; - - if (rule->network) { - assert(rule->section); - hashmap_remove(rule->network->rules_by_section, rule->section); - } - - if (rule->manager) { - if (set_get(rule->manager->rules, rule) == rule) - set_remove(rule->manager->rules, rule); - if (set_get(rule->manager->rules_foreign, rule) == rule) - set_remove(rule->manager->rules_foreign, rule); - } - - network_config_section_free(rule->section); - free(rule->iif); - free(rule->oif); - - return mfree(rule); -} - static int routing_policy_rule_copy(RoutingPolicyRule *dest, RoutingPolicyRule *src) { _cleanup_free_ char *iif = NULL, *oif = NULL; diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 1eaae2ec15..8510dec0fc 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -49,10 +49,7 @@ typedef struct RoutingPolicyRule { int suppress_prefixlen; } RoutingPolicyRule; -int routing_policy_rule_new(RoutingPolicyRule **ret); RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule); - -DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free); int routing_policy_rule_section_verify(RoutingPolicyRule *rule); int link_set_routing_policy_rules(Link *link); From 50a3682f1ea89d83c3d614375bcb8ffe22d76e57 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 00:50:30 +0900 Subject: [PATCH 014/138] network: introduce network_verify_routing_policy_rules() --- src/network/networkd-network.c | 5 +---- src/network/networkd-routing-policy-rule.c | 12 +++++++++++- src/network/networkd-routing-policy-rule.h | 3 ++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 78ccd9311d..c642e86fda 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -150,7 +150,6 @@ static int network_resolve_stacked_netdevs(Network *network) { int network_verify(Network *network) { RoutePrefix *route_prefix, *route_prefix_next; - RoutingPolicyRule *rule; Neighbor *neighbor, *neighbor_next; AddressLabel *label, *label_next; NextHop *nexthop, *nextnop_next; @@ -327,9 +326,7 @@ int network_verify(Network *network) { if (section_is_invalid(route_prefix->section)) route_prefix_free(route_prefix); - HASHMAP_FOREACH(rule, network->rules_by_section) - if (routing_policy_rule_section_verify(rule) < 0) - routing_policy_rule_free(rule); + network_verify_routing_policy_rules(network); bool has_root = false, has_clsact = false; ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 386aa5789b..9dbced6c0c 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -1460,7 +1460,7 @@ int config_parse_routing_policy_rule_suppress_prefixlen( return 0; } -int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { +static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { if (section_is_invalid(rule->section)) return -EINVAL; @@ -1477,6 +1477,16 @@ int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { return 0; } +void network_verify_routing_policy_rules(Network *network) { + RoutingPolicyRule *rule; + + assert(network); + + HASHMAP_FOREACH(rule, network->rules_by_section) + 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; diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 8510dec0fc..9b4f979f7b 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -50,7 +50,8 @@ typedef struct RoutingPolicyRule { } RoutingPolicyRule; RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule); -int routing_policy_rule_section_verify(RoutingPolicyRule *rule); + +void network_verify_routing_policy_rules(Network *network); int link_set_routing_policy_rules(Link *link); From 6f3337277f351877e24ea48a8970d32e9b841a91 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 5 Oct 2020 00:55:15 +0900 Subject: [PATCH 015/138] network: drop unused element --- src/network/networkd-routing-policy-rule.c | 2 -- src/network/networkd-routing-policy-rule.h | 1 - 2 files changed, 3 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 9dbced6c0c..d2a8768a42 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -568,8 +568,6 @@ static int routing_policy_rule_configure_internal(RoutingPolicyRule *rule, int f return log_link_error_errno(link, r, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m"); } - rule->link = link; - r = netlink_call_async(link->manager->rtnl, NULL, m, routing_policy_rule_handler, link_netlink_destroy_callback, link); diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 9b4f979f7b..ac5cbbed0e 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -18,7 +18,6 @@ typedef struct Manager Manager; typedef struct RoutingPolicyRule { Manager *manager; Network *network; - Link *link; NetworkConfigSection *section; bool invert_rule; From 5a82104bf3f5df07f9e73cab5cf7647753371c52 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 5 Oct 2020 22:05:33 +0200 Subject: [PATCH 016/138] network: add missing "else" --- src/network/networkd-routing-policy-rule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index d2a8768a42..f35ab3e3db 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -1687,7 +1687,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { continue; } rule->family = r; - } if (STR_IN_SET(a, "from", "to")) { + } else if (STR_IN_SET(a, "from", "to")) { union in_addr_union *buffer; uint8_t *prefixlen; From d08ed5a1fde2c7cfdfd7425005ef50a121c60bfd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 6 Oct 2020 06:20:39 +0900 Subject: [PATCH 017/138] network: specify all known attributes when removing routing policy rules Otherwise, routing_policy_rule_remove() may removes unintended rule. --- src/network/networkd-routing-policy-rule.c | 248 ++++++++++----------- 1 file changed, 123 insertions(+), 125 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index f35ab3e3db..588c36f306 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -337,136 +337,12 @@ static int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, return routing_policy_rule_add_internal(m, &m->rules_foreign, rule, rule->family, ret); } -static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(m); - assert(link); - assert(link->ifname); - - link->routing_policy_rule_remove_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0) - log_link_message_warning_errno(link, m, r, "Could not drop routing policy rule"); - - return 1; -} - -static int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; +static int routing_policy_rule_set_netlink_message(RoutingPolicyRule *rule, sd_netlink_message *m, Link *link) { int r; assert(rule); - assert(link); - assert(link->manager); - assert(link->manager->rtnl); - assert(link->ifindex > 0); - assert(IN_SET(rule->family, AF_INET, AF_INET6)); - - if (DEBUG_LOGGING) { - _cleanup_free_ char *from = NULL, *to = NULL; - - (void) in_addr_to_string(rule->family, &rule->from, &from); - (void) in_addr_to_string(rule->family, &rule->to, &to); - - log_link_debug(link, - "Removing routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, - rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table); - } - - r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_DELRULE, rule->family); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_DELRULE message: %m"); - - if (in_addr_is_null(rule->family, &rule->from) == 0) { - r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from); - if (r < 0) - return log_link_error_errno(link, r, "Could not append FRA_SRC attribute: %m"); - - r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, rule->from_prefixlen); - if (r < 0) - return log_link_error_errno(link, r, "Could not set source prefix length: %m"); - } - - if (in_addr_is_null(rule->family, &rule->to) == 0) { - r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to); - if (r < 0) - return log_link_error_errno(link, r, "Could not append FRA_DST attribute: %m"); - - r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, rule->to_prefixlen); - if (r < 0) - return log_link_error_errno(link, r, "Could not set destination prefix length: %m"); - } - - r = netlink_call_async(link->manager->rtnl, NULL, m, - routing_policy_rule_remove_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); - - link_ref(link); - - return 0; -} - -static int routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(rtnl); assert(m); assert(link); - assert(link->ifname); - assert(link->routing_policy_rule_messages > 0); - - link->routing_policy_rule_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_message_warning_errno(link, m, r, "Could not add routing policy rule"); - link_enter_failed(link); - return 1; - } - - if (link->routing_policy_rule_messages == 0) { - log_link_debug(link, "Routing policy rule configured"); - link->routing_policy_rules_configured = true; - link_check_ready(link); - } - - return 1; -} - -static int routing_policy_rule_configure_internal(RoutingPolicyRule *rule, int family, Link *link) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; - int r; - - assert(rule); - assert(link); - assert(link->ifindex > 0); - assert(link->manager); - assert(link->manager->rtnl); - - if (DEBUG_LOGGING) { - _cleanup_free_ char *from = NULL, *to = NULL; - - (void) in_addr_to_string(family, &rule->from, &from); - (void) in_addr_to_string(family, &rule->to, &to); - - log_link_debug(link, - "Configuring routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, - rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table); - } - - r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, family); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_NEWRULE message: %m"); if (in_addr_is_null(rule->family, &rule->from) == 0) { r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from); @@ -568,6 +444,128 @@ static int routing_policy_rule_configure_internal(RoutingPolicyRule *rule, int f return log_link_error_errno(link, r, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m"); } + return 0; +} + +static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + + link->routing_policy_rule_remove_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_message_warning_errno(link, m, r, "Could not drop routing policy rule"); + + return 1; +} + +static int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(rule); + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + assert(link->ifindex > 0); + assert(IN_SET(rule->family, AF_INET, AF_INET6)); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *from = NULL, *to = NULL; + + (void) in_addr_to_string(rule->family, &rule->from, &from); + (void) in_addr_to_string(rule->family, &rule->to, &to); + + log_link_debug(link, + "Removing routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, + rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table); + } + + r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_DELRULE, rule->family); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_DELRULE message: %m"); + + r = routing_policy_rule_set_netlink_message(rule, m, link); + if (r < 0) + return r; + + r = netlink_call_async(link->manager->rtnl, NULL, m, + routing_policy_rule_remove_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(rtnl); + assert(m); + assert(link); + assert(link->ifname); + assert(link->routing_policy_rule_messages > 0); + + link->routing_policy_rule_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_message_warning_errno(link, m, r, "Could not add routing policy rule"); + link_enter_failed(link); + return 1; + } + + if (link->routing_policy_rule_messages == 0) { + log_link_debug(link, "Routing policy rule configured"); + link->routing_policy_rules_configured = true; + link_check_ready(link); + } + + return 1; +} + +static int routing_policy_rule_configure_internal(RoutingPolicyRule *rule, int family, Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(rule); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *from = NULL, *to = NULL; + + (void) in_addr_to_string(family, &rule->from, &from); + (void) in_addr_to_string(family, &rule->to, &to); + + log_link_debug(link, + "Configuring routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, + rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table); + } + + r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, family); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_NEWRULE message: %m"); + + r = routing_policy_rule_set_netlink_message(rule, m, link); + if (r < 0) + return r; + r = netlink_call_async(link->manager->rtnl, NULL, m, routing_policy_rule_handler, link_netlink_destroy_callback, link); From 446aaaf35fa4c6067874430522089712ba0ff394 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 16:44:41 +0900 Subject: [PATCH 018/138] network: introduce helper function to enumerate information using netlink --- src/network/networkd-manager.c | 233 ++++++++++++--------------------- src/network/networkd-manager.h | 7 +- src/network/networkd.c | 24 +--- src/network/test-network.c | 2 +- 4 files changed, 88 insertions(+), 178 deletions(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index faea2356b5..2dc6ef0933 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1689,9 +1689,51 @@ bool manager_should_reload(Manager *m) { return paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, false); } -int manager_rtnl_enumerate_links(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *link; +static int manager_enumerate_internal( + Manager *m, + sd_netlink_message *req, + int (*process)(sd_netlink *, sd_netlink_message *, Manager *), + const char *name) { + + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *reply = NULL; + int r; + + assert(m); + assert(m->rtnl); + assert(req); + assert(process); + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) { + if (r == -EOPNOTSUPP && name) { + log_debug_errno(r, "%s are not supported by the kernel. Ignoring.", name); + return 0; + } + + return r; + } + + for (sd_netlink_message *reply_one = reply; reply_one; reply_one = sd_netlink_message_next(reply_one)) { + int k; + + m->enumerating = true; + + k = process(m->rtnl, reply_one, m); + if (k < 0 && r >= 0) + r = k; + + m->enumerating = false; + } + + return r; +} + +static int manager_enumerate_links(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(m); @@ -1701,32 +1743,11 @@ int manager_rtnl_enumerate_links(Manager *m) { if (r < 0) return r; - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (link = reply; link; link = sd_netlink_message_next(link)) { - int k; - - m->enumerating = true; - - k = manager_rtnl_process_link(m->rtnl, link, m); - if (k < 0) - r = k; - - m->enumerating = false; - } - - return r; + return manager_enumerate_internal(m, req, manager_rtnl_process_link, NULL); } -int manager_rtnl_enumerate_addresses(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *addr; +static int manager_enumerate_addresses(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(m); @@ -1736,32 +1757,11 @@ int manager_rtnl_enumerate_addresses(Manager *m) { if (r < 0) return r; - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (addr = reply; addr; addr = sd_netlink_message_next(addr)) { - int k; - - m->enumerating = true; - - k = manager_rtnl_process_address(m->rtnl, addr, m); - if (k < 0) - r = k; - - m->enumerating = false; - } - - return r; + return manager_enumerate_internal(m, req, manager_rtnl_process_address, NULL); } -int manager_rtnl_enumerate_neighbors(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *neigh; +static int manager_enumerate_neighbors(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(m); @@ -1771,32 +1771,11 @@ int manager_rtnl_enumerate_neighbors(Manager *m) { if (r < 0) return r; - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (neigh = reply; neigh; neigh = sd_netlink_message_next(neigh)) { - int k; - - m->enumerating = true; - - k = manager_rtnl_process_neighbor(m->rtnl, neigh, m); - if (k < 0) - r = k; - - m->enumerating = false; - } - - return r; + return manager_enumerate_internal(m, req, manager_rtnl_process_neighbor, NULL); } -int manager_rtnl_enumerate_routes(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *route; +static int manager_enumerate_routes(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(m); @@ -1809,32 +1788,11 @@ int manager_rtnl_enumerate_routes(Manager *m) { if (r < 0) return r; - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (route = reply; route; route = sd_netlink_message_next(route)) { - int k; - - m->enumerating = true; - - k = manager_rtnl_process_route(m->rtnl, route, m); - if (k < 0) - r = k; - - m->enumerating = false; - } - - return r; + return manager_enumerate_internal(m, req, manager_rtnl_process_route, NULL); } -int manager_rtnl_enumerate_rules(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *rule; +static int manager_enumerate_rules(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(m); @@ -1844,38 +1802,11 @@ int manager_rtnl_enumerate_rules(Manager *m) { if (r < 0) return r; - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) { - if (r == -EOPNOTSUPP) { - log_debug("FIB Rules are not supported by the kernel. Ignoring."); - return 0; - } - - return r; - } - - for (rule = reply; rule; rule = sd_netlink_message_next(rule)) { - int k; - - m->enumerating = true; - - k = manager_rtnl_process_rule(m->rtnl, rule, m); - if (k < 0) - r = k; - - m->enumerating = false; - } - - return r; + return manager_enumerate_internal(m, req, manager_rtnl_process_rule, "Routing policy rules"); } -int manager_rtnl_enumerate_nexthop(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *nexthop; +static int manager_enumerate_nexthop(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(m); @@ -1885,33 +1816,37 @@ int manager_rtnl_enumerate_nexthop(Manager *m) { if (r < 0) return r; - r = sd_netlink_message_request_dump(req, true); + return manager_enumerate_internal(m, req, manager_rtnl_process_nexthop, "Nexthop rules"); +} + +int manager_enumerate(Manager *m) { + int r; + + r = manager_enumerate_links(m); if (r < 0) - return r; + return log_error_errno(r, "Could not enumerate links: %m"); - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) { - if (r == -EOPNOTSUPP) { - log_debug("Nexthop are not supported by the kernel. Ignoring."); - return 0; - } + r = manager_enumerate_addresses(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate addresses: %m"); - return r; - } + r = manager_enumerate_neighbors(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate neighbors: %m"); - for (nexthop = reply; nexthop; nexthop = sd_netlink_message_next(nexthop)) { - int k; + r = manager_enumerate_routes(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate routes: %m"); - m->enumerating = true; + r = manager_enumerate_rules(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate routing policy rules: %m"); - k = manager_rtnl_process_nexthop(m->rtnl, nexthop, m); - if (k < 0) - r = k; + r = manager_enumerate_nexthop(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate nexthop rules: %m"); - m->enumerating = false; - } - - return r; + return 0; } int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) { diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 1b6b7f785d..602ae919e9 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -82,12 +82,7 @@ int manager_start(Manager *m); int manager_load_config(Manager *m); bool manager_should_reload(Manager *m); -int manager_rtnl_enumerate_links(Manager *m); -int manager_rtnl_enumerate_addresses(Manager *m); -int manager_rtnl_enumerate_neighbors(Manager *m); -int manager_rtnl_enumerate_routes(Manager *m); -int manager_rtnl_enumerate_rules(Manager *m); -int manager_rtnl_enumerate_nexthop(Manager *m); +int manager_enumerate(Manager *m); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd.c b/src/network/networkd.c index 445aee16ad..f78ff9db54 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -88,29 +88,9 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Could not load configuration files: %m"); - r = manager_rtnl_enumerate_links(m); + r = manager_enumerate(m); if (r < 0) - return log_error_errno(r, "Could not enumerate links: %m"); - - r = manager_rtnl_enumerate_addresses(m); - if (r < 0) - return log_error_errno(r, "Could not enumerate addresses: %m"); - - r = manager_rtnl_enumerate_neighbors(m); - if (r < 0) - return log_error_errno(r, "Could not enumerate neighbors: %m"); - - r = manager_rtnl_enumerate_routes(m); - if (r < 0) - return log_error_errno(r, "Could not enumerate routes: %m"); - - r = manager_rtnl_enumerate_rules(m); - if (r < 0) - return log_error_errno(r, "Could not enumerate rules: %m"); - - r = manager_rtnl_enumerate_nexthop(m); - if (r < 0) - return log_error_errno(r, "Could not enumerate nexthop: %m"); + return r; r = manager_start(m); if (r < 0) diff --git a/src/network/test-network.c b/src/network/test-network.c index 2ac47e72f5..eeb756ca04 100644 --- a/src/network/test-network.c +++ b/src/network/test-network.c @@ -252,6 +252,6 @@ int main(void) { test_network_get(manager, loopback); - assert_se(manager_rtnl_enumerate_links(manager) >= 0); + assert_se(manager_enumerate(manager) >= 0); return 0; } From c133770a6b73b669219742768e93d5393dbc4ec7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 17:18:55 +0900 Subject: [PATCH 019/138] network: move link_request_set_nexthop() to networkd-nexthop.c --- src/network/networkd-link.c | 58 ++----------------------------- src/network/networkd-nexthop.c | 63 ++++++++++++++++++++++++++++++---- src/network/networkd-nexthop.h | 3 +- 3 files changed, 61 insertions(+), 63 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 685cbd34cf..dca9b1550c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -925,60 +925,6 @@ static void link_enter_configured(Link *link) { link_dirty(link); } -static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(link); - assert(link->nexthop_messages > 0); - assert(IN_SET(link->state, LINK_STATE_CONFIGURING, - LINK_STATE_FAILED, LINK_STATE_LINGER)); - - link->nexthop_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_message_warning_errno(link, m, r, "Could not set nexthop"); - link_enter_failed(link); - return 1; - } - - if (link->nexthop_messages == 0) { - log_link_debug(link, "Nexthop set"); - link->static_nexthops_configured = true; - link_check_ready(link); - } - - return 1; -} - -static int link_request_set_nexthop(Link *link) { - NextHop *nh; - int r; - - link->static_nexthops_configured = false; - - LIST_FOREACH(nexthops, nh, link->network->static_nexthops) { - r = nexthop_configure(nh, link, nexthop_handler); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set nexthop: %m"); - if (r > 0) - link->nexthop_messages++; - } - - if (link->nexthop_messages == 0) { - link->static_nexthops_configured = true; - link_check_ready(link); - } else { - log_link_debug(link, "Setting nexthop"); - link_set_state(link, LINK_STATE_CONFIGURING); - } - - return 1; -} - static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -1002,7 +948,7 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { if (link->route_messages == 0) { log_link_debug(link, "Routes set"); link->static_routes_configured = true; - link_request_set_nexthop(link); + link_set_nexthop(link); } return 1; @@ -1053,7 +999,7 @@ int link_request_set_routes(Link *link) { if (link->route_messages == 0) { link->static_routes_configured = true; - link_request_set_nexthop(link); + link_set_nexthop(link); } else { log_link_debug(link, "Setting routes"); link_set_state(link, LINK_STATE_CONFIGURING); diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 6d89be1a25..6b16c0f00a 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -319,10 +319,34 @@ int nexthop_remove(NextHop *nexthop, Link *link, return 0; } -int nexthop_configure( - NextHop *nexthop, - Link *link, - link_netlink_message_handler_t callback) { +static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->nexthop_messages > 0); + + link->nexthop_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_message_warning_errno(link, m, r, "Could not set nexthop"); + link_enter_failed(link); + return 1; + } + + if (link->nexthop_messages == 0) { + log_link_debug(link, "Nexthop set"); + link->static_nexthops_configured = true; + link_check_ready(link); + } + + return 1; +} + +static int nexthop_configure(NextHop *nexthop, Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -331,7 +355,6 @@ int nexthop_configure( assert(link->manager->rtnl); assert(link->ifindex > 0); assert(IN_SET(nexthop->family, AF_INET, AF_INET6)); - assert(callback); if (DEBUG_LOGGING) { _cleanup_free_ char *gw = NULL; @@ -366,7 +389,7 @@ int nexthop_configure( return log_link_error_errno(link, r, "Could not set nexthop family: %m"); } - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + r = netlink_call_async(link->manager->rtnl, NULL, req, nexthop_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -380,6 +403,34 @@ int nexthop_configure( return 1; } +int link_set_nexthop(Link *link) { + NextHop *nh; + int r; + + assert(link); + assert(link->network); + + link->static_nexthops_configured = false; + + LIST_FOREACH(nexthops, nh, link->network->static_nexthops) { + r = nexthop_configure(nh, link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set nexthop: %m"); + if (r > 0) + link->nexthop_messages++; + } + + if (link->nexthop_messages == 0) { + link->static_nexthops_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting nexthop"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 1; +} + int nexthop_section_verify(NextHop *nh) { if (section_is_invalid(nh->section)) return -EINVAL; diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 28cbdad738..cd9958824c 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -34,9 +34,10 @@ extern const struct hash_ops nexthop_hash_ops; int nexthop_new(NextHop **ret); void nexthop_free(NextHop *nexthop); -int nexthop_configure(NextHop *nexthop, Link *link, link_netlink_message_handler_t callback); int nexthop_remove(NextHop *nexthop, Link *link, link_netlink_message_handler_t callback); +int link_set_nexthop(Link *link); + int nexthop_get(Link *link, NextHop *in, NextHop **ret); int nexthop_add(Link *link, NextHop *in, NextHop **ret); int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret); From 454c87b5d53737243a157e319351288c498fea45 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 17:20:40 +0900 Subject: [PATCH 020/138] network: move manager_rtnl_process_nexthop() to networkd-nexthop.c --- src/network/networkd-manager.c | 119 --------------------------------- src/network/networkd-nexthop.c | 119 +++++++++++++++++++++++++++++++++ src/network/networkd-nexthop.h | 2 + 3 files changed, 121 insertions(+), 119 deletions(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 2dc6ef0933..94b036e81e 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -966,125 +966,6 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa return 1; } -static int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - _cleanup_(nexthop_freep) NextHop *tmp = NULL; - _cleanup_free_ char *gateway = NULL; - NextHop *nexthop = NULL; - Link *link = NULL; - uint16_t type; - int r; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); - return 0; - } else if (!IN_SET(type, RTM_NEWNEXTHOP, RTM_DELNEXTHOP)) { - log_warning("rtnl: received unexpected message type %u when processing nexthop, ignoring.", type); - return 0; - } - - r = nexthop_new(&tmp); - if (r < 0) - return log_oom(); - - r = sd_rtnl_message_get_family(message, &tmp->family); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get nexthop family, ignoring: %m"); - return 0; - } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { - log_debug("rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family); - return 0; - } - - switch (tmp->family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, NHA_GATEWAY, &tmp->gw.in); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); - return 0; - } - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, NHA_GATEWAY, &tmp->gw.in6); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); - return 0; - } - break; - - default: - assert_not_reached("Received rule message with unsupported address family"); - } - - r = sd_netlink_message_read_u32(message, NHA_ID, &tmp->id); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get NHA_ID attribute, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, NHA_OIF, &tmp->oif); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get NHA_OIF attribute, ignoring: %m"); - return 0; - } else if (tmp->oif <= 0) { - log_warning("rtnl: received nexthop message with invalid ifindex %d, ignoring.", tmp->oif); - return 0; - } - - r = link_get(m, tmp->oif, &link); - if (r < 0 || !link) { - if (!m->enumerating) - log_warning("rtnl: received nexthop message for link (%d) we do not know about, ignoring", tmp->oif); - return 0; - } - - (void) nexthop_get(link, tmp, &nexthop); - - if (DEBUG_LOGGING) - (void) in_addr_to_string(tmp->family, &tmp->gw, &gateway); - - switch (type) { - case RTM_NEWNEXTHOP: - if (nexthop) - log_link_debug(link, "Received remembered nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); - else { - log_link_debug(link, "Remembering foreign nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); - r = nexthop_add_foreign(link, tmp, &nexthop); - if (r < 0) { - log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m"); - return 0; - } - } - break; - case RTM_DELNEXTHOP: - if (nexthop) { - log_link_debug(link, "Forgetting nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); - nexthop_free(nexthop); - } else - log_link_debug(link, "Kernel removed a nexthop we don't remember: %s, oif: %d, id: %d, ignoring.", - strna(gateway), tmp->oif, tmp->id); - break; - - default: - assert_not_reached("Received invalid RTNL message type"); - } - - return 1; -} - static int systemd_netlink_fd(void) { int n, fd, rtnl_fd = -EINVAL; diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 6b16c0f00a..a4189e8b5a 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -431,6 +431,125 @@ int link_set_nexthop(Link *link) { return 1; } +int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { + _cleanup_(nexthop_freep) NextHop *tmp = NULL; + _cleanup_free_ char *gateway = NULL; + NextHop *nexthop = NULL; + Link *link = NULL; + uint16_t type; + int r; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWNEXTHOP, RTM_DELNEXTHOP)) { + log_warning("rtnl: received unexpected message type %u when processing nexthop, ignoring.", type); + return 0; + } + + r = nexthop_new(&tmp); + if (r < 0) + return log_oom(); + + r = sd_rtnl_message_get_family(message, &tmp->family); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get nexthop family, ignoring: %m"); + return 0; + } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { + log_debug("rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family); + return 0; + } + + switch (tmp->family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, NHA_GATEWAY, &tmp->gw.in); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); + return 0; + } + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, NHA_GATEWAY, &tmp->gw.in6); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); + return 0; + } + break; + + default: + assert_not_reached("Received rule message with unsupported address family"); + } + + r = sd_netlink_message_read_u32(message, NHA_ID, &tmp->id); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_ID attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, NHA_OIF, &tmp->oif); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_OIF attribute, ignoring: %m"); + return 0; + } else if (tmp->oif <= 0) { + log_warning("rtnl: received nexthop message with invalid ifindex %d, ignoring.", tmp->oif); + return 0; + } + + r = link_get(m, tmp->oif, &link); + if (r < 0 || !link) { + if (!m->enumerating) + log_warning("rtnl: received nexthop message for link (%d) we do not know about, ignoring", tmp->oif); + return 0; + } + + (void) nexthop_get(link, tmp, &nexthop); + + if (DEBUG_LOGGING) + (void) in_addr_to_string(tmp->family, &tmp->gw, &gateway); + + switch (type) { + case RTM_NEWNEXTHOP: + if (nexthop) + log_link_debug(link, "Received remembered nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); + else { + log_link_debug(link, "Remembering foreign nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); + r = nexthop_add_foreign(link, tmp, &nexthop); + if (r < 0) { + log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m"); + return 0; + } + } + break; + case RTM_DELNEXTHOP: + if (nexthop) { + log_link_debug(link, "Forgetting nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); + nexthop_free(nexthop); + } else + log_link_debug(link, "Kernel removed a nexthop we don't remember: %s, oif: %d, id: %d, ignoring.", + strna(gateway), tmp->oif, tmp->id); + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + int nexthop_section_verify(NextHop *nh) { if (section_is_invalid(nh->section)) return -EINVAL; diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index cd9958824c..64d92f62be 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -38,6 +38,8 @@ int nexthop_remove(NextHop *nexthop, Link *link, link_netlink_message_handler_t int link_set_nexthop(Link *link); +int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); + int nexthop_get(Link *link, NextHop *in, NextHop **ret); int nexthop_add(Link *link, NextHop *in, NextHop **ret); int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret); From 4736035aaad426bfe55defd18ab6555764388cbd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 17:27:50 +0900 Subject: [PATCH 021/138] network: make several functions static --- src/network/networkd-nexthop.c | 58 ++++++++++++++++++---------------- src/network/networkd-nexthop.h | 8 ----- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index a4189e8b5a..4436aa2a36 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -15,7 +15,33 @@ #include "string-util.h" #include "util.h" -int nexthop_new(NextHop **ret) { +void nexthop_free(NextHop *nexthop) { + if (!nexthop) + return; + + if (nexthop->network) { + LIST_REMOVE(nexthops, nexthop->network->static_nexthops, nexthop); + + assert(nexthop->network->n_static_nexthops > 0); + nexthop->network->n_static_nexthops--; + + if (nexthop->section) + hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section); + } + + network_config_section_free(nexthop->section); + + if (nexthop->link) { + set_remove(nexthop->link->nexthops, nexthop); + set_remove(nexthop->link->nexthops_foreign, nexthop); + } + + free(nexthop); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(NextHop, nexthop_free); + +static int nexthop_new(NextHop **ret) { _cleanup_(nexthop_freep) NextHop *nexthop = NULL; nexthop = new(NextHop, 1); @@ -79,30 +105,6 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s return 0; } -void nexthop_free(NextHop *nexthop) { - if (!nexthop) - return; - - if (nexthop->network) { - LIST_REMOVE(nexthops, nexthop->network->static_nexthops, nexthop); - - assert(nexthop->network->n_static_nexthops > 0); - nexthop->network->n_static_nexthops--; - - if (nexthop->section) - hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section); - } - - network_config_section_free(nexthop->section); - - if (nexthop->link) { - set_remove(nexthop->link->nexthops, nexthop); - set_remove(nexthop->link->nexthops_foreign, nexthop); - } - - free(nexthop); -} - static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) { assert(nexthop); @@ -169,7 +171,7 @@ bool nexthop_equal(NextHop *r1, NextHop *r2) { return nexthop_compare_func(r1, r2) == 0; } -int nexthop_get(Link *link, NextHop *in, NextHop **ret) { +static int nexthop_get(Link *link, NextHop *in, NextHop **ret) { NextHop *existing; assert(link); @@ -225,11 +227,11 @@ static int nexthop_add_internal(Link *link, Set **nexthops, NextHop *in, NextHop return 0; } -int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret) { +static int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret) { return nexthop_add_internal(link, &link->nexthops_foreign, in, ret); } -int nexthop_add(Link *link, NextHop *in, NextHop **ret) { +static int nexthop_add(Link *link, NextHop *in, NextHop **ret) { NextHop *nexthop; int r; diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 64d92f62be..9d5736b3f9 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -30,9 +30,6 @@ struct NextHop { LIST_FIELDS(NextHop, nexthops); }; -extern const struct hash_ops nexthop_hash_ops; - -int nexthop_new(NextHop **ret); void nexthop_free(NextHop *nexthop); int nexthop_remove(NextHop *nexthop, Link *link, link_netlink_message_handler_t callback); @@ -40,14 +37,9 @@ int link_set_nexthop(Link *link); int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); -int nexthop_get(Link *link, NextHop *in, NextHop **ret); -int nexthop_add(Link *link, NextHop *in, NextHop **ret); -int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret); bool nexthop_equal(NextHop *r1, NextHop *r2); int nexthop_section_verify(NextHop *nexthop); -DEFINE_NETWORK_SECTION_FUNCTIONS(NextHop, nexthop_free); - CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id); CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_gateway); From 8d7b137a821b546d1af43875f7f86fb196c07fcb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 17:29:19 +0900 Subject: [PATCH 022/138] network: drop unused nexthop_remove() and nexthop_equal() --- src/network/networkd-nexthop.c | 71 ---------------------------------- src/network/networkd-nexthop.h | 3 -- 2 files changed, 74 deletions(-) diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 4436aa2a36..6ff616d906 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -161,16 +161,6 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( nexthop_compare_func, nexthop_free); -bool nexthop_equal(NextHop *r1, NextHop *r2) { - if (r1 == r2) - return true; - - if (!r1 || !r2) - return false; - - return nexthop_compare_func(r1, r2) == 0; -} - static int nexthop_get(Link *link, NextHop *in, NextHop **ret) { NextHop *existing; @@ -260,67 +250,6 @@ static int nexthop_add(Link *link, NextHop *in, NextHop **ret) { return 0; } -static int nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(m); - assert(link); - assert(link->ifname); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -ESRCH) - log_link_message_warning_errno(link, m, r, "Could not drop nexthop, ignoring"); - - return 1; -} - -int nexthop_remove(NextHop *nexthop, Link *link, - link_netlink_message_handler_t callback) { - - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(link); - assert(link->manager); - assert(link->manager->rtnl); - assert(link->ifindex > 0); - assert(IN_SET(nexthop->family, AF_INET, AF_INET6)); - - r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &req, - RTM_DELNEXTHOP, nexthop->family, - nexthop->protocol); - if (r < 0) - return log_link_error_errno(link, r, "Could not create RTM_DELNEXTHOP message: %m"); - - if (DEBUG_LOGGING) { - _cleanup_free_ char *gw = NULL; - - if (!in_addr_is_null(nexthop->family, &nexthop->gw)) - (void) in_addr_to_string(nexthop->family, &nexthop->gw, &gw); - - log_link_debug(link, "Removing nexthop: gw: %s", strna(gw)); - } - - if (in_addr_is_null(nexthop->family, &nexthop->gw) == 0) { - r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, nexthop->family, &nexthop->gw); - if (r < 0) - return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m"); - } - - r = netlink_call_async(link->manager->rtnl, NULL, req, - callback ?: nexthop_remove_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); - - link_ref(link); - - return 0; -} - static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 9d5736b3f9..af6bf7b0c2 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -31,14 +31,11 @@ struct NextHop { }; void nexthop_free(NextHop *nexthop); -int nexthop_remove(NextHop *nexthop, Link *link, link_netlink_message_handler_t callback); int link_set_nexthop(Link *link); int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); -bool nexthop_equal(NextHop *r1, NextHop *r2); - int nexthop_section_verify(NextHop *nexthop); CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id); From b82663ddee4a4fb140cc53674242cdc334e30c1f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 17:37:56 +0900 Subject: [PATCH 023/138] network: drop list of static nexthops [NextHop] sections are managed by both LIST and Hashmap. Let's drop list, as they store the completely same information. --- src/network/networkd-network.c | 10 ++----- src/network/networkd-network.h | 2 -- src/network/networkd-nexthop.c | 55 +++++++++++++--------------------- src/network/networkd-nexthop.h | 2 -- 4 files changed, 24 insertions(+), 45 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c642e86fda..d8831561c4 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -152,7 +152,7 @@ int network_verify(Network *network) { RoutePrefix *route_prefix, *route_prefix_next; Neighbor *neighbor, *neighbor_next; AddressLabel *label, *label_next; - NextHop *nexthop, *nextnop_next; + NextHop *nexthop; Address *address, *address_next; Prefix *prefix, *prefix_next; Route *route, *route_next; @@ -298,7 +298,7 @@ int network_verify(Network *network) { if (route_section_verify(route, network) < 0) route_free(route); - LIST_FOREACH_SAFE(nexthops, nexthop, nextnop_next, network->static_nexthops) + HASHMAP_FOREACH(nexthop, network->nexthops_by_section) if (nexthop_section_verify(nexthop) < 0) nexthop_free(nexthop); @@ -649,7 +649,6 @@ static Network *network_free(Network *network) { MdbEntry *mdb_entry; Neighbor *neighbor; Address *address; - NextHop *nexthop; Prefix *prefix; Route *route; @@ -711,9 +710,6 @@ static Network *network_free(Network *network) { while ((route = network->static_routes)) route_free(route); - while ((nexthop = network->static_nexthops)) - nexthop_free(nexthop); - while ((address = network->static_addresses)) address_free(address); @@ -740,7 +736,7 @@ static Network *network_free(Network *network) { hashmap_free(network->addresses_by_section); hashmap_free(network->routes_by_section); - hashmap_free(network->nexthops_by_section); + hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free); hashmap_free(network->fdb_entries_by_section); hashmap_free(network->mdb_entries_by_section); hashmap_free(network->neighbors_by_section); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index bc006944d7..c92b751866 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -286,7 +286,6 @@ struct Network { LIST_HEAD(Address, static_addresses); LIST_HEAD(Route, static_routes); - LIST_HEAD(NextHop, static_nexthops); LIST_HEAD(FdbEntry, static_fdb_entries); LIST_HEAD(MdbEntry, static_mdb_entries); LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); @@ -297,7 +296,6 @@ struct Network { unsigned n_static_addresses; unsigned n_static_routes; - unsigned n_static_nexthops; unsigned n_static_fdb_entries; unsigned n_static_mdb_entries; unsigned n_ipv6_proxy_ndp_addresses; diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 6ff616d906..6c9d1c57dd 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -20,13 +20,8 @@ void nexthop_free(NextHop *nexthop) { return; if (nexthop->network) { - LIST_REMOVE(nexthops, nexthop->network->static_nexthops, nexthop); - - assert(nexthop->network->n_static_nexthops > 0); - nexthop->network->n_static_nexthops--; - - if (nexthop->section) - hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section); + assert(nexthop->section); + hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section); } network_config_section_free(nexthop->section); @@ -64,19 +59,17 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; - nexthop = hashmap_get(network->nexthops_by_section, n); - if (nexthop) { - *ret = TAKE_PTR(nexthop); - - return 0; - } + nexthop = hashmap_get(network->nexthops_by_section, n); + if (nexthop) { + *ret = TAKE_PTR(nexthop); + return 0; } r = nexthop_new(&nexthop); @@ -85,23 +78,17 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s nexthop->protocol = RTPROT_STATIC; nexthop->network = network; - LIST_PREPEND(nexthops, network->static_nexthops, nexthop); - network->n_static_nexthops++; + nexthop->section = TAKE_PTR(n); - if (filename) { - nexthop->section = TAKE_PTR(n); + r = hashmap_ensure_allocated(&network->nexthops_by_section, &network_config_hash_ops); + if (r < 0) + return r; - r = hashmap_ensure_allocated(&network->nexthops_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->nexthops_by_section, nexthop->section, nexthop); - if (r < 0) - return r; - } + r = hashmap_put(network->nexthops_by_section, nexthop->section, nexthop); + if (r < 0) + return r; *ret = TAKE_PTR(nexthop); - return 0; } @@ -343,12 +330,12 @@ int link_set_nexthop(Link *link) { link->static_nexthops_configured = false; - LIST_FOREACH(nexthops, nh, link->network->static_nexthops) { + HASHMAP_FOREACH(nh, link->network->nexthops_by_section) { r = nexthop_configure(nh, link); if (r < 0) return log_link_warning_errno(link, r, "Could not set nexthop: %m"); - if (r > 0) - link->nexthop_messages++; + + link->nexthop_messages++; } if (link->nexthop_messages == 0) { diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index af6bf7b0c2..2ff8b4b81e 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -26,8 +26,6 @@ struct NextHop { uint32_t id; union in_addr_union gw; - - LIST_FIELDS(NextHop, nexthops); }; void nexthop_free(NextHop *nexthop); From 75156ccbdcae8f83235ac718a65dedaa631d5b2a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 17:47:28 +0900 Subject: [PATCH 024/138] network: cleanup headers included in networkd-nexthop.h --- src/network/networkd-link.c | 1 + src/network/networkd-manager.c | 1 + src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 - src/network/networkd-nexthop.c | 11 +++++------ src/network/networkd-nexthop.h | 24 +++++++++++++----------- 7 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index dca9b1550c..e5d51f1572 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -32,6 +32,7 @@ #include "networkd-manager.h" #include "networkd-ndisc.h" #include "networkd-neighbor.h" +#include "networkd-nexthop.h" #include "networkd-sriov.h" #include "networkd-radv.h" #include "networkd-routing-policy-rule.h" diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 94b036e81e..0a0fb36f95 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -30,6 +30,7 @@ #include "networkd-manager-bus.h" #include "networkd-manager.h" #include "networkd-network-bus.h" +#include "networkd-nexthop.h" #include "networkd-routing-policy-rule.h" #include "networkd-speed-meter.h" #include "ordered-set.h" diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index b3f3a22d07..25a7b8991a 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -15,6 +15,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "networkd-ipv4ll.h" #include "networkd-ndisc.h" #include "networkd-network.h" +#include "networkd-nexthop.h" #include "networkd-routing-policy-rule.h" #include "networkd-sriov.h" #include "qdisc.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index d8831561c4..d04d523c32 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -16,6 +16,7 @@ #include "network-internal.h" #include "networkd-manager.h" #include "networkd-network.h" +#include "networkd-nexthop.h" #include "networkd-routing-policy-rule.h" #include "networkd-sriov.h" #include "parse-util.h" diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index c92b751866..12ec6ef1b2 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -26,7 +26,6 @@ #include "networkd-mdb.h" #include "networkd-ndisc.h" #include "networkd-neighbor.h" -#include "networkd-nexthop.h" #include "networkd-radv.h" #include "networkd-route.h" #include "networkd-util.h" diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 6c9d1c57dd..4f40883e54 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -5,19 +5,18 @@ #include #include "alloc-util.h" -#include "conf-parser.h" -#include "in-addr-util.h" #include "netlink-util.h" +#include "networkd-link.h" #include "networkd-manager.h" +#include "networkd-network.h" #include "networkd-nexthop.h" #include "parse-util.h" #include "set.h" #include "string-util.h" -#include "util.h" -void nexthop_free(NextHop *nexthop) { +NextHop *nexthop_free(NextHop *nexthop) { if (!nexthop) - return; + return NULL; if (nexthop->network) { assert(nexthop->section); @@ -31,7 +30,7 @@ void nexthop_free(NextHop *nexthop) { set_remove(nexthop->link->nexthops_foreign, nexthop); } - free(nexthop); + return mfree(nexthop); } DEFINE_NETWORK_SECTION_FUNCTIONS(NextHop, nexthop_free); diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 2ff8b4b81e..7d1705904f 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -4,16 +4,19 @@ #pragma once +#include + +#include "sd-netlink.h" + #include "conf-parser.h" -#include "macro.h" - -typedef struct NextHop NextHop; -typedef struct NetworkConfigSection NetworkConfigSection; - -#include "networkd-network.h" +#include "in-addr-util.h" #include "networkd-util.h" -struct NextHop { +typedef struct Link Link; +typedef struct Manager Manager; +typedef struct Network Network; + +typedef struct NextHop { Network *network; NetworkConfigSection *section; @@ -26,15 +29,14 @@ struct NextHop { uint32_t id; union in_addr_union gw; -}; +} NextHop; -void nexthop_free(NextHop *nexthop); +NextHop *nexthop_free(NextHop *nexthop); +int nexthop_section_verify(NextHop *nexthop); int link_set_nexthop(Link *link); int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); -int nexthop_section_verify(NextHop *nexthop); - CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id); CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_gateway); From cf5a228f7b17d73f1f49e07882ed87a1f7362c99 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 21:53:05 +0900 Subject: [PATCH 025/138] network: slightly shorten nexthop_compare_func() --- src/network/networkd-nexthop.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 4f40883e54..03e4bd152a 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -125,19 +125,10 @@ static int nexthop_compare_func(const NextHop *a, const NextHop *b) { if (r != 0) return r; - switch (a->family) { - case AF_INET: - case AF_INET6: + if (IN_SET(a->family, AF_INET, AF_INET6)) + return memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family)); - r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family)); - if (r != 0) - return r; - - return 0; - default: - /* treat any other address family as AF_UNSPEC */ - return 0; - } + return 0; } DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( From 8c112218793458bd6f9f062865599eef3fa061c3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 22:20:23 +0900 Subject: [PATCH 026/138] network: drop NextHop::oif and always use link ifindex --- src/network/networkd-nexthop.c | 54 ++++++++++++++++------------------ src/network/networkd-nexthop.h | 4 +-- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 03e4bd152a..48f00b218b 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -95,7 +95,6 @@ static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) { assert(nexthop); siphash24_compress(&nexthop->id, sizeof(nexthop->id), state); - siphash24_compress(&nexthop->oif, sizeof(nexthop->oif), state); siphash24_compress(&nexthop->family, sizeof(nexthop->family), state); switch (nexthop->family) { @@ -117,10 +116,6 @@ static int nexthop_compare_func(const NextHop *a, const NextHop *b) { if (r != 0) return r; - r = CMP(a->oif, b->oif); - if (r != 0) - return r; - r = CMP(a->family, b->family); if (r != 0) return r; @@ -174,7 +169,6 @@ static int nexthop_add_internal(Link *link, Set **nexthops, NextHop *in, NextHop return r; nexthop->id = in->id; - nexthop->oif = in->oif; nexthop->family = in->family; nexthop->gw = in->gw; @@ -343,8 +337,9 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, _cleanup_(nexthop_freep) NextHop *tmp = NULL; _cleanup_free_ char *gateway = NULL; NextHop *nexthop = NULL; - Link *link = NULL; + uint32_t ifindex; uint16_t type; + Link *link; int r; assert(rtnl); @@ -368,6 +363,25 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, return 0; } + r = sd_netlink_message_read_u32(message, NHA_OIF, &ifindex); + if (r == -ENODATA) { + log_warning_errno(r, "rtnl: received nexthop message without NHA_OIF attribute, ignoring: %m"); + return 0; + } else if (r < 0) { + log_warning_errno(r, "rtnl: could not get NHA_OIF attribute, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received nexthop message with invalid ifindex %"PRIu32", ignoring.", ifindex); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0 || !link) { + if (!m->enumerating) + log_warning("rtnl: received nexthop message for link (%"PRIu32") we do not know about, ignoring", ifindex); + return 0; + } + r = nexthop_new(&tmp); if (r < 0) return log_oom(); @@ -408,22 +422,6 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, return 0; } - r = sd_netlink_message_read_u32(message, NHA_OIF, &tmp->oif); - if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get NHA_OIF attribute, ignoring: %m"); - return 0; - } else if (tmp->oif <= 0) { - log_warning("rtnl: received nexthop message with invalid ifindex %d, ignoring.", tmp->oif); - return 0; - } - - r = link_get(m, tmp->oif, &link); - if (r < 0 || !link) { - if (!m->enumerating) - log_warning("rtnl: received nexthop message for link (%d) we do not know about, ignoring", tmp->oif); - return 0; - } - (void) nexthop_get(link, tmp, &nexthop); if (DEBUG_LOGGING) @@ -432,9 +430,9 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, switch (type) { case RTM_NEWNEXTHOP: if (nexthop) - log_link_debug(link, "Received remembered nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); + log_link_debug(link, "Received remembered nexthop: %s, id: %d", strna(gateway), tmp->id); else { - log_link_debug(link, "Remembering foreign nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); + log_link_debug(link, "Remembering foreign nexthop: %s, id: %d", strna(gateway), tmp->id); r = nexthop_add_foreign(link, tmp, &nexthop); if (r < 0) { log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m"); @@ -444,11 +442,11 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, break; case RTM_DELNEXTHOP: if (nexthop) { - log_link_debug(link, "Forgetting nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); + log_link_debug(link, "Forgetting nexthop: %s, id: %d", strna(gateway), tmp->id); nexthop_free(nexthop); } else - log_link_debug(link, "Kernel removed a nexthop we don't remember: %s, oif: %d, id: %d, ignoring.", - strna(gateway), tmp->oif, tmp->id); + log_link_debug(link, "Kernel removed a nexthop we don't remember: %s, id: %d, ignoring.", + strna(gateway), tmp->id); break; default: diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 7d1705904f..8f4686d864 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -24,10 +24,8 @@ typedef struct NextHop { unsigned char protocol; - int family; - uint32_t oif; uint32_t id; - + int family; union in_addr_union gw; } NextHop; From 47a277f18ba147bb74bd186752558ab90809689f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 22:21:52 +0900 Subject: [PATCH 027/138] network: use log_link_xxx() at more places --- src/network/networkd-nexthop.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 48f00b218b..f7815a3864 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -388,18 +388,16 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, r = sd_rtnl_message_get_family(message, &tmp->family); if (r < 0) { - log_warning_errno(r, "rtnl: could not get nexthop family, ignoring: %m"); + log_link_warning_errno(link, r, "rtnl: could not get nexthop family, ignoring: %m"); return 0; - } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { - log_debug("rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family); - return 0; - } + } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) + return log_link_debug(link, "rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family); switch (tmp->family) { case AF_INET: r = sd_netlink_message_read_in_addr(message, NHA_GATEWAY, &tmp->gw.in); if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); + log_link_warning_errno(link, r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); return 0; } break; @@ -407,7 +405,7 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, case AF_INET6: r = sd_netlink_message_read_in6_addr(message, NHA_GATEWAY, &tmp->gw.in6); if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); + log_link_warning_errno(link, r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); return 0; } break; @@ -418,7 +416,7 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, r = sd_netlink_message_read_u32(message, NHA_ID, &tmp->id); if (r < 0 && r != -ENODATA) { - log_warning_errno(r, "rtnl: could not get NHA_ID attribute, ignoring: %m"); + log_link_warning_errno(link, r, "rtnl: could not get NHA_ID attribute, ignoring: %m"); return 0; } From f29b6b371e39acc3c9028231a4fdcb8e8ee7d2b5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 22:34:37 +0900 Subject: [PATCH 028/138] sd-netlink: introduce netlink_message_read_in_addr_union() --- src/libsystemd/sd-netlink/netlink-message.c | 37 +++++++++++---------- src/libsystemd/sd-netlink/netlink-util.h | 2 ++ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index d6bf31efc7..0d9a57ee9e 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -862,11 +862,12 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ return 0; } -int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) { - int r; +int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short type, int family, union in_addr_union *data) { void *attr_data; + int r; assert_return(m, -EINVAL); + assert_return(IN_SET(family, AF_INET, AF_INET6), -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); if (r < 0) @@ -875,35 +876,35 @@ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; - else if ((size_t) r < sizeof(struct in_addr)) + else if ((size_t) r < FAMILY_ADDRESS_SIZE(family)) return -EIO; if (data) - memcpy(data, attr_data, sizeof(struct in_addr)); + memcpy(data, attr_data, FAMILY_ADDRESS_SIZE(family)); return 0; } -int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) { +int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) { + union in_addr_union u; int r; - void *attr_data; - assert_return(m, -EINVAL); + r = netlink_message_read_in_addr_union(m, type, AF_INET, &u); + if (r >= 0 && data) + *data = u.in; - r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); - if (r < 0) - return r; + return r; +} - r = netlink_message_read_internal(m, type, &attr_data, NULL); - if (r < 0) - return r; - else if ((size_t) r < sizeof(struct in6_addr)) - return -EIO; +int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) { + union in_addr_union u; + int r; - if (data) - memcpy(data, attr_data, sizeof(struct in6_addr)); + r = netlink_message_read_in_addr_union(m, type, AF_INET6, &u); + if (r >= 0 && data) + *data = u.in6; - return 0; + return r; } int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) { diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h index 8e99cd451d..fa17e7dae7 100644 --- a/src/libsystemd/sd-netlink/netlink-util.h +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -90,5 +90,7 @@ int rtnl_log_create_error(int r); int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data); int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data); +int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short type, int family, union in_addr_union *data); + void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length); int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void *data, size_t data_length); From f96f4ebc85b7ea64aa9192cea0878177d218826a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 22:35:03 +0900 Subject: [PATCH 029/138] network: use netlink_message_read_in_addr_union() --- src/network/networkd-nexthop.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index f7815a3864..61c33f4900 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -393,25 +393,10 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) return log_link_debug(link, "rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family); - switch (tmp->family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, NHA_GATEWAY, &tmp->gw.in); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); - return 0; - } - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, NHA_GATEWAY, &tmp->gw.in6); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); - return 0; - } - break; - - default: - assert_not_reached("Received rule message with unsupported address family"); + r = netlink_message_read_in_addr_union(message, NHA_GATEWAY, tmp->family, &tmp->gw); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); + return 0; } r = sd_netlink_message_read_u32(message, NHA_ID, &tmp->id); From 0992f9fb0ed684e603d0517146a07aaa0f61e4d3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 00:58:01 +0900 Subject: [PATCH 030/138] network: introduce network_verify_nexthops() --- src/network/networkd-network.c | 5 +---- src/network/networkd-nexthop.c | 12 +++++++++++- src/network/networkd-nexthop.h | 3 ++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index d04d523c32..de15074550 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -153,7 +153,6 @@ int network_verify(Network *network) { RoutePrefix *route_prefix, *route_prefix_next; Neighbor *neighbor, *neighbor_next; AddressLabel *label, *label_next; - NextHop *nexthop; Address *address, *address_next; Prefix *prefix, *prefix_next; Route *route, *route_next; @@ -299,9 +298,7 @@ int network_verify(Network *network) { if (route_section_verify(route, network) < 0) route_free(route); - HASHMAP_FOREACH(nexthop, network->nexthops_by_section) - if (nexthop_section_verify(nexthop) < 0) - nexthop_free(nexthop); + network_verify_nexthops(network); LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries) if (section_is_invalid(fdb->section)) diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 61c33f4900..1f03cbfe07 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -439,7 +439,7 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, return 1; } -int nexthop_section_verify(NextHop *nh) { +static int nexthop_section_verify(NextHop *nh) { if (section_is_invalid(nh->section)) return -EINVAL; @@ -449,6 +449,16 @@ int nexthop_section_verify(NextHop *nh) { return 0; } +void network_verify_nexthops(Network *network) { + NextHop *nh; + + assert(network); + + HASHMAP_FOREACH(nh, network->nexthops_by_section) + if (nexthop_section_verify(nh) < 0) + nexthop_free(nh); +} + int config_parse_nexthop_id( const char *unit, const char *filename, diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 8f4686d864..f286f0e61e 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -30,7 +30,8 @@ typedef struct NextHop { } NextHop; NextHop *nexthop_free(NextHop *nexthop); -int nexthop_section_verify(NextHop *nexthop); + +void network_verify_nexthops(Network *network); int link_set_nexthop(Link *link); From fceee7cc7ef13c63205c739ca69d1e630bbecc0c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 23:15:41 +0900 Subject: [PATCH 031/138] network: move functions --- src/network/networkd-neighbor.c | 236 ++++++++++++++++---------------- 1 file changed, 118 insertions(+), 118 deletions(-) diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 09ddb9c8a5..26ef94328f 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -87,124 +87,6 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned return 0; } -static int neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(m); - assert(link); - assert(link->neighbor_messages > 0); - - link->neighbor_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - /* Neighbor may not exist yet. So, do not enter failed state here. */ - log_link_message_warning_errno(link, m, r, "Could not set neighbor, ignoring"); - - if (link->neighbor_messages == 0) { - log_link_debug(link, "Neighbors set"); - link->neighbors_configured = true; - link_check_ready(link); - } - - return 1; -} - -int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(neighbor); - assert(link); - assert(link->ifindex > 0); - assert(link->manager); - assert(link->manager->rtnl); - - r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, - link->ifindex, neighbor->family); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_NEWNEIGH message: %m"); - - r = sd_rtnl_message_neigh_set_state(req, NUD_PERMANENT); - if (r < 0) - return log_link_error_errno(link, r, "Could not set state: %m"); - - r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE); - if (r < 0) - return log_link_error_errno(link, r, "Could not set flags: %m"); - - r = sd_netlink_message_append_data(req, NDA_LLADDR, &neighbor->lladdr, neighbor->lladdr_size); - if (r < 0) - return log_link_error_errno(link, r, "Could not append NDA_LLADDR attribute: %m"); - - r = netlink_message_append_in_addr_union(req, NDA_DST, neighbor->family, &neighbor->in_addr); - if (r < 0) - return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); - - r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_configure_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); - - link->neighbor_messages++; - link_ref(link); - - r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Could not add neighbor: %m"); - - return 0; -} - -static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(m); - assert(link); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -ESRCH) - /* Neighbor may not exist because it already got deleted, ignore that. */ - log_link_message_warning_errno(link, m, r, "Could not remove neighbor"); - - return 1; -} - -int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(neighbor); - assert(link); - assert(link->ifindex > 0); - assert(link->manager); - assert(link->manager->rtnl); - - r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_DELNEIGH, - link->ifindex, neighbor->family); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_DELNEIGH message: %m"); - - r = netlink_message_append_in_addr_union(req, NDA_DST, neighbor->family, &neighbor->in_addr); - if (r < 0) - return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); - - r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_remove_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); - - link_ref(link); - - return 0; -} - static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) { assert(neighbor); @@ -356,6 +238,124 @@ bool neighbor_equal(const Neighbor *n1, const Neighbor *n2) { return neighbor_compare_func(n1, n2) == 0; } +static int neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->neighbor_messages > 0); + + link->neighbor_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) + /* Neighbor may not exist yet. So, do not enter failed state here. */ + log_link_message_warning_errno(link, m, r, "Could not set neighbor, ignoring"); + + if (link->neighbor_messages == 0) { + log_link_debug(link, "Neighbors set"); + link->neighbors_configured = true; + link_check_ready(link); + } + + return 1; +} + +int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(neighbor); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, + link->ifindex, neighbor->family); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_NEWNEIGH message: %m"); + + r = sd_rtnl_message_neigh_set_state(req, NUD_PERMANENT); + if (r < 0) + return log_link_error_errno(link, r, "Could not set state: %m"); + + r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE); + if (r < 0) + return log_link_error_errno(link, r, "Could not set flags: %m"); + + r = sd_netlink_message_append_data(req, NDA_LLADDR, &neighbor->lladdr, neighbor->lladdr_size); + if (r < 0) + return log_link_error_errno(link, r, "Could not append NDA_LLADDR attribute: %m"); + + r = netlink_message_append_in_addr_union(req, NDA_DST, neighbor->family, &neighbor->in_addr); + if (r < 0) + return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_configure_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link->neighbor_messages++; + link_ref(link); + + r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Could not add neighbor: %m"); + + return 0; +} + +static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -ESRCH) + /* Neighbor may not exist because it already got deleted, ignore that. */ + log_link_message_warning_errno(link, m, r, "Could not remove neighbor"); + + return 1; +} + +int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(neighbor); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_DELNEIGH, + link->ifindex, neighbor->family); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_DELNEIGH message: %m"); + + r = netlink_message_append_in_addr_union(req, NDA_DST, neighbor->family, &neighbor->in_addr); + if (r < 0) + return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_remove_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + int neighbor_section_verify(Neighbor *neighbor) { if (section_is_invalid(neighbor->section)) return -EINVAL; From 58f1fe9af9429c994c0a94ea3762d66a596ec261 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 23:17:43 +0900 Subject: [PATCH 032/138] network: move link_request_set_neighbors() to networkd-neighbor.c --- src/network/networkd-link.c | 29 +---------------------------- src/network/networkd-neighbor.c | 27 +++++++++++++++++++++++++++ src/network/networkd-neighbor.h | 2 ++ 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index e5d51f1572..6df7ce74a0 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1131,33 +1131,6 @@ void link_check_ready(Link *link) { return; } -static int link_request_set_neighbors(Link *link) { - Neighbor *neighbor; - int r; - - assert(link); - assert(link->network); - assert(link->state != _LINK_STATE_INVALID); - - link->neighbors_configured = false; - - LIST_FOREACH(neighbors, neighbor, link->network->neighbors) { - r = neighbor_configure(neighbor, link, NULL); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set neighbor: %m"); - } - - if (link->neighbor_messages == 0) { - link->neighbors_configured = true; - link_check_ready(link); - } else { - log_link_debug(link, "Setting neighbors"); - link_set_state(link, LINK_STATE_CONFIGURING); - } - - return 0; -} - static int link_set_bridge_fdb(Link *link) { FdbEntry *fdb_entry; int r; @@ -1307,7 +1280,7 @@ static int link_request_set_addresses(Link *link) { if (r < 0) return r; - r = link_request_set_neighbors(link); + r = link_set_neighbors(link); if (r < 0) return r; diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 26ef94328f..b9c149121c 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -310,6 +310,33 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand return 0; } +int link_set_neighbors(Link *link) { + Neighbor *neighbor; + int r; + + assert(link); + assert(link->network); + assert(link->state != _LINK_STATE_INVALID); + + link->neighbors_configured = false; + + LIST_FOREACH(neighbors, neighbor, link->network->neighbors) { + r = neighbor_configure(neighbor, link, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set neighbor: %m"); + } + + if (link->neighbor_messages == 0) { + link->neighbors_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting neighbors"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 97ee1f6d73..bba59f0227 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -47,6 +47,8 @@ bool neighbor_equal(const Neighbor *n1, const Neighbor *n2); int neighbor_section_verify(Neighbor *neighbor); +int link_set_neighbors(Link *link); + CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address); CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr); CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr); From eab052d2b3e73b6b3787d00131ae2d191e7a4ec6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 23:20:14 +0900 Subject: [PATCH 033/138] network: move manager_rtnl_process_neighbor() to networkd-neighbor.c --- src/network/networkd-manager.c | 180 -------------------------------- src/network/networkd-neighbor.c | 180 ++++++++++++++++++++++++++++++++ src/network/networkd-neighbor.h | 2 + 3 files changed, 182 insertions(+), 180 deletions(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 0a0fb36f95..37a9745df8 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -538,186 +538,6 @@ static int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *mess return 1; } -static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) { - int r; - - assert(message); - assert(lladdr); - assert(size); - assert(str); - - *str = NULL; - - r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in6), &lladdr->ip.in6); - if (r >= 0) { - *size = sizeof(lladdr->ip.in6); - if (in_addr_to_string(AF_INET6, &lladdr->ip, str) < 0) - log_warning_errno(r, "Could not print lower address: %m"); - return r; - } - - r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->mac), &lladdr->mac); - if (r >= 0) { - *size = sizeof(lladdr->mac); - *str = new(char, ETHER_ADDR_TO_STRING_MAX); - if (!*str) { - log_oom(); - return r; - } - ether_addr_to_string(&lladdr->mac, *str); - return r; - } - - r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in), &lladdr->ip.in); - if (r >= 0) { - *size = sizeof(lladdr->ip.in); - if (in_addr_to_string(AF_INET, &lladdr->ip, str) < 0) - log_warning_errno(r, "Could not print lower address: %m"); - return r; - } - - return r; -} - -static int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - Link *link = NULL; - Neighbor *neighbor = NULL; - int ifindex, family, r; - uint16_t type, state; - union in_addr_union in_addr = IN_ADDR_NULL; - _cleanup_free_ char *addr_str = NULL; - union lladdr_union lladdr; - size_t lladdr_size = 0; - _cleanup_free_ char *lladdr_str = NULL; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_message_warning_errno(message, r, "rtnl: failed to receive neighbor message, ignoring"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); - return 0; - } else if (!IN_SET(type, RTM_NEWNEIGH, RTM_DELNEIGH)) { - log_warning("rtnl: received unexpected message type %u when processing neighbor, ignoring.", type); - return 0; - } - - r = sd_rtnl_message_neigh_get_state(message, &state); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid state, ignoring: %m"); - return 0; - } else if (!FLAGS_SET(state, NUD_PERMANENT)) { - log_debug("rtnl: received non-static neighbor, ignoring."); - return 0; - } - - r = sd_rtnl_message_neigh_get_ifindex(message, &ifindex); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received neighbor message with invalid ifindex %d, ignoring.", ifindex); - return 0; - } - - r = link_get(m, ifindex, &link); - if (r < 0 || !link) { - /* when enumerating we might be out of sync, but we will get the neighbor again, so just - * ignore it */ - if (!m->enumerating) - log_warning("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex); - return 0; - } - - r = sd_rtnl_message_neigh_get_family(message, &family); - if (r < 0) { - log_link_warning(link, "rtnl: received neighbor message without family, ignoring."); - return 0; - } else if (!IN_SET(family, AF_INET, AF_INET6)) { - log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", family); - return 0; - } - - switch (family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, NDA_DST, &in_addr.in); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m"); - return 0; - } - - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, NDA_DST, &in_addr.in6); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m"); - return 0; - } - - break; - - default: - assert_not_reached("Received unsupported address family"); - } - - if (in_addr_to_string(family, &in_addr, &addr_str) < 0) - log_link_warning_errno(link, r, "Could not print address: %m"); - - r = manager_rtnl_process_neighbor_lladdr(message, &lladdr, &lladdr_size, &lladdr_str); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m"); - return 0; - } - - (void) neighbor_get(link, family, &in_addr, &lladdr, lladdr_size, &neighbor); - - switch (type) { - case RTM_NEWNEIGH: - if (neighbor) - log_link_debug(link, "Received remembered neighbor: %s->%s", - strnull(addr_str), strnull(lladdr_str)); - else { - /* A neighbor appeared that we did not request */ - r = neighbor_add_foreign(link, family, &in_addr, &lladdr, lladdr_size, &neighbor); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m", - strnull(addr_str), strnull(lladdr_str)); - return 0; - } else - log_link_debug(link, "Remembering foreign neighbor: %s->%s", - strnull(addr_str), strnull(lladdr_str)); - } - - break; - - case RTM_DELNEIGH: - if (neighbor) { - log_link_debug(link, "Forgetting neighbor: %s->%s", - strnull(addr_str), strnull(lladdr_str)); - (void) neighbor_free(neighbor); - } else - log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.", - strnull(addr_str), strnull(lladdr_str)); - - break; - - default: - assert_not_reached("Received invalid RTNL message type"); - } - - return 1; -} - int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_free_ char *buf = NULL; Link *link = NULL; diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index b9c149121c..3eec965533 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -383,6 +383,186 @@ int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler return 0; } +static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) { + int r; + + assert(message); + assert(lladdr); + assert(size); + assert(str); + + *str = NULL; + + r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in6), &lladdr->ip.in6); + if (r >= 0) { + *size = sizeof(lladdr->ip.in6); + if (in_addr_to_string(AF_INET6, &lladdr->ip, str) < 0) + log_warning_errno(r, "Could not print lower address: %m"); + return r; + } + + r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->mac), &lladdr->mac); + if (r >= 0) { + *size = sizeof(lladdr->mac); + *str = new(char, ETHER_ADDR_TO_STRING_MAX); + if (!*str) { + log_oom(); + return r; + } + ether_addr_to_string(&lladdr->mac, *str); + return r; + } + + r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in), &lladdr->ip.in); + if (r >= 0) { + *size = sizeof(lladdr->ip.in); + if (in_addr_to_string(AF_INET, &lladdr->ip, str) < 0) + log_warning_errno(r, "Could not print lower address: %m"); + return r; + } + + return r; +} + +int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { + Link *link = NULL; + Neighbor *neighbor = NULL; + int ifindex, family, r; + uint16_t type, state; + union in_addr_union in_addr = IN_ADDR_NULL; + _cleanup_free_ char *addr_str = NULL; + union lladdr_union lladdr; + size_t lladdr_size = 0; + _cleanup_free_ char *lladdr_str = NULL; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_message_warning_errno(message, r, "rtnl: failed to receive neighbor message, ignoring"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWNEIGH, RTM_DELNEIGH)) { + log_warning("rtnl: received unexpected message type %u when processing neighbor, ignoring.", type); + return 0; + } + + r = sd_rtnl_message_neigh_get_state(message, &state); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid state, ignoring: %m"); + return 0; + } else if (!FLAGS_SET(state, NUD_PERMANENT)) { + log_debug("rtnl: received non-static neighbor, ignoring."); + return 0; + } + + r = sd_rtnl_message_neigh_get_ifindex(message, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received neighbor message with invalid ifindex %d, ignoring.", ifindex); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0 || !link) { + /* when enumerating we might be out of sync, but we will get the neighbor again, so just + * ignore it */ + if (!m->enumerating) + log_warning("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex); + return 0; + } + + r = sd_rtnl_message_neigh_get_family(message, &family); + if (r < 0) { + log_link_warning(link, "rtnl: received neighbor message without family, ignoring."); + return 0; + } else if (!IN_SET(family, AF_INET, AF_INET6)) { + log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", family); + return 0; + } + + switch (family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, NDA_DST, &in_addr.in); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m"); + return 0; + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, NDA_DST, &in_addr.in6); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m"); + return 0; + } + + break; + + default: + assert_not_reached("Received unsupported address family"); + } + + if (in_addr_to_string(family, &in_addr, &addr_str) < 0) + log_link_warning_errno(link, r, "Could not print address: %m"); + + r = manager_rtnl_process_neighbor_lladdr(message, &lladdr, &lladdr_size, &lladdr_str); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m"); + return 0; + } + + (void) neighbor_get(link, family, &in_addr, &lladdr, lladdr_size, &neighbor); + + switch (type) { + case RTM_NEWNEIGH: + if (neighbor) + log_link_debug(link, "Received remembered neighbor: %s->%s", + strnull(addr_str), strnull(lladdr_str)); + else { + /* A neighbor appeared that we did not request */ + r = neighbor_add_foreign(link, family, &in_addr, &lladdr, lladdr_size, &neighbor); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m", + strnull(addr_str), strnull(lladdr_str)); + return 0; + } else + log_link_debug(link, "Remembering foreign neighbor: %s->%s", + strnull(addr_str), strnull(lladdr_str)); + } + + break; + + case RTM_DELNEIGH: + if (neighbor) { + log_link_debug(link, "Forgetting neighbor: %s->%s", + strnull(addr_str), strnull(lladdr_str)); + (void) neighbor_free(neighbor); + } else + log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.", + strnull(addr_str), strnull(lladdr_str)); + + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + int neighbor_section_verify(Neighbor *neighbor) { if (section_is_invalid(neighbor->section)) return -EINVAL; diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index bba59f0227..3f21a25c2f 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -49,6 +49,8 @@ int neighbor_section_verify(Neighbor *neighbor); int link_set_neighbors(Link *link); +int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); + CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address); CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr); CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr); From b0ba6938df4b096ecd0f956bd501b564b6da7295 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 29 Sep 2020 23:31:38 +0900 Subject: [PATCH 034/138] network: drop list of static neighbors [Neighbor] sections are managed by both LIST and Hashmap. Let's drop list, as they store the completely same information. --- src/network/networkd-link.c | 2 +- src/network/networkd-neighbor.c | 51 ++++++++++++--------------------- src/network/networkd-neighbor.h | 2 -- src/network/networkd-network.c | 12 +++----- src/network/networkd-network.h | 2 -- 5 files changed, 24 insertions(+), 45 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 6df7ce74a0..48cf83a753 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2602,7 +2602,7 @@ static bool link_is_neighbor_configured(Link *link, Neighbor *neighbor) { if (!link->network) return false; - LIST_FOREACH(neighbors, net_neighbor, link->network->neighbors) + HASHMAP_FOREACH(net_neighbor, link->network->neighbors_by_section) if (neighbor_equal(net_neighbor, neighbor)) return true; diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 3eec965533..0b4ceafb31 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -18,12 +18,8 @@ void neighbor_free(Neighbor *neighbor) { return; if (neighbor->network) { - LIST_REMOVE(neighbors, neighbor->network->neighbors, neighbor); - assert(neighbor->network->n_neighbors > 0); - neighbor->network->n_neighbors--; - - if (neighbor->section) - hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section); + assert(neighbor->section); + hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section); } network_config_section_free(neighbor->section); @@ -43,19 +39,17 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; - neighbor = hashmap_get(network->neighbors_by_section, n); - if (neighbor) { - *ret = TAKE_PTR(neighbor); - - return 0; - } + neighbor = hashmap_get(network->neighbors_by_section, n); + if (neighbor) { + *ret = TAKE_PTR(neighbor); + return 0; } neighbor = new(Neighbor, 1); @@ -65,25 +59,18 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned *neighbor = (Neighbor) { .network = network, .family = AF_UNSPEC, + .section = TAKE_PTR(n), }; - LIST_APPEND(neighbors, network->neighbors, neighbor); - network->n_neighbors++; + r = hashmap_ensure_allocated(&network->neighbors_by_section, &network_config_hash_ops); + if (r < 0) + return r; - if (filename) { - neighbor->section = TAKE_PTR(n); - - r = hashmap_ensure_allocated(&network->neighbors_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->neighbors_by_section, neighbor->section, neighbor); - if (r < 0) - return r; - } + r = hashmap_put(network->neighbors_by_section, neighbor->section, neighbor); + if (r < 0) + return r; *ret = TAKE_PTR(neighbor); - return 0; } @@ -320,7 +307,7 @@ int link_set_neighbors(Link *link) { link->neighbors_configured = false; - LIST_FOREACH(neighbors, neighbor, link->network->neighbors) { + HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) { r = neighbor_configure(neighbor, link, NULL); if (r < 0) return log_link_warning_errno(link, r, "Could not set neighbor: %m"); diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 3f21a25c2f..34083cf526 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -29,8 +29,6 @@ struct Neighbor { union in_addr_union in_addr; union lladdr_union lladdr; size_t lladdr_size; - - LIST_FIELDS(Neighbor, neighbors); }; void neighbor_free(Neighbor *neighbor); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index de15074550..f4b03beeab 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -151,7 +151,7 @@ static int network_resolve_stacked_netdevs(Network *network) { int network_verify(Network *network) { RoutePrefix *route_prefix, *route_prefix_next; - Neighbor *neighbor, *neighbor_next; + Neighbor *neighbor; AddressLabel *label, *label_next; Address *address, *address_next; Prefix *prefix, *prefix_next; @@ -308,7 +308,7 @@ int network_verify(Network *network) { if (mdb_entry_verify(mdb) < 0) mdb_entry_free(mdb); - LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors) + HASHMAP_FOREACH(neighbor, network->neighbors_by_section) if (neighbor_section_verify(neighbor) < 0) neighbor_free(neighbor); @@ -645,7 +645,6 @@ static Network *network_free(Network *network) { AddressLabel *label; FdbEntry *fdb_entry; MdbEntry *mdb_entry; - Neighbor *neighbor; Address *address; Prefix *prefix; Route *route; @@ -720,9 +719,6 @@ static Network *network_free(Network *network) { while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses)) ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address); - while ((neighbor = network->neighbors)) - neighbor_free(neighbor); - while ((label = network->address_labels)) address_label_free(label); @@ -737,7 +733,7 @@ static Network *network_free(Network *network) { hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free); hashmap_free(network->fdb_entries_by_section); hashmap_free(network->mdb_entries_by_section); - hashmap_free(network->neighbors_by_section); + hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free); hashmap_free(network->address_labels_by_section); hashmap_free(network->prefixes_by_section); hashmap_free(network->route_prefixes_by_section); @@ -870,7 +866,7 @@ bool network_has_static_ipv6_configurations(Network *network) { if (mdb->family == AF_INET6) return true; - LIST_FOREACH(neighbors, neighbor, network->neighbors) + HASHMAP_FOREACH(neighbor, network->neighbors_by_section) if (neighbor->family == AF_INET6) return true; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 12ec6ef1b2..5ab609bcc0 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -288,7 +288,6 @@ struct Network { LIST_HEAD(FdbEntry, static_fdb_entries); LIST_HEAD(MdbEntry, static_mdb_entries); LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); - LIST_HEAD(Neighbor, neighbors); LIST_HEAD(AddressLabel, address_labels); LIST_HEAD(Prefix, static_prefixes); LIST_HEAD(RoutePrefix, static_route_prefixes); @@ -298,7 +297,6 @@ struct Network { unsigned n_static_fdb_entries; unsigned n_static_mdb_entries; unsigned n_ipv6_proxy_ndp_addresses; - unsigned n_neighbors; unsigned n_address_labels; unsigned n_static_prefixes; unsigned n_static_route_prefixes; From 19f8cffce1dc36fef30e4e07bfc0b13c74873d56 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 00:00:20 +0900 Subject: [PATCH 035/138] network: make neighbor_{add,get}() takes Neighbor object --- src/network/networkd-link.c | 2 +- src/network/networkd-neighbor.c | 99 ++++++++++++--------------------- src/network/networkd-neighbor.h | 6 +- 3 files changed, 40 insertions(+), 67 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 48cf83a753..d2befa28ec 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2731,7 +2731,7 @@ static int link_drop_foreign_config(Link *link) { SET_FOREACH(neighbor, link->neighbors_foreign) { if (link_is_neighbor_configured(link, neighbor)) { - r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL); + r = neighbor_add(link, neighbor, NULL); if (r < 0) return r; } else { diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 0b4ceafb31..abffa39f26 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -118,28 +118,20 @@ static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) { DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func, neighbor_free); -int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) { - Neighbor neighbor, *existing; +int neighbor_get(Link *link, const Neighbor *in, Neighbor **ret) { + Neighbor *existing; assert(link); - assert(addr); - assert(lladdr); + assert(in); - neighbor = (Neighbor) { - .family = family, - .in_addr = *addr, - .lladdr = *lladdr, - .lladdr_size = lladdr_size, - }; - - existing = set_get(link->neighbors, &neighbor); + existing = set_get(link->neighbors, in); if (existing) { if (ret) *ret = existing; return 1; } - existing = set_get(link->neighbors_foreign, &neighbor); + existing = set_get(link->neighbors_foreign, in); if (existing) { if (ret) *ret = existing; @@ -149,24 +141,23 @@ int neighbor_get(Link *link, int family, const union in_addr_union *addr, const return -ENOENT; } -static int neighbor_add_internal(Link *link, Set **neighbors, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) { +static int neighbor_add_internal(Link *link, Set **neighbors, const Neighbor *in, Neighbor **ret) { _cleanup_(neighbor_freep) Neighbor *neighbor = NULL; int r; assert(link); assert(neighbors); - assert(addr); - assert(lladdr); + assert(in); neighbor = new(Neighbor, 1); if (!neighbor) return -ENOMEM; *neighbor = (Neighbor) { - .family = family, - .in_addr = *addr, - .lladdr = *lladdr, - .lladdr_size = lladdr_size, + .family = in->family, + .in_addr = in->in_addr, + .lladdr = in->lladdr, + .lladdr_size = in->lladdr_size, }; r = set_ensure_put(neighbors, &neighbor_hash_ops, neighbor); @@ -179,19 +170,19 @@ static int neighbor_add_internal(Link *link, Set **neighbors, int family, const if (ret) *ret = neighbor; - TAKE_PTR(neighbor); + TAKE_PTR(neighbor); return 0; } -int neighbor_add(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) { +int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret) { Neighbor *neighbor; int r; - r = neighbor_get(link, family, addr, lladdr, lladdr_size, &neighbor); + r = neighbor_get(link, in, &neighbor); if (r == -ENOENT) { /* Neighbor doesn't exist, make a new one */ - r = neighbor_add_internal(link, &link->neighbors, family, addr, lladdr, lladdr_size, &neighbor); + r = neighbor_add_internal(link, &link->neighbors, in, &neighbor); if (r < 0) return r; } else if (r == 0) { @@ -211,8 +202,8 @@ int neighbor_add(Link *link, int family, const union in_addr_union *addr, const return 0; } -int neighbor_add_foreign(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) { - return neighbor_add_internal(link, &link->neighbors_foreign, family, addr, lladdr, lladdr_size, ret); +int neighbor_add_foreign(Link *link, const Neighbor *in, Neighbor **ret) { + return neighbor_add_internal(link, &link->neighbors_foreign, in, ret); } bool neighbor_equal(const Neighbor *n1, const Neighbor *n2) { @@ -290,7 +281,7 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand link->neighbor_messages++; link_ref(link); - r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL); + r = neighbor_add(link, neighbor, NULL); if (r < 0) return log_link_error_errno(link, r, "Could not add neighbor: %m"); @@ -412,15 +403,12 @@ static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, uni } int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - Link *link = NULL; + _cleanup_(neighbor_freep) Neighbor *tmp = NULL; + _cleanup_free_ char *addr_str = NULL, *lladdr_str = NULL; Neighbor *neighbor = NULL; - int ifindex, family, r; uint16_t type, state; - union in_addr_union in_addr = IN_ADDR_NULL; - _cleanup_free_ char *addr_str = NULL; - union lladdr_union lladdr; - size_t lladdr_size = 0; - _cleanup_free_ char *lladdr_str = NULL; + int ifindex, r; + Link *link; assert(rtnl); assert(message); @@ -445,7 +433,7 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, r = sd_rtnl_message_neigh_get_state(message, &state); if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid state, ignoring: %m"); + log_warning_errno(r, "rtnl: received neighbor message with invalid state, ignoring: %m"); return 0; } else if (!FLAGS_SET(state, NUD_PERMANENT)) { log_debug("rtnl: received non-static neighbor, ignoring."); @@ -470,48 +458,33 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, return 0; } - r = sd_rtnl_message_neigh_get_family(message, &family); + tmp = new0(Neighbor, 1); + + r = sd_rtnl_message_neigh_get_family(message, &tmp->family); if (r < 0) { log_link_warning(link, "rtnl: received neighbor message without family, ignoring."); return 0; - } else if (!IN_SET(family, AF_INET, AF_INET6)) { - log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", family); + } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { + log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", tmp->family); return 0; } - switch (family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, NDA_DST, &in_addr.in); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m"); - return 0; - } - - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, NDA_DST, &in_addr.in6); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m"); - return 0; - } - - break; - - default: - assert_not_reached("Received unsupported address family"); + r = netlink_message_read_in_addr_union(message, NDA_DST, tmp->family, &tmp->in_addr); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m"); + return 0; } - if (in_addr_to_string(family, &in_addr, &addr_str) < 0) + if (in_addr_to_string(tmp->family, &tmp->in_addr, &addr_str) < 0) log_link_warning_errno(link, r, "Could not print address: %m"); - r = manager_rtnl_process_neighbor_lladdr(message, &lladdr, &lladdr_size, &lladdr_str); + r = manager_rtnl_process_neighbor_lladdr(message, &tmp->lladdr, &tmp->lladdr_size, &lladdr_str); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m"); return 0; } - (void) neighbor_get(link, family, &in_addr, &lladdr, lladdr_size, &neighbor); + (void) neighbor_get(link, tmp, &neighbor); switch (type) { case RTM_NEWNEIGH: @@ -520,7 +493,7 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, strnull(addr_str), strnull(lladdr_str)); else { /* A neighbor appeared that we did not request */ - r = neighbor_add_foreign(link, family, &in_addr, &lladdr, lladdr_size, &neighbor); + r = neighbor_add_foreign(link, tmp, NULL); if (r < 0) { log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m", strnull(addr_str), strnull(lladdr_str)); diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 34083cf526..fad4ab23be 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -38,9 +38,9 @@ DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free); int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback); int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback); -int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret); -int neighbor_add(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret); -int neighbor_add_foreign(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret); +int neighbor_get(Link *link, const Neighbor *in, Neighbor **ret); +int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret); +int neighbor_add_foreign(Link *link, const Neighbor *in, Neighbor **ret); bool neighbor_equal(const Neighbor *n1, const Neighbor *n2); int neighbor_section_verify(Neighbor *neighbor); From 0d6e933eace5bdd1d4f21c2379752d21d037b4e6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 00:05:18 +0900 Subject: [PATCH 036/138] network: make several functions static --- src/network/networkd-neighbor.c | 8 +++++--- src/network/networkd-neighbor.h | 8 +------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index abffa39f26..a4336005d9 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -32,6 +32,8 @@ void neighbor_free(Neighbor *neighbor) { free(neighbor); } +DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free); + static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) { _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; _cleanup_(neighbor_freep) Neighbor *neighbor = NULL; @@ -118,7 +120,7 @@ static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) { DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func, neighbor_free); -int neighbor_get(Link *link, const Neighbor *in, Neighbor **ret) { +static int neighbor_get(Link *link, const Neighbor *in, Neighbor **ret) { Neighbor *existing; assert(link); @@ -202,7 +204,7 @@ int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret) { return 0; } -int neighbor_add_foreign(Link *link, const Neighbor *in, Neighbor **ret) { +static int neighbor_add_foreign(Link *link, const Neighbor *in, Neighbor **ret) { return neighbor_add_internal(link, &link->neighbors_foreign, in, ret); } @@ -242,7 +244,7 @@ static int neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, L return 1; } -int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { +static int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index fad4ab23be..47a182161d 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -32,19 +32,13 @@ struct Neighbor { }; void neighbor_free(Neighbor *neighbor); +int neighbor_section_verify(Neighbor *neighbor); -DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free); - -int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback); int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback); -int neighbor_get(Link *link, const Neighbor *in, Neighbor **ret); int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret); -int neighbor_add_foreign(Link *link, const Neighbor *in, Neighbor **ret); bool neighbor_equal(const Neighbor *n1, const Neighbor *n2); -int neighbor_section_verify(Neighbor *neighbor); - int link_set_neighbors(Link *link); int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); From 9be0b3abc24425675ace0876c05fd161789cbd14 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 00:09:21 +0900 Subject: [PATCH 037/138] network: drop unused arguments --- src/network/networkd-link.c | 4 ++-- src/network/networkd-neighbor.c | 14 +++++++------- src/network/networkd-neighbor.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index d2befa28ec..9b56cc1f84 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2735,7 +2735,7 @@ static int link_drop_foreign_config(Link *link) { if (r < 0) return r; } else { - r = neighbor_remove(neighbor, link, NULL); + r = neighbor_remove(neighbor, link); if (r < 0) return r; } @@ -2833,7 +2833,7 @@ static int link_drop_config(Link *link) { } SET_FOREACH(neighbor, link->neighbors) { - r = neighbor_remove(neighbor, link, NULL); + r = neighbor_remove(neighbor, link); if (r < 0) return r; } diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index a4336005d9..28c8571a4b 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -244,7 +244,7 @@ static int neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, L return 1; } -static int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { +static int neighbor_configure(Neighbor *neighbor, Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -255,7 +255,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_messa assert(link->manager->rtnl); r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, - link->ifindex, neighbor->family); + link->ifindex, neighbor->family); if (r < 0) return log_link_error_errno(link, r, "Could not allocate RTM_NEWNEIGH message: %m"); @@ -275,7 +275,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_messa if (r < 0) return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); - r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_configure_handler, + r = netlink_call_async(link->manager->rtnl, NULL, req, neighbor_configure_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -301,7 +301,7 @@ int link_set_neighbors(Link *link) { link->neighbors_configured = false; HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) { - r = neighbor_configure(neighbor, link, NULL); + r = neighbor_configure(neighbor, link); if (r < 0) return log_link_warning_errno(link, r, "Could not set neighbor: %m"); } @@ -334,7 +334,7 @@ static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link return 1; } -int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { +int neighbor_remove(Neighbor *neighbor, Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -345,7 +345,7 @@ int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler assert(link->manager->rtnl); r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_DELNEIGH, - link->ifindex, neighbor->family); + link->ifindex, neighbor->family); if (r < 0) return log_link_error_errno(link, r, "Could not allocate RTM_DELNEIGH message: %m"); @@ -353,7 +353,7 @@ int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler if (r < 0) return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); - r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_remove_handler, + r = netlink_call_async(link->manager->rtnl, NULL, req, neighbor_remove_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 47a182161d..5f738f7d4a 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -34,7 +34,7 @@ struct Neighbor { void neighbor_free(Neighbor *neighbor); int neighbor_section_verify(Neighbor *neighbor); -int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback); +int neighbor_remove(Neighbor *neighbor, Link *link); int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret); bool neighbor_equal(const Neighbor *n1, const Neighbor *n2); From 1939ebeb893ddf62bc80d74ef766a495f120b1a1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 00:17:22 +0900 Subject: [PATCH 038/138] network: cleanup headers in networkd-neighbor.[ch] --- src/network/netdev/macsec.h | 1 + src/network/networkd-fdb.h | 1 + src/network/networkd-manager.c | 1 + src/network/networkd-neighbor.c | 6 +----- src/network/networkd-neighbor.h | 17 ++++++++--------- src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 - 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/network/netdev/macsec.h b/src/network/netdev/macsec.h index 2a3443a6d4..26ad2b7cca 100644 --- a/src/network/netdev/macsec.h +++ b/src/network/netdev/macsec.h @@ -4,6 +4,7 @@ #include #include +#include "ether-addr-util.h" #include "in-addr-util.h" #include "netdev.h" #include "networkd-util.h" diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h index 5e24ad6aee..f607dfc70f 100644 --- a/src/network/networkd-fdb.h +++ b/src/network/networkd-fdb.h @@ -8,6 +8,7 @@ #include #include "conf-parser.h" +#include "ether-addr-util.h" #include "list.h" #include "macro.h" #include "networkd-util.h" diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 37a9745df8..cd0ad82e2e 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -29,6 +29,7 @@ #include "networkd-link-bus.h" #include "networkd-manager-bus.h" #include "networkd-manager.h" +#include "networkd-neighbor.h" #include "networkd-network-bus.h" #include "networkd-nexthop.h" #include "networkd-routing-policy-rule.h" diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 28c8571a4b..f04a0b762c 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -1,16 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -#include "sd-netlink.h" - #include "alloc-util.h" -#include "conf-parser.h" -#include "ether-addr-util.h" #include "hashmap.h" -#include "in-addr-util.h" #include "netlink-util.h" #include "networkd-link.h" #include "networkd-manager.h" #include "networkd-neighbor.h" +#include "networkd-network.h" #include "set.h" void neighbor_free(Neighbor *neighbor) { diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 5f738f7d4a..56d1f66bf7 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -1,26 +1,25 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include + #include "sd-netlink.h" #include "conf-parser.h" #include "ether-addr-util.h" #include "in-addr-util.h" -#include "list.h" -#include "macro.h" - -typedef struct Neighbor Neighbor; - -#include "networkd-link.h" -#include "networkd-network.h" #include "networkd-util.h" +typedef Manager Manager; +typedef Network Network; +typedef Link Link; + union lladdr_union { struct ether_addr mac; union in_addr_union ip; }; -struct Neighbor { +typedef struct Neighbor { Network *network; Link *link; NetworkConfigSection *section; @@ -29,7 +28,7 @@ struct Neighbor { union in_addr_union in_addr; union lladdr_union lladdr; size_t lladdr_size; -}; +} Neighbor; void neighbor_free(Neighbor *neighbor); int neighbor_section_verify(Neighbor *neighbor); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 25a7b8991a..444b6fce9c 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -15,6 +15,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "networkd-ipv4ll.h" #include "networkd-ndisc.h" #include "networkd-network.h" +#include "networkd-neighbor.h" #include "networkd-nexthop.h" #include "networkd-routing-policy-rule.h" #include "networkd-sriov.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index f4b03beeab..f0fd3ad3e9 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -15,6 +15,7 @@ #include "networkd-dhcp-server.h" #include "network-internal.h" #include "networkd-manager.h" +#include "networkd-neighbor.h" #include "networkd-network.h" #include "networkd-nexthop.h" #include "networkd-routing-policy-rule.h" diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 5ab609bcc0..acc4378771 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -25,7 +25,6 @@ #include "networkd-lldp-tx.h" #include "networkd-mdb.h" #include "networkd-ndisc.h" -#include "networkd-neighbor.h" #include "networkd-radv.h" #include "networkd-route.h" #include "networkd-util.h" From 590483365921d8ac4007ce3dfdda8d6e588afe9e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 00:37:39 +0900 Subject: [PATCH 039/138] network: introduce neighbor_drop_{,foreign_}neighbors() --- src/network/networkd-link.c | 40 ++++------------------- src/network/networkd-neighbor.c | 57 +++++++++++++++++++++++++++++++-- src/network/networkd-neighbor.h | 7 ++-- 3 files changed, 62 insertions(+), 42 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 9b56cc1f84..9aebe74565 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2593,22 +2593,6 @@ static bool link_is_static_address_configured(Link *link, Address *address) { return false; } -static bool link_is_neighbor_configured(Link *link, Neighbor *neighbor) { - Neighbor *net_neighbor; - - assert(link); - assert(neighbor); - - if (!link->network) - return false; - - HASHMAP_FOREACH(net_neighbor, link->network->neighbors_by_section) - if (neighbor_equal(net_neighbor, neighbor)) - return true; - - return false; -} - static bool link_is_static_route_configured(Link *link, Route *route) { Route *net_route; @@ -2695,7 +2679,6 @@ static int link_enumerate_ipv6_tentative_addresses(Link *link) { static int link_drop_foreign_config(Link *link) { Address *address; - Neighbor *neighbor; Route *route; int r; @@ -2729,17 +2712,9 @@ static int link_drop_foreign_config(Link *link) { } } - SET_FOREACH(neighbor, link->neighbors_foreign) { - if (link_is_neighbor_configured(link, neighbor)) { - r = neighbor_add(link, neighbor, NULL); - if (r < 0) - return r; - } else { - r = neighbor_remove(neighbor, link); - if (r < 0) - return r; - } - } + r = link_drop_foreign_neighbors(link); + if (r < 0) + return r; SET_FOREACH(route, link->routes_foreign) { /* do not touch routes managed by the kernel */ @@ -2808,7 +2783,6 @@ static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m static int link_drop_config(Link *link) { Address *address, *pool_address; - Neighbor *neighbor; Route *route; int r; @@ -2832,11 +2806,9 @@ static int link_drop_config(Link *link) { } } - SET_FOREACH(neighbor, link->neighbors) { - r = neighbor_remove(neighbor, link); - if (r < 0) - return r; - } + r = link_drop_neighbors(link); + if (r < 0) + return r; SET_FOREACH(route, link->routes) { /* do not touch routes managed by the kernel */ diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index f04a0b762c..5135ed6422 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -173,7 +173,7 @@ static int neighbor_add_internal(Link *link, Set **neighbors, const Neighbor *in return 0; } -int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret) { +static int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret) { Neighbor *neighbor; int r; @@ -204,7 +204,7 @@ static int neighbor_add_foreign(Link *link, const Neighbor *in, Neighbor **ret) return neighbor_add_internal(link, &link->neighbors_foreign, in, ret); } -bool neighbor_equal(const Neighbor *n1, const Neighbor *n2) { +static bool neighbor_equal(const Neighbor *n1, const Neighbor *n2) { if (n1 == n2) return true; @@ -330,7 +330,7 @@ static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link return 1; } -int neighbor_remove(Neighbor *neighbor, Link *link) { +static int neighbor_remove(Neighbor *neighbor, Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -359,6 +359,57 @@ int neighbor_remove(Neighbor *neighbor, Link *link) { return 0; } +static bool link_is_neighbor_configured(Link *link, Neighbor *neighbor) { + Neighbor *net_neighbor; + + assert(link); + assert(neighbor); + + if (!link->network) + return false; + + HASHMAP_FOREACH(net_neighbor, link->network->neighbors_by_section) + if (neighbor_equal(net_neighbor, neighbor)) + return true; + + return false; +} + +int link_drop_foreign_neighbors(Link *link) { + Neighbor *neighbor; + int r; + + assert(link); + + SET_FOREACH(neighbor, link->neighbors_foreign) + if (link_is_neighbor_configured(link, neighbor)) { + r = neighbor_add(link, neighbor, NULL); + if (r < 0) + return r; + } else { + r = neighbor_remove(neighbor, link); + if (r < 0) + return r; + } + + return 0; +} + +int link_drop_neighbors(Link *link) { + Neighbor *neighbor; + int k, r = 0; + + assert(link); + + SET_FOREACH(neighbor, link->neighbors) { + k = neighbor_remove(neighbor, link); + if (k < 0 && r >= 0) + r = k; + } + + return r; +} + static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) { int r; diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 56d1f66bf7..a0e3fbd47a 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -33,12 +33,9 @@ typedef struct Neighbor { void neighbor_free(Neighbor *neighbor); int neighbor_section_verify(Neighbor *neighbor); -int neighbor_remove(Neighbor *neighbor, Link *link); - -int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret); -bool neighbor_equal(const Neighbor *n1, const Neighbor *n2); - int link_set_neighbors(Link *link); +int link_drop_neighbors(Link *link); +int link_drop_foreign_neighbors(Link *link); int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); From 78ada14f257991635d2cba68e1232cda0f4617e2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 00:43:06 +0900 Subject: [PATCH 040/138] network: introduce network_verify_neighbors() --- src/network/networkd-neighbor.c | 13 ++++++++++++- src/network/networkd-neighbor.h | 3 ++- src/network/networkd-network.c | 5 +---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 5135ed6422..908fc1c11c 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -572,7 +572,7 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, return 1; } -int neighbor_section_verify(Neighbor *neighbor) { +static int neighbor_section_verify(Neighbor *neighbor) { if (section_is_invalid(neighbor->section)) return -EINVAL; @@ -591,6 +591,17 @@ int neighbor_section_verify(Neighbor *neighbor) { return 0; } +void network_verify_neighbors(Network *network) { + Neighbor *neighbor; + + assert(network); + + HASHMAP_FOREACH(neighbor, network->neighbors_by_section) + if (neighbor_section_verify(neighbor) < 0) + neighbor_free(neighbor); +} + + int config_parse_neighbor_address( const char *unit, const char *filename, diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index a0e3fbd47a..0c3dfc8303 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -31,7 +31,8 @@ typedef struct Neighbor { } Neighbor; void neighbor_free(Neighbor *neighbor); -int neighbor_section_verify(Neighbor *neighbor); + +void network_verify_neighbors(Network *network); int link_set_neighbors(Link *link); int link_drop_neighbors(Link *link); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index f0fd3ad3e9..0591b23e09 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -152,7 +152,6 @@ static int network_resolve_stacked_netdevs(Network *network) { int network_verify(Network *network) { RoutePrefix *route_prefix, *route_prefix_next; - Neighbor *neighbor; AddressLabel *label, *label_next; Address *address, *address_next; Prefix *prefix, *prefix_next; @@ -309,9 +308,7 @@ int network_verify(Network *network) { if (mdb_entry_verify(mdb) < 0) mdb_entry_free(mdb); - HASHMAP_FOREACH(neighbor, network->neighbors_by_section) - if (neighbor_section_verify(neighbor) < 0) - neighbor_free(neighbor); + network_verify_neighbors(network); LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels) if (section_is_invalid(label->section)) From 64753f354d762e0f9cb641c48256011503408a44 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 00:45:19 +0900 Subject: [PATCH 041/138] network: make neighbor_free() return NULL --- src/network/networkd-neighbor.c | 6 +++--- src/network/networkd-neighbor.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 908fc1c11c..c14c8f7e06 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -9,9 +9,9 @@ #include "networkd-network.h" #include "set.h" -void neighbor_free(Neighbor *neighbor) { +Neighbor *neighbor_free(Neighbor *neighbor) { if (!neighbor) - return; + return NULL; if (neighbor->network) { assert(neighbor->section); @@ -25,7 +25,7 @@ void neighbor_free(Neighbor *neighbor) { set_remove(neighbor->link->neighbors_foreign, neighbor); } - free(neighbor); + return mfree(neighbor); } DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free); diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 0c3dfc8303..f40fdccc48 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -30,7 +30,7 @@ typedef struct Neighbor { size_t lladdr_size; } Neighbor; -void neighbor_free(Neighbor *neighbor); +Neighbor *neighbor_free(Neighbor *neighbor); void network_verify_neighbors(Network *network); From d6a2a0f9a7a325e98b053a1447b04d548a11e35e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 01:20:43 +0900 Subject: [PATCH 042/138] network: drop list of static address labels [IPv6AddressLabel] sections are managed by both LIST and Hashmap. Let's drop list, as they store the completely same information. --- src/network/networkd-address-label.c | 52 ++++++++++------------------ src/network/networkd-address-label.h | 2 -- src/network/networkd-link.c | 2 +- src/network/networkd-network.c | 12 +++---- src/network/networkd-network.h | 2 -- 5 files changed, 24 insertions(+), 46 deletions(-) diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index 0d53aa9042..6c3c0409a9 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -16,16 +16,11 @@ void address_label_free(AddressLabel *label) { return; if (label->network) { - LIST_REMOVE(labels, label->network->address_labels, label); - assert(label->network->n_address_labels > 0); - label->network->n_address_labels--; - - if (label->section) { - hashmap_remove(label->network->address_labels_by_section, label->section); - network_config_section_free(label->section); - } + assert(label->section); + hashmap_remove(label->network->address_labels_by_section, label->section); } + network_config_section_free(label->section); free(label); } @@ -36,19 +31,17 @@ static int address_label_new_static(Network *network, const char *filename, unsi assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; - label = hashmap_get(network->address_labels_by_section, n); - if (label) { - *ret = TAKE_PTR(label); - - return 0; - } + label = hashmap_get(network->address_labels_by_section, n); + if (label) { + *ret = TAKE_PTR(label); + return 0; } label = new(AddressLabel, 1); @@ -57,25 +50,18 @@ static int address_label_new_static(Network *network, const char *filename, unsi *label = (AddressLabel) { .network = network, + .section = TAKE_PTR(n), }; - LIST_APPEND(labels, network->address_labels, label); - network->n_address_labels++; + r = hashmap_ensure_allocated(&network->address_labels_by_section, &network_config_hash_ops); + if (r < 0) + return r; - if (filename) { - label->section = TAKE_PTR(n); - - r = hashmap_ensure_allocated(&network->address_labels_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->address_labels_by_section, label->section, label); - if (r < 0) - return r; - } + r = hashmap_put(network->address_labels_by_section, label->section, label); + if (r < 0) + return r; *ret = TAKE_PTR(label); - return 0; } diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index 595072a17e..5e02dee246 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -25,8 +25,6 @@ struct AddressLabel { uint32_t label; union in_addr_union in_addr; - - LIST_FIELDS(AddressLabel, labels); }; void address_label_free(AddressLabel *label); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 9aebe74565..dc12a9694c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1322,7 +1322,7 @@ static int link_request_set_addresses(Link *link) { return r; } - LIST_FOREACH(labels, label, link->network->address_labels) { + HASHMAP_FOREACH(label, link->network->address_labels_by_section) { r = address_label_configure(label, link, NULL, false); if (r < 0) return log_link_warning_errno(link, r, "Could not set address label: %m"); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 0591b23e09..b170f7aa35 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -152,7 +152,7 @@ static int network_resolve_stacked_netdevs(Network *network) { int network_verify(Network *network) { RoutePrefix *route_prefix, *route_prefix_next; - AddressLabel *label, *label_next; + AddressLabel *label; Address *address, *address_next; Prefix *prefix, *prefix_next; Route *route, *route_next; @@ -310,7 +310,7 @@ int network_verify(Network *network) { network_verify_neighbors(network); - LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels) + HASHMAP_FOREACH(label, network->address_labels_by_section) if (section_is_invalid(label->section)) address_label_free(label); @@ -640,7 +640,6 @@ failure: static Network *network_free(Network *network) { IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; RoutePrefix *route_prefix; - AddressLabel *label; FdbEntry *fdb_entry; MdbEntry *mdb_entry; Address *address; @@ -717,9 +716,6 @@ static Network *network_free(Network *network) { while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses)) ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address); - while ((label = network->address_labels)) - address_label_free(label); - while ((prefix = network->static_prefixes)) prefix_free(prefix); @@ -732,7 +728,7 @@ static Network *network_free(Network *network) { hashmap_free(network->fdb_entries_by_section); hashmap_free(network->mdb_entries_by_section); hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free); - hashmap_free(network->address_labels_by_section); + hashmap_free_with_destructor(network->address_labels_by_section, address_label_free); hashmap_free(network->prefixes_by_section); hashmap_free(network->route_prefixes_by_section); hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free); @@ -868,7 +864,7 @@ bool network_has_static_ipv6_configurations(Network *network) { if (neighbor->family == AF_INET6) return true; - if (!LIST_IS_EMPTY(network->address_labels)) + if (!hashmap_isempty(network->address_labels_by_section)) return true; if (!LIST_IS_EMPTY(network->static_prefixes)) diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index acc4378771..4f05b92b3e 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -287,7 +287,6 @@ struct Network { LIST_HEAD(FdbEntry, static_fdb_entries); LIST_HEAD(MdbEntry, static_mdb_entries); LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); - LIST_HEAD(AddressLabel, address_labels); LIST_HEAD(Prefix, static_prefixes); LIST_HEAD(RoutePrefix, static_route_prefixes); @@ -296,7 +295,6 @@ struct Network { unsigned n_static_fdb_entries; unsigned n_static_mdb_entries; unsigned n_ipv6_proxy_ndp_addresses; - unsigned n_address_labels; unsigned n_static_prefixes; unsigned n_static_route_prefixes; From cae418a3060aaa36aecea507d9a7a0ff5a9799d5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 01:25:12 +0900 Subject: [PATCH 043/138] network: make address_label_free() return NULL --- src/network/networkd-address-label.c | 6 +++--- src/network/networkd-address-label.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index 6c3c0409a9..6236f048f2 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -11,9 +11,9 @@ #include "parse-util.h" #include "socket-util.h" -void address_label_free(AddressLabel *label) { +AddressLabel *address_label_free(AddressLabel *label) { if (!label) - return; + return NULL; if (label->network) { assert(label->section); @@ -21,7 +21,7 @@ void address_label_free(AddressLabel *label) { } network_config_section_free(label->section); - free(label); + return mfree(label); } static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) { diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index 5e02dee246..44292718e5 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -27,7 +27,7 @@ struct AddressLabel { union in_addr_union in_addr; }; -void address_label_free(AddressLabel *label); +AddressLabel *address_label_free(AddressLabel *label); DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free); From ab316813ea3f91b677e80f0ef92f7f0f7f309fa3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 01:28:35 +0900 Subject: [PATCH 044/138] network: introduce network_verify_address_labels() --- src/network/networkd-address-label.c | 10 ++++++++++ src/network/networkd-address-label.h | 2 ++ src/network/networkd-network.c | 6 +----- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index 6236f048f2..c25ac0ae1e 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -136,6 +136,16 @@ int address_label_configure( return 0; } +void network_verify_address_labels(Network *network) { + AddressLabel *label; + + assert(network); + + HASHMAP_FOREACH(label, network->address_labels_by_section) + if (section_is_invalid(label->section)) + address_label_free(label); +} + int config_parse_address_label_prefix(const char *unit, const char *filename, unsigned line, diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index 44292718e5..994a4f69bf 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -31,6 +31,8 @@ AddressLabel *address_label_free(AddressLabel *label); DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free); +void network_verify_address_labels(Network *network); + int address_label_configure(AddressLabel *address, Link *link, link_netlink_message_handler_t callback, bool update); CONFIG_PARSER_PROTOTYPE(config_parse_address_label); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index b170f7aa35..d5b60e8260 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -152,7 +152,6 @@ static int network_resolve_stacked_netdevs(Network *network) { int network_verify(Network *network) { RoutePrefix *route_prefix, *route_prefix_next; - AddressLabel *label; Address *address, *address_next; Prefix *prefix, *prefix_next; Route *route, *route_next; @@ -309,10 +308,7 @@ int network_verify(Network *network) { mdb_entry_free(mdb); network_verify_neighbors(network); - - HASHMAP_FOREACH(label, network->address_labels_by_section) - if (section_is_invalid(label->section)) - address_label_free(label); + network_verify_address_labels(network); LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes) if (section_is_invalid(prefix->section)) From fe2bc17ca7bd42218b147a7781ecf7313090a18c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 01:33:25 +0900 Subject: [PATCH 045/138] network: introduce link_set_address_labels() --- src/network/networkd-address-label.c | 27 ++++++++++++++++++++------- src/network/networkd-address-label.h | 2 +- src/network/networkd-link.c | 11 +++-------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index c25ac0ae1e..b48e997782 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -93,12 +93,7 @@ static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * return 1; } -int address_label_configure( - AddressLabel *label, - Link *link, - link_netlink_message_handler_t callback, - bool update) { - +static int address_label_configure(AddressLabel *label, Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -126,7 +121,7 @@ int address_label_configure( return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m"); r = netlink_call_async(link->manager->rtnl, NULL, req, - callback ?: address_label_handler, + address_label_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -136,6 +131,24 @@ int address_label_configure( return 0; } +int link_set_address_labels(Link *link) { + AddressLabel *label; + int r; + + assert(link); + assert(link->network); + + HASHMAP_FOREACH(label, link->network->address_labels_by_section) { + r = address_label_configure(label, link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set address label: %m"); + + link->address_label_messages++; + } + + return 0; +} + void network_verify_address_labels(Network *network) { AddressLabel *label; diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index 994a4f69bf..dde6877eef 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -33,7 +33,7 @@ DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free); void network_verify_address_labels(Network *network); -int address_label_configure(AddressLabel *address, Link *link, link_netlink_message_handler_t callback, bool update); +int link_set_address_labels(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_address_label); CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index dc12a9694c..fd339e289a 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1248,7 +1248,6 @@ static int static_address_configure(Address *address, Link *link, bool update) { } static int link_request_set_addresses(Link *link) { - AddressLabel *label; Address *ad; Prefix *p; int r; @@ -1322,13 +1321,9 @@ static int link_request_set_addresses(Link *link) { return r; } - HASHMAP_FOREACH(label, link->network->address_labels_by_section) { - r = address_label_configure(label, link, NULL, false); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set address label: %m"); - - link->address_label_messages++; - } + r = link_set_address_labels(link); + if (r < 0) + return r; /* now that we can figure out a default address for the dhcp server, start it */ if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) { From fb486c90824b054b8f3ca028bce953e7c09037be Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 01:40:03 +0900 Subject: [PATCH 046/138] network: cleanup networkd-address-label.h --- src/network/networkd-address-label.c | 8 +++++--- src/network/networkd-address-label.h | 14 ++------------ src/network/networkd-link.c | 1 + src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 - 6 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index b48e997782..e83665bfda 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -4,12 +4,12 @@ #include #include "alloc-util.h" -#include "conf-parser.h" -#include "networkd-address-label.h" #include "netlink-util.h" +#include "networkd-address-label.h" +#include "networkd-link.h" #include "networkd-manager.h" +#include "networkd-network.h" #include "parse-util.h" -#include "socket-util.h" AddressLabel *address_label_free(AddressLabel *label) { if (!label) @@ -24,6 +24,8 @@ AddressLabel *address_label_free(AddressLabel *label) { return mfree(label); } +DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free); + static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) { _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; _cleanup_(address_label_freep) AddressLabel *label = NULL; diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index dde6877eef..aacab867e7 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -2,35 +2,25 @@ #pragma once #include -#include #include "conf-parser.h" #include "in-addr-util.h" - -typedef struct AddressLabel AddressLabel; - -#include "networkd-link.h" -#include "networkd-network.h" #include "networkd-util.h" typedef struct Network Network; typedef struct Link Link; -typedef struct NetworkConfigSection NetworkConfigSection; -struct AddressLabel { +typedef struct AddressLabel { Network *network; NetworkConfigSection *section; unsigned char prefixlen; uint32_t label; - union in_addr_union in_addr; -}; +} AddressLabel; AddressLabel *address_label_free(AddressLabel *label); -DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free); - void network_verify_address_labels(Network *network); int link_set_address_labels(Link *link); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index fd339e289a..b94e4945f3 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -20,6 +20,7 @@ #include "missing_network.h" #include "netlink-util.h" #include "network-internal.h" +#include "networkd-address-label.h" #include "networkd-can.h" #include "networkd-dhcp-server.h" #include "networkd-dhcp4.h" diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 444b6fce9c..648e882a29 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -6,6 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "conf-parser.h" #include "netem.h" #include "network-internal.h" +#include "networkd-address-label.h" #include "networkd-can.h" #include "networkd-conf.h" #include "networkd-dhcp-common.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index d5b60e8260..95f3f65394 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -14,6 +14,7 @@ #include "in-addr-util.h" #include "networkd-dhcp-server.h" #include "network-internal.h" +#include "networkd-address-label.h" #include "networkd-manager.h" #include "networkd-neighbor.h" #include "networkd-network.h" diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 4f05b92b3e..c129338569 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -12,7 +12,6 @@ #include "conf-parser.h" #include "hashmap.h" #include "netdev.h" -#include "networkd-address-label.h" #include "networkd-address.h" #include "networkd-brvlan.h" #include "networkd-dhcp-common.h" From df3a18f87f2995b7e2f9c8a1043679f7ec64c45c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 01:53:16 +0900 Subject: [PATCH 047/138] network: make fdb_entry_free() return NULL --- src/network/networkd-fdb.c | 38 ++++++++++++++++++++------------------ src/network/networkd-fdb.h | 4 +--- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 628c3988ac..43aaebb285 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -30,6 +30,26 @@ static const char* const fdb_ntf_flags_table[_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX] = DEFINE_STRING_TABLE_LOOKUP(fdb_ntf_flags, NeighborCacheEntryFlags); +/* remove and FDB entry. */ +FdbEntry *fdb_entry_free(FdbEntry *fdb_entry) { + if (!fdb_entry) + return NULL; + + if (fdb_entry->network) { + LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry); + assert(fdb_entry->network->n_static_fdb_entries > 0); + fdb_entry->network->n_static_fdb_entries--; + + if (fdb_entry->section) + hashmap_remove(fdb_entry->network->fdb_entries_by_section, fdb_entry->section); + } + + network_config_section_free(fdb_entry->section); + return mfree(fdb_entry); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(FdbEntry, fdb_entry_free); + /* create a new FDB entry or get an existing one. */ static int fdb_entry_new_static( Network *network, @@ -171,24 +191,6 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { return 1; } -/* remove and FDB entry. */ -void fdb_entry_free(FdbEntry *fdb_entry) { - if (!fdb_entry) - return; - - if (fdb_entry->network) { - LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry); - assert(fdb_entry->network->n_static_fdb_entries > 0); - fdb_entry->network->n_static_fdb_entries--; - - if (fdb_entry->section) - hashmap_remove(fdb_entry->network->fdb_entries_by_section, fdb_entry->section); - } - - network_config_section_free(fdb_entry->section); - free(fdb_entry); -} - /* parse the HW address from config files. */ int config_parse_fdb_hwaddr( const char *unit, diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h index f607dfc70f..521376cb86 100644 --- a/src/network/networkd-fdb.h +++ b/src/network/networkd-fdb.h @@ -43,11 +43,9 @@ struct FdbEntry { LIST_FIELDS(FdbEntry, static_fdb_entries); }; -void fdb_entry_free(FdbEntry *fdb_entry); +FdbEntry *fdb_entry_free(FdbEntry *fdb_entry); int fdb_entry_configure(Link *link, FdbEntry *fdb_entry); -DEFINE_NETWORK_SECTION_FUNCTIONS(FdbEntry, fdb_entry_free); - const char* fdb_ntf_flags_to_string(NeighborCacheEntryFlags i) _const_; NeighborCacheEntryFlags fdb_ntf_flags_from_string(const char *s) _pure_; From 62ed9442bf551499be39c4e4ba12d7b405f3b3d6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 02:01:46 +0900 Subject: [PATCH 048/138] network: drop list of bridge FDB entries [BridgeFDB] sections are managed by both LIST and Hashmap, and they contains the completely same information. Let's drop the list. --- src/network/networkd-fdb.c | 52 +++++++++++++--------------------- src/network/networkd-fdb.h | 2 -- src/network/networkd-link.c | 2 +- src/network/networkd-network.c | 12 +++----- src/network/networkd-network.h | 2 -- 5 files changed, 25 insertions(+), 45 deletions(-) diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 43aaebb285..0337ec24a5 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -36,12 +36,8 @@ FdbEntry *fdb_entry_free(FdbEntry *fdb_entry) { return NULL; if (fdb_entry->network) { - LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry); - assert(fdb_entry->network->n_static_fdb_entries > 0); - fdb_entry->network->n_static_fdb_entries--; - - if (fdb_entry->section) - hashmap_remove(fdb_entry->network->fdb_entries_by_section, fdb_entry->section); + assert(fdb_entry->section); + hashmap_remove(fdb_entry->network->fdb_entries_by_section, fdb_entry->section); } network_config_section_free(fdb_entry->section); @@ -63,23 +59,21 @@ static int fdb_entry_new_static( assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); + + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; /* search entry in hashmap first. */ - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; - - fdb_entry = hashmap_get(network->fdb_entries_by_section, n); - if (fdb_entry) { - *ret = TAKE_PTR(fdb_entry); - - return 0; - } + fdb_entry = hashmap_get(network->fdb_entries_by_section, n); + if (fdb_entry) { + *ret = TAKE_PTR(fdb_entry); + return 0; } - if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX) + if (hashmap_size(network->fdb_entries_by_section) >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX) return -E2BIG; /* allocate space for and FDB entry. */ @@ -90,24 +84,18 @@ static int fdb_entry_new_static( /* init FDB structure. */ *fdb_entry = (FdbEntry) { .network = network, + .section = TAKE_PTR(n), .vni = VXLAN_VID_MAX + 1, .fdb_ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF, }; - LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry); - network->n_static_fdb_entries++; + r = hashmap_ensure_allocated(&network->fdb_entries_by_section, &network_config_hash_ops); + if (r < 0) + return r; - if (filename) { - fdb_entry->section = TAKE_PTR(n); - - r = hashmap_ensure_allocated(&network->fdb_entries_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->fdb_entries_by_section, fdb_entry->section, fdb_entry); - if (r < 0) - return r; - } + r = hashmap_put(network->fdb_entries_by_section, fdb_entry->section, fdb_entry); + if (r < 0) + return r; /* return allocated FDB structure. */ *ret = TAKE_PTR(fdb_entry); diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h index 521376cb86..c6b5055f8e 100644 --- a/src/network/networkd-fdb.h +++ b/src/network/networkd-fdb.h @@ -39,8 +39,6 @@ struct FdbEntry { struct ether_addr mac_addr; union in_addr_union destination_addr; NeighborCacheEntryFlags fdb_ntf_flags; - - LIST_FIELDS(FdbEntry, static_fdb_entries); }; FdbEntry *fdb_entry_free(FdbEntry *fdb_entry); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index b94e4945f3..c47bf75cdf 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1136,7 +1136,7 @@ static int link_set_bridge_fdb(Link *link) { FdbEntry *fdb_entry; int r; - LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) { + HASHMAP_FOREACH(fdb_entry, link->network->fdb_entries_by_section) { r = fdb_entry_configure(link, fdb_entry); if (r < 0) return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 95f3f65394..149c3cf2d3 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -156,7 +156,7 @@ int network_verify(Network *network) { Address *address, *address_next; Prefix *prefix, *prefix_next; Route *route, *route_next; - FdbEntry *fdb, *fdb_next; + FdbEntry *fdb; MdbEntry *mdb, *mdb_next; TrafficControl *tc; SRIOV *sr_iov; @@ -300,7 +300,7 @@ int network_verify(Network *network) { network_verify_nexthops(network); - LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries) + HASHMAP_FOREACH(fdb, network->fdb_entries_by_section) if (section_is_invalid(fdb->section)) fdb_entry_free(fdb); @@ -637,7 +637,6 @@ failure: static Network *network_free(Network *network) { IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; RoutePrefix *route_prefix; - FdbEntry *fdb_entry; MdbEntry *mdb_entry; Address *address; Prefix *prefix; @@ -704,9 +703,6 @@ static Network *network_free(Network *network) { while ((address = network->static_addresses)) address_free(address); - while ((fdb_entry = network->static_fdb_entries)) - fdb_entry_free(fdb_entry); - while ((mdb_entry = network->static_mdb_entries)) mdb_entry_free(mdb_entry); @@ -722,7 +718,7 @@ static Network *network_free(Network *network) { hashmap_free(network->addresses_by_section); hashmap_free(network->routes_by_section); hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free); - hashmap_free(network->fdb_entries_by_section); + hashmap_free_with_destructor(network->fdb_entries_by_section, fdb_entry_free); hashmap_free(network->mdb_entries_by_section); hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free); hashmap_free_with_destructor(network->address_labels_by_section, address_label_free); @@ -849,7 +845,7 @@ bool network_has_static_ipv6_configurations(Network *network) { if (route->family == AF_INET6) return true; - LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries) + HASHMAP_FOREACH(fdb, network->fdb_entries_by_section) if (fdb->family == AF_INET6) return true; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index c129338569..e1d22f1864 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -283,7 +283,6 @@ struct Network { LIST_HEAD(Address, static_addresses); LIST_HEAD(Route, static_routes); - LIST_HEAD(FdbEntry, static_fdb_entries); LIST_HEAD(MdbEntry, static_mdb_entries); LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); LIST_HEAD(Prefix, static_prefixes); @@ -291,7 +290,6 @@ struct Network { unsigned n_static_addresses; unsigned n_static_routes; - unsigned n_static_fdb_entries; unsigned n_static_mdb_entries; unsigned n_ipv6_proxy_ndp_addresses; unsigned n_static_prefixes; From 5bb4542b0c93f9e9b57f388b8f191945d192dba3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 02:05:08 +0900 Subject: [PATCH 049/138] network: move link_set_bridge_fdb() --- src/network/networkd-fdb.c | 18 +++++++++++++++++- src/network/networkd-fdb.h | 3 ++- src/network/networkd-link.c | 13 ------------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 0337ec24a5..792e02a066 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -122,7 +122,7 @@ static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) } /* send a request to the kernel to add a FDB entry in its static MAC table. */ -int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { +static int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -179,6 +179,22 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { return 1; } +int link_set_bridge_fdb(Link *link) { + FdbEntry *fdb_entry; + int r; + + assert(link); + assert(link->network); + + HASHMAP_FOREACH(fdb_entry, link->network->fdb_entries_by_section) { + r = fdb_entry_configure(link, fdb_entry); + if (r < 0) + return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); + } + + return 0; +} + /* parse the HW address from config files. */ int config_parse_fdb_hwaddr( const char *unit, diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h index c6b5055f8e..faddcf604e 100644 --- a/src/network/networkd-fdb.h +++ b/src/network/networkd-fdb.h @@ -42,7 +42,8 @@ struct FdbEntry { }; FdbEntry *fdb_entry_free(FdbEntry *fdb_entry); -int fdb_entry_configure(Link *link, FdbEntry *fdb_entry); + +int link_set_bridge_fdb(Link *link); const char* fdb_ntf_flags_to_string(NeighborCacheEntryFlags i) _const_; NeighborCacheEntryFlags fdb_ntf_flags_from_string(const char *s) _pure_; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index c47bf75cdf..2282749fa6 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1132,19 +1132,6 @@ void link_check_ready(Link *link) { return; } -static int link_set_bridge_fdb(Link *link) { - FdbEntry *fdb_entry; - int r; - - HASHMAP_FOREACH(fdb_entry, link->network->fdb_entries_by_section) { - r = fdb_entry_configure(link, fdb_entry); - if (r < 0) - return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); - } - - return 0; -} - static int static_address_ready_callback(Address *address) { Address *a; Link *link; From e6ad630d774054d93648be5e618bd0bfab2e6720 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 02:09:28 +0900 Subject: [PATCH 050/138] network: introduce network_verify_fdb_entries() --- src/network/networkd-fdb.c | 10 ++++++++++ src/network/networkd-fdb.h | 2 ++ src/network/networkd-network.c | 6 +----- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 792e02a066..05fd07c374 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -195,6 +195,16 @@ int link_set_bridge_fdb(Link *link) { return 0; } +void network_verify_fdb_entries(Network *network) { + FdbEntry *fdb_entry; + + assert(network); + + HASHMAP_FOREACH(fdb_entry, network->fdb_entries_by_section) + if (section_is_invalid(fdb_entry->section)) + fdb_entry_free(fdb_entry); +} + /* parse the HW address from config files. */ int config_parse_fdb_hwaddr( const char *unit, diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h index faddcf604e..39e016e867 100644 --- a/src/network/networkd-fdb.h +++ b/src/network/networkd-fdb.h @@ -43,6 +43,8 @@ struct FdbEntry { FdbEntry *fdb_entry_free(FdbEntry *fdb_entry); +void network_verify_fdb_entries(Network *network); + int link_set_bridge_fdb(Link *link); const char* fdb_ntf_flags_to_string(NeighborCacheEntryFlags i) _const_; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 149c3cf2d3..a8c32b9628 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -156,7 +156,6 @@ int network_verify(Network *network) { Address *address, *address_next; Prefix *prefix, *prefix_next; Route *route, *route_next; - FdbEntry *fdb; MdbEntry *mdb, *mdb_next; TrafficControl *tc; SRIOV *sr_iov; @@ -299,10 +298,7 @@ int network_verify(Network *network) { route_free(route); network_verify_nexthops(network); - - HASHMAP_FOREACH(fdb, network->fdb_entries_by_section) - if (section_is_invalid(fdb->section)) - fdb_entry_free(fdb); + network_verify_fdb_entries(network); LIST_FOREACH_SAFE(static_mdb_entries, mdb, mdb_next, network->static_mdb_entries) if (mdb_entry_verify(mdb) < 0) From 75ffb011b059be96d73241e6eb4a481ec667a4cb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 02:14:19 +0900 Subject: [PATCH 051/138] network: drop unused fdb_ntf_flags_to_string() --- src/network/networkd-fdb.c | 18 +++++++++--------- src/network/networkd-fdb.h | 3 --- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 05fd07c374..c5e591d50b 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -21,15 +21,6 @@ #define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U -static const char* const fdb_ntf_flags_table[_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX] = { - [NEIGHBOR_CACHE_ENTRY_FLAGS_USE] = "use", - [NEIGHBOR_CACHE_ENTRY_FLAGS_SELF] = "self", - [NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER] = "master", - [NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER] = "router", -}; - -DEFINE_STRING_TABLE_LOOKUP(fdb_ntf_flags, NeighborCacheEntryFlags); - /* remove and FDB entry. */ FdbEntry *fdb_entry_free(FdbEntry *fdb_entry) { if (!fdb_entry) @@ -368,6 +359,15 @@ int config_parse_fdb_vxlan_vni( return 0; } +static const char* const fdb_ntf_flags_table[_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX] = { + [NEIGHBOR_CACHE_ENTRY_FLAGS_USE] = "use", + [NEIGHBOR_CACHE_ENTRY_FLAGS_SELF] = "self", + [NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER] = "master", + [NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER] = "router", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fdb_ntf_flags, NeighborCacheEntryFlags); + int config_parse_fdb_ntf_flags( const char *unit, const char *filename, diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h index 39e016e867..9ab44f9d3e 100644 --- a/src/network/networkd-fdb.h +++ b/src/network/networkd-fdb.h @@ -47,9 +47,6 @@ void network_verify_fdb_entries(Network *network); int link_set_bridge_fdb(Link *link); -const char* fdb_ntf_flags_to_string(NeighborCacheEntryFlags i) _const_; -NeighborCacheEntryFlags fdb_ntf_flags_from_string(const char *s) _pure_; - CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination); From ee446d57b844d18c3a283b62fe8fca0daac90e96 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 02:24:02 +0900 Subject: [PATCH 052/138] network: cleanup networkd-fdb.h --- src/network/networkd-fdb.c | 5 ++--- src/network/networkd-fdb.h | 10 ++++------ src/network/networkd-link.c | 1 + src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 - src/network/networkd-sriov.h | 1 + src/network/networkd-wifi.c | 1 + src/network/test-network.c | 1 + 9 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index c5e591d50b..47db929187 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -8,14 +8,13 @@ #include "alloc-util.h" #include "bridge.h" -#include "conf-parser.h" #include "netlink-util.h" #include "networkd-fdb.h" +#include "networkd-link.h" #include "networkd-manager.h" +#include "networkd-network.h" #include "parse-util.h" -#include "string-util.h" #include "string-table.h" -#include "util.h" #include "vlan-util.h" #include "vxlan.h" diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h index 9ab44f9d3e..4aeb8be9ce 100644 --- a/src/network/networkd-fdb.h +++ b/src/network/networkd-fdb.h @@ -5,18 +5,16 @@ Copyright © 2014 Intel Corporation. All rights reserved. ***/ +#include #include #include "conf-parser.h" #include "ether-addr-util.h" -#include "list.h" -#include "macro.h" +#include "in-addr-util.h" #include "networkd-util.h" typedef struct Network Network; -typedef struct FdbEntry FdbEntry; typedef struct Link Link; -typedef struct NetworkConfigSection NetworkConfigSection; typedef enum NeighborCacheEntryFlags { NEIGHBOR_CACHE_ENTRY_FLAGS_USE = NTF_USE, @@ -27,7 +25,7 @@ typedef enum NeighborCacheEntryFlags { _NEIGHBOR_CACHE_ENTRY_FLAGS_INVALID = -1, } NeighborCacheEntryFlags; -struct FdbEntry { +typedef struct FdbEntry { Network *network; NetworkConfigSection *section; @@ -39,7 +37,7 @@ struct FdbEntry { struct ether_addr mac_addr; union in_addr_union destination_addr; NeighborCacheEntryFlags fdb_ntf_flags; -}; +} FdbEntry; FdbEntry *fdb_entry_free(FdbEntry *fdb_entry); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 2282749fa6..aa9c0c528a 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -25,6 +25,7 @@ #include "networkd-dhcp-server.h" #include "networkd-dhcp4.h" #include "networkd-dhcp6.h" +#include "networkd-fdb.h" #include "networkd-ipv4ll.h" #include "networkd-ipv6-proxy-ndp.h" #include "networkd-link-bus.h" diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 648e882a29..ac28de39aa 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -13,6 +13,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "networkd-dhcp-server.h" #include "networkd-dhcp4.h" #include "networkd-dhcp6.h" +#include "networkd-fdb.h" #include "networkd-ipv4ll.h" #include "networkd-ndisc.h" #include "networkd-network.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index a8c32b9628..25b0046bd9 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -15,6 +15,7 @@ #include "networkd-dhcp-server.h" #include "network-internal.h" #include "networkd-address-label.h" +#include "networkd-fdb.h" #include "networkd-manager.h" #include "networkd-neighbor.h" #include "networkd-network.h" diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index e1d22f1864..d471c98239 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -18,7 +18,6 @@ #include "networkd-dhcp4.h" #include "networkd-dhcp6.h" #include "networkd-dhcp-server.h" -#include "networkd-fdb.h" #include "networkd-ipv6-proxy-ndp.h" #include "networkd-lldp-rx.h" #include "networkd-lldp-tx.h" diff --git a/src/network/networkd-sriov.h b/src/network/networkd-sriov.h index a545d1292a..04cc4270f1 100644 --- a/src/network/networkd-sriov.h +++ b/src/network/networkd-sriov.h @@ -5,6 +5,7 @@ #include #include "conf-parser.h" +#include "ether-addr-util.h" #include "networkd-link.h" #include "networkd-network.h" #include "networkd-util.h" diff --git a/src/network/networkd-wifi.c b/src/network/networkd-wifi.c index 14a8687458..53b65286b3 100644 --- a/src/network/networkd-wifi.c +++ b/src/network/networkd-wifi.c @@ -6,6 +6,7 @@ #include "sd-bus.h" #include "bus-util.h" +#include "ether-addr-util.h" #include "netlink-internal.h" #include "netlink-util.h" #include "networkd-link.h" diff --git a/src/network/test-network.c b/src/network/test-network.c index eeb756ca04..e93e8c0cc0 100644 --- a/src/network/test-network.c +++ b/src/network/test-network.c @@ -7,6 +7,7 @@ #include "alloc-util.h" #include "dhcp-lease-internal.h" +#include "ether-addr-util.h" #include "hostname-util.h" #include "network-internal.h" #include "networkd-manager.h" From 8c06da1cd1038d3baf906b79dfdcffe004929c0d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 02:33:14 +0900 Subject: [PATCH 053/138] network: move mdb_entry_free() and friends --- src/network/networkd-mdb.c | 40 ++++++++++++++++++++------------------ src/network/networkd-mdb.h | 2 -- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/network/networkd-mdb.c b/src/network/networkd-mdb.c index 542ba75ad0..0ac770264c 100644 --- a/src/network/networkd-mdb.c +++ b/src/network/networkd-mdb.c @@ -10,6 +10,27 @@ #define STATIC_MDB_ENTRIES_PER_NETWORK_MAX 1024U +/* remove MDB entry. */ +MdbEntry *mdb_entry_free(MdbEntry *mdb_entry) { + if (!mdb_entry) + return NULL; + + if (mdb_entry->network) { + LIST_REMOVE(static_mdb_entries, mdb_entry->network->static_mdb_entries, mdb_entry); + assert(mdb_entry->network->n_static_mdb_entries > 0); + mdb_entry->network->n_static_mdb_entries--; + + if (mdb_entry->section) + hashmap_remove(mdb_entry->network->mdb_entries_by_section, mdb_entry->section); + } + + network_config_section_free(mdb_entry->section); + + return mfree(mdb_entry); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(MdbEntry, mdb_entry_free); + /* create a new MDB entry or get an existing one. */ static int mdb_entry_new_static( Network *network, @@ -72,25 +93,6 @@ static int mdb_entry_new_static( return 0; } -/* remove and MDB entry. */ -MdbEntry *mdb_entry_free(MdbEntry *mdb_entry) { - if (!mdb_entry) - return NULL; - - if (mdb_entry->network) { - LIST_REMOVE(static_mdb_entries, mdb_entry->network->static_mdb_entries, mdb_entry); - assert(mdb_entry->network->n_static_mdb_entries > 0); - mdb_entry->network->n_static_mdb_entries--; - - if (mdb_entry->section) - hashmap_remove(mdb_entry->network->mdb_entries_by_section, mdb_entry->section); - } - - network_config_section_free(mdb_entry->section); - - return mfree(mdb_entry); -} - static int set_mdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; diff --git a/src/network/networkd-mdb.h b/src/network/networkd-mdb.h index d46ab4a50e..70250b5d45 100644 --- a/src/network/networkd-mdb.h +++ b/src/network/networkd-mdb.h @@ -26,7 +26,5 @@ int mdb_entry_verify(MdbEntry *mdb_entry); MdbEntry *mdb_entry_free(MdbEntry *mdb_entry); int link_set_bridge_mdb(Link *link); -DEFINE_NETWORK_SECTION_FUNCTIONS(MdbEntry, mdb_entry_free); - CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_vlan_id); From 03c9738e1d4b22c0b23f06e2ceb7599b15e16f1a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 02:40:28 +0900 Subject: [PATCH 054/138] network: drop list of bridge MDB entries [BridgeMDB] sections are managed by LIST and Hashmap, and they contins the completely same information. Let's drop the list. --- src/network/networkd-mdb.c | 56 +++++++++++++--------------------- src/network/networkd-mdb.h | 2 -- src/network/networkd-network.c | 12 +++----- src/network/networkd-network.h | 2 -- 4 files changed, 26 insertions(+), 46 deletions(-) diff --git a/src/network/networkd-mdb.c b/src/network/networkd-mdb.c index 0ac770264c..3bf18dbd71 100644 --- a/src/network/networkd-mdb.c +++ b/src/network/networkd-mdb.c @@ -16,12 +16,8 @@ MdbEntry *mdb_entry_free(MdbEntry *mdb_entry) { return NULL; if (mdb_entry->network) { - LIST_REMOVE(static_mdb_entries, mdb_entry->network->static_mdb_entries, mdb_entry); - assert(mdb_entry->network->n_static_mdb_entries > 0); - mdb_entry->network->n_static_mdb_entries--; - - if (mdb_entry->section) - hashmap_remove(mdb_entry->network->mdb_entries_by_section, mdb_entry->section); + assert(mdb_entry->section); + hashmap_remove(mdb_entry->network->mdb_entries_by_section, mdb_entry->section); } network_config_section_free(mdb_entry->section); @@ -44,22 +40,21 @@ static int mdb_entry_new_static( assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); + + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; /* search entry in hashmap first. */ - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; - - mdb_entry = hashmap_get(network->mdb_entries_by_section, n); - if (mdb_entry) { - *ret = TAKE_PTR(mdb_entry); - return 0; - } + mdb_entry = hashmap_get(network->mdb_entries_by_section, n); + if (mdb_entry) { + *ret = TAKE_PTR(mdb_entry); + return 0; } - if (network->n_static_mdb_entries >= STATIC_MDB_ENTRIES_PER_NETWORK_MAX) + if (hashmap_size(network->mdb_entries_by_section) >= STATIC_MDB_ENTRIES_PER_NETWORK_MAX) return -E2BIG; /* allocate space for an MDB entry. */ @@ -70,26 +65,19 @@ static int mdb_entry_new_static( /* init MDB structure. */ *mdb_entry = (MdbEntry) { .network = network, + .section = TAKE_PTR(n), }; - LIST_PREPEND(static_mdb_entries, network->static_mdb_entries, mdb_entry); - network->n_static_mdb_entries++; + r = hashmap_ensure_allocated(&network->mdb_entries_by_section, &network_config_hash_ops); + if (r < 0) + return r; - if (filename) { - mdb_entry->section = TAKE_PTR(n); - - r = hashmap_ensure_allocated(&network->mdb_entries_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->mdb_entries_by_section, mdb_entry->section, mdb_entry); - if (r < 0) - return r; - } + r = hashmap_put(network->mdb_entries_by_section, mdb_entry->section, mdb_entry); + if (r < 0) + return r; /* return allocated MDB structure. */ *ret = TAKE_PTR(mdb_entry); - return 0; } @@ -214,7 +202,7 @@ int link_set_bridge_mdb(Link *link) { if (!link->network) return 0; - if (LIST_IS_EMPTY(link->network->static_mdb_entries)) + if (hashmap_isempty(link->network->mdb_entries_by_section)) goto finish; if (!link_has_carrier(link)) @@ -238,7 +226,7 @@ int link_set_bridge_mdb(Link *link) { goto finish; } - LIST_FOREACH(static_mdb_entries, mdb_entry, link->network->static_mdb_entries) { + HASHMAP_FOREACH(mdb_entry, link->network->mdb_entries_by_section) { r = mdb_entry_configure(link, mdb_entry); if (r < 0) return log_link_error_errno(link, r, "Failed to add MDB entry to multicast group database: %m"); diff --git a/src/network/networkd-mdb.h b/src/network/networkd-mdb.h index 70250b5d45..00c16463b8 100644 --- a/src/network/networkd-mdb.h +++ b/src/network/networkd-mdb.h @@ -18,8 +18,6 @@ struct MdbEntry { int family; union in_addr_union group_addr; uint16_t vlan_id; - - LIST_FIELDS(MdbEntry, static_mdb_entries); }; int mdb_entry_verify(MdbEntry *mdb_entry); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 25b0046bd9..7a0feae8fc 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -157,7 +157,7 @@ int network_verify(Network *network) { Address *address, *address_next; Prefix *prefix, *prefix_next; Route *route, *route_next; - MdbEntry *mdb, *mdb_next; + MdbEntry *mdb; TrafficControl *tc; SRIOV *sr_iov; @@ -301,7 +301,7 @@ int network_verify(Network *network) { network_verify_nexthops(network); network_verify_fdb_entries(network); - LIST_FOREACH_SAFE(static_mdb_entries, mdb, mdb_next, network->static_mdb_entries) + HASHMAP_FOREACH(mdb, network->mdb_entries_by_section) if (mdb_entry_verify(mdb) < 0) mdb_entry_free(mdb); @@ -634,7 +634,6 @@ failure: static Network *network_free(Network *network) { IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; RoutePrefix *route_prefix; - MdbEntry *mdb_entry; Address *address; Prefix *prefix; Route *route; @@ -700,9 +699,6 @@ static Network *network_free(Network *network) { while ((address = network->static_addresses)) address_free(address); - while ((mdb_entry = network->static_mdb_entries)) - mdb_entry_free(mdb_entry); - while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses)) ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address); @@ -716,7 +712,7 @@ static Network *network_free(Network *network) { hashmap_free(network->routes_by_section); hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free); hashmap_free_with_destructor(network->fdb_entries_by_section, fdb_entry_free); - hashmap_free(network->mdb_entries_by_section); + hashmap_free_with_destructor(network->mdb_entries_by_section, mdb_entry_free); hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free); hashmap_free_with_destructor(network->address_labels_by_section, address_label_free); hashmap_free(network->prefixes_by_section); @@ -846,7 +842,7 @@ bool network_has_static_ipv6_configurations(Network *network) { if (fdb->family == AF_INET6) return true; - LIST_FOREACH(static_mdb_entries, mdb, network->static_mdb_entries) + HASHMAP_FOREACH(mdb, network->mdb_entries_by_section) if (mdb->family == AF_INET6) return true; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index d471c98239..e584e5d460 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -282,14 +282,12 @@ struct Network { LIST_HEAD(Address, static_addresses); LIST_HEAD(Route, static_routes); - LIST_HEAD(MdbEntry, static_mdb_entries); LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); LIST_HEAD(Prefix, static_prefixes); LIST_HEAD(RoutePrefix, static_route_prefixes); unsigned n_static_addresses; unsigned n_static_routes; - unsigned n_static_mdb_entries; unsigned n_ipv6_proxy_ndp_addresses; unsigned n_static_prefixes; unsigned n_static_route_prefixes; From ee4522ce86fa8735006b51d066b04de93fcd7261 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 02:44:57 +0900 Subject: [PATCH 055/138] network: introduce network_verify_mdb_entries() --- src/network/networkd-mdb.c | 76 +++++++++++++++++++--------------- src/network/networkd-mdb.h | 4 +- src/network/networkd-network.c | 7 +--- 3 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/network/networkd-mdb.c b/src/network/networkd-mdb.c index 3bf18dbd71..31234ba3bc 100644 --- a/src/network/networkd-mdb.c +++ b/src/network/networkd-mdb.c @@ -243,6 +243,49 @@ finish: return 0; } +static int mdb_entry_verify(MdbEntry *mdb_entry) { + if (section_is_invalid(mdb_entry->section)) + return -EINVAL; + + if (mdb_entry->family == AF_UNSPEC) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: [BridgeMDB] section without MulticastGroupAddress= field configured. " + "Ignoring [BridgeMDB] section from line %u.", + mdb_entry->section->filename, mdb_entry->section->line); + + if (!in_addr_is_multicast(mdb_entry->family, &mdb_entry->group_addr)) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: MulticastGroupAddress= is not a multicast address. " + "Ignoring [BridgeMDB] section from line %u.", + mdb_entry->section->filename, mdb_entry->section->line); + + if (mdb_entry->family == AF_INET) { + if (in4_addr_is_local_multicast(&mdb_entry->group_addr.in)) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: MulticastGroupAddress= is a local multicast address. " + "Ignoring [BridgeMDB] section from line %u.", + mdb_entry->section->filename, mdb_entry->section->line); + } else { + if (in6_addr_is_link_local_all_nodes(&mdb_entry->group_addr.in6)) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: MulticastGroupAddress= is the multicast all nodes address. " + "Ignoring [BridgeMDB] section from line %u.", + mdb_entry->section->filename, mdb_entry->section->line); + } + + return 0; +} + +void network_verify_mdb_entries(Network *network) { + MdbEntry *mdb_entry; + + assert(network); + + HASHMAP_FOREACH(mdb_entry, network->mdb_entries_by_section) + if (mdb_entry_verify(mdb_entry) < 0) + mdb_entry_free(mdb_entry); +} + /* parse the VLAN Id from config files. */ int config_parse_mdb_vlan_id( const char *unit, @@ -318,36 +361,3 @@ int config_parse_mdb_group_address( return 0; } - -int mdb_entry_verify(MdbEntry *mdb_entry) { - if (section_is_invalid(mdb_entry->section)) - return -EINVAL; - - if (mdb_entry->family == AF_UNSPEC) - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: [BridgeMDB] section without MulticastGroupAddress= field configured. " - "Ignoring [BridgeMDB] section from line %u.", - mdb_entry->section->filename, mdb_entry->section->line); - - if (!in_addr_is_multicast(mdb_entry->family, &mdb_entry->group_addr)) - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: MulticastGroupAddress= is not a multicast address. " - "Ignoring [BridgeMDB] section from line %u.", - mdb_entry->section->filename, mdb_entry->section->line); - - if (mdb_entry->family == AF_INET) { - if (in4_addr_is_local_multicast(&mdb_entry->group_addr.in)) - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: MulticastGroupAddress= is a local multicast address. " - "Ignoring [BridgeMDB] section from line %u.", - mdb_entry->section->filename, mdb_entry->section->line); - } else { - if (in6_addr_is_link_local_all_nodes(&mdb_entry->group_addr.in6)) - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: MulticastGroupAddress= is the multicast all nodes address. " - "Ignoring [BridgeMDB] section from line %u.", - mdb_entry->section->filename, mdb_entry->section->line); - } - - return 0; -} diff --git a/src/network/networkd-mdb.h b/src/network/networkd-mdb.h index 00c16463b8..b3d0513293 100644 --- a/src/network/networkd-mdb.h +++ b/src/network/networkd-mdb.h @@ -20,8 +20,10 @@ struct MdbEntry { uint16_t vlan_id; }; -int mdb_entry_verify(MdbEntry *mdb_entry); MdbEntry *mdb_entry_free(MdbEntry *mdb_entry); + +void network_verify_mdb_entries(Network *network); + int link_set_bridge_mdb(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 7a0feae8fc..67acb1e761 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -157,7 +157,6 @@ int network_verify(Network *network) { Address *address, *address_next; Prefix *prefix, *prefix_next; Route *route, *route_next; - MdbEntry *mdb; TrafficControl *tc; SRIOV *sr_iov; @@ -300,11 +299,7 @@ int network_verify(Network *network) { network_verify_nexthops(network); network_verify_fdb_entries(network); - - HASHMAP_FOREACH(mdb, network->mdb_entries_by_section) - if (mdb_entry_verify(mdb) < 0) - mdb_entry_free(mdb); - + network_verify_mdb_entries(network); network_verify_neighbors(network); network_verify_address_labels(network); From dbf6319691207a1a384a52da982e8e83a21693cd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 02:49:14 +0900 Subject: [PATCH 056/138] network: cleanup networkd-mdb.h --- src/network/networkd-link.c | 1 + src/network/networkd-mdb.c | 2 ++ src/network/networkd-mdb.h | 11 +++++------ src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 - 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index aa9c0c528a..36f627c48c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -32,6 +32,7 @@ #include "networkd-link.h" #include "networkd-lldp-tx.h" #include "networkd-manager.h" +#include "networkd-mdb.h" #include "networkd-ndisc.h" #include "networkd-neighbor.h" #include "networkd-nexthop.h" diff --git a/src/network/networkd-mdb.c b/src/network/networkd-mdb.c index 31234ba3bc..169cc6eb00 100644 --- a/src/network/networkd-mdb.c +++ b/src/network/networkd-mdb.c @@ -3,8 +3,10 @@ #include #include "netlink-util.h" +#include "networkd-link.h" #include "networkd-manager.h" #include "networkd-mdb.h" +#include "networkd-network.h" #include "string-util.h" #include "vlan-util.h" diff --git a/src/network/networkd-mdb.h b/src/network/networkd-mdb.h index b3d0513293..e0d9052497 100644 --- a/src/network/networkd-mdb.h +++ b/src/network/networkd-mdb.h @@ -1,24 +1,23 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include + #include "conf-parser.h" -#include "list.h" -#include "macro.h" +#include "in-addr-util.h" #include "networkd-util.h" typedef struct Network Network; -typedef struct MdbEntry MdbEntry; typedef struct Link Link; -typedef struct NetworkConfigSection NetworkConfigSection; -struct MdbEntry { +typedef struct MdbEntry { Network *network; NetworkConfigSection *section; int family; union in_addr_union group_addr; uint16_t vlan_id; -}; +} MdbEntry; MdbEntry *mdb_entry_free(MdbEntry *mdb_entry); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index ac28de39aa..51a1533554 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -15,6 +15,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "networkd-dhcp6.h" #include "networkd-fdb.h" #include "networkd-ipv4ll.h" +#include "networkd-mdb.h" #include "networkd-ndisc.h" #include "networkd-network.h" #include "networkd-neighbor.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 67acb1e761..864eb1b4c9 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -17,6 +17,7 @@ #include "networkd-address-label.h" #include "networkd-fdb.h" #include "networkd-manager.h" +#include "networkd-mdb.h" #include "networkd-neighbor.h" #include "networkd-network.h" #include "networkd-nexthop.h" diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index e584e5d460..9a2e364303 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -21,7 +21,6 @@ #include "networkd-ipv6-proxy-ndp.h" #include "networkd-lldp-rx.h" #include "networkd-lldp-tx.h" -#include "networkd-mdb.h" #include "networkd-ndisc.h" #include "networkd-radv.h" #include "networkd-route.h" From a8c82f90e778ed72ce5d4b9cc7b1ed69ea1691a5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 04:37:18 +0900 Subject: [PATCH 057/138] network: move functions --- src/network/networkd-ipv6-proxy-ndp.c | 186 +++++++++++++------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index 7051ba9dac..96e4b6453a 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -14,40 +14,19 @@ #include "string-util.h" #include "sysctl-util.h" -static bool ipv6_proxy_ndp_is_needed(Link *link) { - assert(link); +void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address) { + if (!ipv6_proxy_ndp_address) + return; - if (link->flags & IFF_LOOPBACK) - return false; + if (ipv6_proxy_ndp_address->network) { + LIST_REMOVE(ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address->network->ipv6_proxy_ndp_addresses, + ipv6_proxy_ndp_address); - if (!link->network) - return false; + assert(ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses > 0); + ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses--; + } - if (link->network->ipv6_proxy_ndp >= 0) - return link->network->ipv6_proxy_ndp; - - if (link->network->n_ipv6_proxy_ndp_addresses == 0) - return false; - - return true; -} - -static int ipv6_proxy_ndp_set(Link *link) { - bool v; - int r; - - assert(link); - - if (!socket_ipv6_is_supported()) - return 0; - - v = ipv6_proxy_ndp_is_needed(link); - - r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v); - if (r < 0) - log_link_warning_errno(link, r, "Cannot configure proxy NDP for interface: %m"); - - return 0; + free(ipv6_proxy_ndp_address); } static int ipv6_proxy_ndp_address_new_static(Network *network, IPv6ProxyNDPAddress **ret) { @@ -73,68 +52,6 @@ static int ipv6_proxy_ndp_address_new_static(Network *network, IPv6ProxyNDPAddre return 0; } -void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address) { - if (!ipv6_proxy_ndp_address) - return; - - if (ipv6_proxy_ndp_address->network) { - LIST_REMOVE(ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address->network->ipv6_proxy_ndp_addresses, - ipv6_proxy_ndp_address); - - assert(ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses > 0); - ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses--; - } - - free(ipv6_proxy_ndp_address); -} - -int config_parse_ipv6_proxy_ndp_address( - 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) { - - Network *network = userdata; - _cleanup_(ipv6_proxy_ndp_address_freep) IPv6ProxyNDPAddress *ipv6_proxy_ndp_address = NULL; - int r; - union in_addr_union buffer; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = ipv6_proxy_ndp_address_new_static(network, &ipv6_proxy_ndp_address); - if (r < 0) - return log_oom(); - - r = in_addr_from_string(AF_INET6, rvalue, &buffer); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse IPv6 proxy NDP address, ignoring: %s", - rvalue); - return 0; - } - - if (in_addr_is_null(AF_INET6, &buffer)) { - log_syntax(unit, LOG_WARNING, filename, line, 0, - "IPv6 proxy NDP address cannot be the ANY address, ignoring: %s", rvalue); - return 0; - } - - ipv6_proxy_ndp_address->in_addr = buffer.in6; - ipv6_proxy_ndp_address = NULL; - - return 0; -} - static int set_ipv6_proxy_ndp_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -183,6 +100,42 @@ int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy return 0; } +static bool ipv6_proxy_ndp_is_needed(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->ipv6_proxy_ndp >= 0) + return link->network->ipv6_proxy_ndp; + + if (link->network->n_ipv6_proxy_ndp_addresses == 0) + return false; + + return true; +} + +static int ipv6_proxy_ndp_set(Link *link) { + bool v; + int r; + + assert(link); + + if (!socket_ipv6_is_supported()) + return 0; + + v = ipv6_proxy_ndp_is_needed(link); + + r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure proxy NDP for interface: %m"); + + return 0; +} + /* configure all ipv6 proxy ndp addresses */ int ipv6_proxy_ndp_addresses_configure(Link *link) { IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; @@ -202,3 +155,50 @@ int ipv6_proxy_ndp_addresses_configure(Link *link) { } return 0; } + +int config_parse_ipv6_proxy_ndp_address( + 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) { + + Network *network = userdata; + _cleanup_(ipv6_proxy_ndp_address_freep) IPv6ProxyNDPAddress *ipv6_proxy_ndp_address = NULL; + int r; + union in_addr_union buffer; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = ipv6_proxy_ndp_address_new_static(network, &ipv6_proxy_ndp_address); + if (r < 0) + return log_oom(); + + r = in_addr_from_string(AF_INET6, rvalue, &buffer); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse IPv6 proxy NDP address, ignoring: %s", + rvalue); + return 0; + } + + if (in_addr_is_null(AF_INET6, &buffer)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "IPv6 proxy NDP address cannot be the ANY address, ignoring: %s", rvalue); + return 0; + } + + ipv6_proxy_ndp_address->in_addr = buffer.in6; + ipv6_proxy_ndp_address = NULL; + + return 0; +} From d349f5026e2131395f63b3a7dbeaded88d14833d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 05:06:17 +0900 Subject: [PATCH 058/138] network: drop struct IPv6ProxyNDPAddress Its only important value is in6_addr. So, let's just use struct in6_addr and drop IPv6ProxyNDPAddress. --- src/network/networkd-ipv6-proxy-ndp.c | 98 ++++++++------------------- src/network/networkd-ipv6-proxy-ndp.h | 15 ---- src/network/networkd-network.c | 5 +- src/network/networkd-network.h | 3 +- 4 files changed, 32 insertions(+), 89 deletions(-) diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index 96e4b6453a..fc429d25b2 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -14,44 +14,6 @@ #include "string-util.h" #include "sysctl-util.h" -void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address) { - if (!ipv6_proxy_ndp_address) - return; - - if (ipv6_proxy_ndp_address->network) { - LIST_REMOVE(ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address->network->ipv6_proxy_ndp_addresses, - ipv6_proxy_ndp_address); - - assert(ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses > 0); - ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses--; - } - - free(ipv6_proxy_ndp_address); -} - -static int ipv6_proxy_ndp_address_new_static(Network *network, IPv6ProxyNDPAddress **ret) { - _cleanup_(ipv6_proxy_ndp_address_freep) IPv6ProxyNDPAddress *ipv6_proxy_ndp_address = NULL; - - assert(network); - assert(ret); - - /* allocate space for IPv6ProxyNDPAddress entry */ - ipv6_proxy_ndp_address = new(IPv6ProxyNDPAddress, 1); - if (!ipv6_proxy_ndp_address) - return -ENOMEM; - - *ipv6_proxy_ndp_address = (IPv6ProxyNDPAddress) { - .network = network, - }; - - LIST_PREPEND(ipv6_proxy_ndp_addresses, network->ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address); - network->n_ipv6_proxy_ndp_addresses++; - - *ret = TAKE_PTR(ipv6_proxy_ndp_address); - - return 0; -} - static int set_ipv6_proxy_ndp_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -65,20 +27,16 @@ static int set_ipv6_proxy_ndp_address_handler(sd_netlink *rtnl, sd_netlink_messa } /* send a request to the kernel to add a IPv6 Proxy entry to the neighbour table */ -int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy_ndp_address) { +static int ipv6_proxy_ndp_address_configure(Link *link, const struct in6_addr *address) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - sd_netlink *rtnl; int r; assert(link); - assert(link->network); assert(link->manager); - assert(ipv6_proxy_ndp_address); - - rtnl = link->manager->rtnl; + assert(address); /* create new netlink message */ - r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, AF_INET6); + r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, AF_INET6); if (r < 0) return log_link_error_errno(link, r, "Could not create RTM_NEWNEIGH message: %m"); @@ -86,11 +44,11 @@ int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy if (r < 0) return log_link_error_errno(link, r, "Could not set neighbor flags: %m"); - r = sd_netlink_message_append_in6_addr(req, NDA_DST, &ipv6_proxy_ndp_address->in_addr); + r = sd_netlink_message_append_in6_addr(req, NDA_DST, address); if (r < 0) return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); - r = netlink_call_async(rtnl, NULL, req, set_ipv6_proxy_ndp_address_handler, + r = netlink_call_async(link->manager->rtnl, NULL, req, set_ipv6_proxy_ndp_address_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -112,10 +70,7 @@ static bool ipv6_proxy_ndp_is_needed(Link *link) { if (link->network->ipv6_proxy_ndp >= 0) return link->network->ipv6_proxy_ndp; - if (link->network->n_ipv6_proxy_ndp_addresses == 0) - return false; - - return true; + return !set_isempty(link->network->ipv6_proxy_ndp_addresses); } static int ipv6_proxy_ndp_set(Link *link) { @@ -138,21 +93,23 @@ static int ipv6_proxy_ndp_set(Link *link) { /* configure all ipv6 proxy ndp addresses */ int ipv6_proxy_ndp_addresses_configure(Link *link) { - IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; + struct in6_addr *address; int r; assert(link); + assert(link->network); /* enable or disable proxy_ndp itself depending on whether ipv6_proxy_ndp_addresses are set or not */ r = ipv6_proxy_ndp_set(link); - if (r != 0) + if (r < 0) return r; - LIST_FOREACH(ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address, link->network->ipv6_proxy_ndp_addresses) { - r = ipv6_proxy_ndp_address_configure(link, ipv6_proxy_ndp_address); - if (r != 0) + SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) { + r = ipv6_proxy_ndp_address_configure(link, address); + if (r < 0) return r; } + return 0; } @@ -168,26 +125,24 @@ int config_parse_ipv6_proxy_ndp_address( void *data, void *userdata) { + _cleanup_free_ struct in6_addr *address = NULL; Network *network = userdata; - _cleanup_(ipv6_proxy_ndp_address_freep) IPv6ProxyNDPAddress *ipv6_proxy_ndp_address = NULL; - int r; union in_addr_union buffer; + int r; assert(filename); - assert(section); - assert(lvalue); assert(rvalue); - assert(data); + assert(network); - r = ipv6_proxy_ndp_address_new_static(network, &ipv6_proxy_ndp_address); - if (r < 0) - return log_oom(); + if (isempty(rvalue)) { + network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses); + return 0; + } r = in_addr_from_string(AF_INET6, rvalue, &buffer); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse IPv6 proxy NDP address, ignoring: %s", - rvalue); + "Failed to parse IPv6 proxy NDP address, ignoring: %s", rvalue); return 0; } @@ -197,8 +152,15 @@ int config_parse_ipv6_proxy_ndp_address( return 0; } - ipv6_proxy_ndp_address->in_addr = buffer.in6; - ipv6_proxy_ndp_address = NULL; + address = newdup(struct in6_addr, &buffer.in6, 1); + if (!address) + return log_oom(); + + r = set_ensure_put(&network->ipv6_proxy_ndp_addresses, &in6_addr_hash_ops, address); + if (r < 0) + return log_oom(); + if (r > 0) + TAKE_PTR(address); return 0; } diff --git a/src/network/networkd-ipv6-proxy-ndp.h b/src/network/networkd-ipv6-proxy-ndp.h index d6666beab5..c7590001ff 100644 --- a/src/network/networkd-ipv6-proxy-ndp.h +++ b/src/network/networkd-ipv6-proxy-ndp.h @@ -2,24 +2,9 @@ #pragma once #include "conf-parser.h" -#include "list.h" -#include "macro.h" -typedef struct Network Network; -typedef struct IPv6ProxyNDPAddress IPv6ProxyNDPAddress; typedef struct Link Link; -struct IPv6ProxyNDPAddress { - Network *network; - struct in6_addr in_addr; - - LIST_FIELDS(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); -}; - -void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address); -int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy_ndp_address); int ipv6_proxy_ndp_addresses_configure(Link *link); -DEFINE_TRIVIAL_CLEANUP_FUNC(IPv6ProxyNDPAddress*, ipv6_proxy_ndp_address_free); - CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 864eb1b4c9..a8021f863f 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -628,7 +628,6 @@ failure: } static Network *network_free(Network *network) { - IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; RoutePrefix *route_prefix; Address *address; Prefix *prefix; @@ -695,15 +694,13 @@ static Network *network_free(Network *network) { while ((address = network->static_addresses)) address_free(address); - while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses)) - ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address); - while ((prefix = network->static_prefixes)) prefix_free(prefix); while ((route_prefix = network->static_route_prefixes)) route_prefix_free(route_prefix); + set_free_free(network->ipv6_proxy_ndp_addresses); hashmap_free(network->addresses_by_section); hashmap_free(network->routes_by_section); hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 9a2e364303..e22c60e9ea 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -239,6 +239,7 @@ struct Network { int ipv6_dad_transmits; int ipv6_hop_limit; int ipv6_proxy_ndp; + Set *ipv6_proxy_ndp_addresses; int proxy_arp; uint32_t ipv6_mtu; @@ -281,13 +282,11 @@ struct Network { LIST_HEAD(Address, static_addresses); LIST_HEAD(Route, static_routes); - LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); LIST_HEAD(Prefix, static_prefixes); LIST_HEAD(RoutePrefix, static_route_prefixes); unsigned n_static_addresses; unsigned n_static_routes; - unsigned n_ipv6_proxy_ndp_addresses; unsigned n_static_prefixes; unsigned n_static_route_prefixes; From c16b58217ade02704fbcdb4aebbcef393c70becd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 05:15:32 +0900 Subject: [PATCH 059/138] network: rename ipv6_proxy_ndp_addresses_configure() -> link_set_ipv6_proxy_ndp_addresses() --- src/network/networkd-ipv6-proxy-ndp.c | 2 +- src/network/networkd-ipv6-proxy-ndp.h | 2 +- src/network/networkd-link.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index fc429d25b2..6aacadfedf 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -92,7 +92,7 @@ static int ipv6_proxy_ndp_set(Link *link) { } /* configure all ipv6 proxy ndp addresses */ -int ipv6_proxy_ndp_addresses_configure(Link *link) { +int link_set_ipv6_proxy_ndp_addresses(Link *link) { struct in6_addr *address; int r; diff --git a/src/network/networkd-ipv6-proxy-ndp.h b/src/network/networkd-ipv6-proxy-ndp.h index c7590001ff..e58b17ec94 100644 --- a/src/network/networkd-ipv6-proxy-ndp.h +++ b/src/network/networkd-ipv6-proxy-ndp.h @@ -5,6 +5,6 @@ typedef struct Link Link; -int ipv6_proxy_ndp_addresses_configure(Link *link); +int link_set_ipv6_proxy_ndp_addresses(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 36f627c48c..b161f1801e 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2896,7 +2896,7 @@ static int link_configure(Link *link) { if (r < 0) return r; - r = ipv6_proxy_ndp_addresses_configure(link); + r = link_set_ipv6_proxy_ndp_addresses(link); if (r < 0) return r; From 5823a48993188e0308a7274d794ff6f893c5e1d8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 05:16:25 +0900 Subject: [PATCH 060/138] network: drop networkd-ipv6-proxy-ndp.h from networkd-network.h --- src/network/networkd-ipv6-proxy-ndp.c | 2 -- src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.h | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index 6aacadfedf..f0870becac 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -2,9 +2,7 @@ #include #include -#include -#include "fileio.h" #include "netlink-util.h" #include "networkd-ipv6-proxy-ndp.h" #include "networkd-link.h" diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 51a1533554..6a774001b8 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -15,6 +15,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "networkd-dhcp6.h" #include "networkd-fdb.h" #include "networkd-ipv4ll.h" +#include "networkd-ipv6-proxy-ndp.h" #include "networkd-mdb.h" #include "networkd-ndisc.h" #include "networkd-network.h" diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index e22c60e9ea..bdfef34bad 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -18,7 +18,6 @@ #include "networkd-dhcp4.h" #include "networkd-dhcp6.h" #include "networkd-dhcp-server.h" -#include "networkd-ipv6-proxy-ndp.h" #include "networkd-lldp-rx.h" #include "networkd-lldp-tx.h" #include "networkd-ndisc.h" From fd773a11d8e2b01e9e6d234ca5693417c0101fca Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 05:24:03 +0900 Subject: [PATCH 061/138] network: propagate errors in ipv6_proxy_ndp_set() And ignore IPv6ProxyNDPAddress= settings if proxy_ndp is zero. --- src/network/networkd-ipv6-proxy-ndp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index f0870becac..fb8464ff2f 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -84,9 +84,9 @@ static int ipv6_proxy_ndp_set(Link *link) { r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v); if (r < 0) - log_link_warning_errno(link, r, "Cannot configure proxy NDP for interface: %m"); + return log_link_warning_errno(link, r, "Cannot configure proxy NDP for the interface: %m"); - return 0; + return v; } /* configure all ipv6 proxy ndp addresses */ @@ -99,7 +99,7 @@ int link_set_ipv6_proxy_ndp_addresses(Link *link) { /* enable or disable proxy_ndp itself depending on whether ipv6_proxy_ndp_addresses are set or not */ r = ipv6_proxy_ndp_set(link); - if (r < 0) + if (r <= 0) return r; SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) { From 87851e0feb7e8f164487cb3c8c770583b52a8c57 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 05:29:42 +0900 Subject: [PATCH 062/138] network: warn if IPv6ProxyNDPAddress= is set and IPv6ProxyNDP= is disabled --- src/network/networkd-network.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index a8021f863f..4d094b107c 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -290,6 +290,11 @@ int network_verify(Network *network) { if (network->keep_configuration < 0) network->keep_configuration = KEEP_CONFIGURATION_NO; + if (network->ipv6_proxy_ndp == 0 && !set_isempty(network->ipv6_proxy_ndp_addresses)) { + log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network->filename); + network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses); + } + LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses) if (address_section_verify(address) < 0) address_free(address); From 064dfb05f0c69800e731d1d2e8acbf09cac36136 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 05:40:14 +0900 Subject: [PATCH 063/138] network: make prefix_free() and route_prefix_free() return NULL --- src/network/networkd-radv.c | 46 ++++++++++++++++++++----------------- src/network/networkd-radv.h | 9 ++------ 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 003a50b68b..3382fa1f5a 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -16,9 +16,9 @@ #include "string-table.h" #include "strv.h" -void prefix_free(Prefix *prefix) { +Prefix *prefix_free(Prefix *prefix) { if (!prefix) - return; + return NULL; if (prefix->network) { LIST_REMOVE(prefixes, prefix->network->static_prefixes, prefix); @@ -33,9 +33,11 @@ void prefix_free(Prefix *prefix) { network_config_section_free(prefix->section); sd_radv_prefix_unref(prefix->radv_prefix); - free(prefix); + return mfree(prefix); } +DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free); + static int prefix_new(Prefix **ret) { _cleanup_(prefix_freep) Prefix *prefix = NULL; @@ -101,24 +103,9 @@ static int prefix_new_static(Network *network, const char *filename, return 0; } -static int route_prefix_new(RoutePrefix **ret) { - _cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL; - - prefix = new0(RoutePrefix, 1); +RoutePrefix *route_prefix_free(RoutePrefix *prefix) { if (!prefix) - return -ENOMEM; - - if (sd_radv_route_prefix_new(&prefix->radv_route_prefix) < 0) - return -ENOMEM; - - *ret = TAKE_PTR(prefix); - - return 0; -} - -void route_prefix_free(RoutePrefix *prefix) { - if (!prefix) - return; + return NULL; if (prefix->network) { LIST_REMOVE(route_prefixes, prefix->network->static_route_prefixes, prefix); @@ -133,7 +120,24 @@ void route_prefix_free(RoutePrefix *prefix) { network_config_section_free(prefix->section); sd_radv_route_prefix_unref(prefix->radv_route_prefix); - free(prefix); + return mfree(prefix); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free); + +static int route_prefix_new(RoutePrefix **ret) { + _cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL; + + prefix = new0(RoutePrefix, 1); + if (!prefix) + return -ENOMEM; + + if (sd_radv_route_prefix_new(&prefix->radv_route_prefix) < 0) + return -ENOMEM; + + *ret = TAKE_PTR(prefix); + + return 0; } static int route_prefix_new_static(Network *network, const char *filename, diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 496ef97adc..7addf45e94 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -42,13 +42,8 @@ struct RoutePrefix { LIST_FIELDS(RoutePrefix, route_prefixes); }; -void prefix_free(Prefix *prefix); - -DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free); - -void route_prefix_free(RoutePrefix *prefix); - -DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free); +Prefix *prefix_free(Prefix *prefix); +RoutePrefix *route_prefix_free(RoutePrefix *prefix); int radv_emit_dns(Link *link); int radv_configure(Link *link); From ecb0e85ea97414d77184c2376a5d339a94cedc32 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 05:54:19 +0900 Subject: [PATCH 064/138] network: drop redundant list of prefixes and route prefixes --- src/network/networkd-link.c | 8 ++- src/network/networkd-network.c | 22 +++---- src/network/networkd-network.h | 4 -- src/network/networkd-radv.c | 109 +++++++++++++-------------------- src/network/networkd-radv.h | 4 -- 5 files changed, 53 insertions(+), 94 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index b161f1801e..5c29af2c2d 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1239,7 +1239,6 @@ static int static_address_configure(Address *address, Link *link, bool update) { static int link_request_set_addresses(Link *link) { Address *ad; - Prefix *p; int r; assert(link); @@ -1286,8 +1285,10 @@ static int link_request_set_addresses(Link *link) { return r; } - if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) - LIST_FOREACH(prefixes, p, link->network->static_prefixes) { + if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) { + Prefix *p; + + HASHMAP_FOREACH(p, link->network->prefixes_by_section) { _cleanup_(address_freep) Address *address = NULL; if (!p->assign) @@ -1310,6 +1311,7 @@ static int link_request_set_addresses(Link *link) { if (r < 0) return r; } + } r = link_set_address_labels(link); if (r < 0) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 4d094b107c..348be6ad0b 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -154,9 +154,9 @@ static int network_resolve_stacked_netdevs(Network *network) { } int network_verify(Network *network) { - RoutePrefix *route_prefix, *route_prefix_next; + RoutePrefix *route_prefix; Address *address, *address_next; - Prefix *prefix, *prefix_next; + Prefix *prefix; Route *route, *route_next; TrafficControl *tc; SRIOV *sr_iov; @@ -309,11 +309,11 @@ int network_verify(Network *network) { network_verify_neighbors(network); network_verify_address_labels(network); - LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes) + HASHMAP_FOREACH(prefix, network->prefixes_by_section) if (section_is_invalid(prefix->section)) prefix_free(prefix); - LIST_FOREACH_SAFE(route_prefixes, route_prefix, route_prefix_next, network->static_route_prefixes) + HASHMAP_FOREACH(route_prefix, network->route_prefixes_by_section) if (section_is_invalid(route_prefix->section)) route_prefix_free(route_prefix); @@ -633,9 +633,7 @@ failure: } static Network *network_free(Network *network) { - RoutePrefix *route_prefix; Address *address; - Prefix *prefix; Route *route; if (!network) @@ -699,12 +697,6 @@ static Network *network_free(Network *network) { while ((address = network->static_addresses)) address_free(address); - while ((prefix = network->static_prefixes)) - prefix_free(prefix); - - while ((route_prefix = network->static_route_prefixes)) - route_prefix_free(route_prefix); - set_free_free(network->ipv6_proxy_ndp_addresses); hashmap_free(network->addresses_by_section); hashmap_free(network->routes_by_section); @@ -713,8 +705,8 @@ static Network *network_free(Network *network) { hashmap_free_with_destructor(network->mdb_entries_by_section, mdb_entry_free); hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free); hashmap_free_with_destructor(network->address_labels_by_section, address_label_free); - hashmap_free(network->prefixes_by_section); - hashmap_free(network->route_prefixes_by_section); + hashmap_free_with_destructor(network->prefixes_by_section, prefix_free); + hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free); hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free); ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free); ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free); @@ -851,7 +843,7 @@ bool network_has_static_ipv6_configurations(Network *network) { if (!hashmap_isempty(network->address_labels_by_section)) return true; - if (!LIST_IS_EMPTY(network->static_prefixes)) + if (!hashmap_isempty(network->prefixes_by_section)) return true; return false; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index bdfef34bad..b7a93fb942 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -281,13 +281,9 @@ struct Network { LIST_HEAD(Address, static_addresses); LIST_HEAD(Route, static_routes); - LIST_HEAD(Prefix, static_prefixes); - LIST_HEAD(RoutePrefix, static_route_prefixes); unsigned n_static_addresses; unsigned n_static_routes; - unsigned n_static_prefixes; - unsigned n_static_route_prefixes; Hashmap *addresses_by_section; Hashmap *routes_by_section; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 3382fa1f5a..f5e1926afb 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -21,13 +21,8 @@ Prefix *prefix_free(Prefix *prefix) { return NULL; if (prefix->network) { - LIST_REMOVE(prefixes, prefix->network->static_prefixes, prefix); - assert(prefix->network->n_static_prefixes > 0); - prefix->network->n_static_prefixes--; - - if (prefix->section) - hashmap_remove(prefix->network->prefixes_by_section, - prefix->section); + assert(prefix->section); + hashmap_remove(prefix->network->prefixes_by_section, prefix->section); } network_config_section_free(prefix->section); @@ -61,21 +56,17 @@ static int prefix_new_static(Network *network, const char *filename, assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; - if (section_line) { - prefix = hashmap_get(network->prefixes_by_section, n); - if (prefix) { - *ret = TAKE_PTR(prefix); - - return 0; - } - } + prefix = hashmap_get(network->prefixes_by_section, n); + if (prefix) { + *ret = TAKE_PTR(prefix); + return 0; } r = prefix_new(&prefix); @@ -83,20 +74,15 @@ static int prefix_new_static(Network *network, const char *filename, return r; prefix->network = network; - LIST_APPEND(prefixes, network->static_prefixes, prefix); - network->n_static_prefixes++; + prefix->section = TAKE_PTR(n); - if (filename) { - prefix->section = TAKE_PTR(n); + r = hashmap_ensure_allocated(&network->prefixes_by_section, &network_config_hash_ops); + if (r < 0) + return r; - r = hashmap_ensure_allocated(&network->prefixes_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->prefixes_by_section, prefix->section, prefix); - if (r < 0) - return r; - } + r = hashmap_put(network->prefixes_by_section, prefix->section, prefix); + if (r < 0) + return r; *ret = TAKE_PTR(prefix); @@ -108,13 +94,8 @@ RoutePrefix *route_prefix_free(RoutePrefix *prefix) { return NULL; if (prefix->network) { - LIST_REMOVE(route_prefixes, prefix->network->static_route_prefixes, prefix); - assert(prefix->network->n_static_route_prefixes > 0); - prefix->network->n_static_route_prefixes--; - - if (prefix->section) - hashmap_remove(prefix->network->route_prefixes_by_section, - prefix->section); + assert(prefix->section); + hashmap_remove(prefix->network->route_prefixes_by_section, prefix->section); } network_config_section_free(prefix->section); @@ -148,21 +129,17 @@ static int route_prefix_new_static(Network *network, const char *filename, assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; - if (section_line) { - prefix = hashmap_get(network->route_prefixes_by_section, n); - if (prefix) { - *ret = TAKE_PTR(prefix); - - return 0; - } - } + prefix = hashmap_get(network->route_prefixes_by_section, n); + if (prefix) { + *ret = TAKE_PTR(prefix); + return 0; } r = route_prefix_new(&prefix); @@ -170,20 +147,15 @@ static int route_prefix_new_static(Network *network, const char *filename, return r; prefix->network = network; - LIST_APPEND(route_prefixes, network->static_route_prefixes, prefix); - network->n_static_route_prefixes++; + prefix->section = TAKE_PTR(n); - if (filename) { - prefix->section = TAKE_PTR(n); + r = hashmap_ensure_allocated(&network->route_prefixes_by_section, &network_config_hash_ops); + if (r < 0) + return r; - r = hashmap_ensure_allocated(&network->route_prefixes_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->route_prefixes_by_section, prefix->section, prefix); - if (r < 0) - return r; - } + r = hashmap_put(network->route_prefixes_by_section, prefix->section, prefix); + if (r < 0) + return r; *ret = TAKE_PTR(prefix); @@ -609,8 +581,6 @@ int radv_emit_dns(Link *link) { } int radv_configure(Link *link) { - RoutePrefix *q; - Prefix *p; int r; assert(link); @@ -655,7 +625,10 @@ int radv_configure(Link *link) { } if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) { - LIST_FOREACH(prefixes, p, link->network->static_prefixes) { + RoutePrefix *q; + Prefix *p; + + HASHMAP_FOREACH(p, link->network->prefixes_by_section) { r = sd_radv_add_prefix(link->radv, p->radv_prefix, false); if (r == -EEXIST) continue; @@ -667,7 +640,7 @@ int radv_configure(Link *link) { return r; } - LIST_FOREACH(route_prefixes, q, link->network->static_route_prefixes) { + HASHMAP_FOREACH(q, link->network->route_prefixes_by_section) { r = sd_radv_add_route_prefix(link->radv, q->radv_route_prefix, false); if (r == -EEXIST) continue; diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 7addf45e94..6fe1c947ba 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -29,8 +29,6 @@ struct Prefix { sd_radv_prefix *radv_prefix; bool assign; - - LIST_FIELDS(Prefix, prefixes); }; struct RoutePrefix { @@ -38,8 +36,6 @@ struct RoutePrefix { NetworkConfigSection *section; sd_radv_route_prefix *radv_route_prefix; - - LIST_FIELDS(RoutePrefix, route_prefixes); }; Prefix *prefix_free(Prefix *prefix); From d30081c24e1a496327f2f3d76eac0b5cf3766a4d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 05:56:05 +0900 Subject: [PATCH 065/138] network: also check route prefixes are configured --- src/network/networkd-network.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 348be6ad0b..a89a8259a2 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -846,6 +846,9 @@ bool network_has_static_ipv6_configurations(Network *network) { if (!hashmap_isempty(network->prefixes_by_section)) return true; + if (!hashmap_isempty(network->route_prefixes_by_section)) + return true; + return false; } From 1a7deb2fcfe5641354770c00d266bd20e3e96d31 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 06:01:09 +0900 Subject: [PATCH 066/138] network: introduce network_verify_prefix() and network_verify_route_prefix() --- src/network/networkd-network.c | 13 ++----------- src/network/networkd-radv.c | 20 ++++++++++++++++++++ src/network/networkd-radv.h | 3 +++ 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index a89a8259a2..f77d1bae89 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -154,9 +154,7 @@ static int network_resolve_stacked_netdevs(Network *network) { } int network_verify(Network *network) { - RoutePrefix *route_prefix; Address *address, *address_next; - Prefix *prefix; Route *route, *route_next; TrafficControl *tc; SRIOV *sr_iov; @@ -308,15 +306,8 @@ int network_verify(Network *network) { network_verify_mdb_entries(network); network_verify_neighbors(network); network_verify_address_labels(network); - - HASHMAP_FOREACH(prefix, network->prefixes_by_section) - if (section_is_invalid(prefix->section)) - prefix_free(prefix); - - HASHMAP_FOREACH(route_prefix, network->route_prefixes_by_section) - if (section_is_invalid(route_prefix->section)) - route_prefix_free(route_prefix); - + network_verify_prefixes(network); + network_verify_route_prefixes(network); network_verify_routing_policy_rules(network); bool has_root = false, has_clsact = false; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index f5e1926afb..9762b3a5e7 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -162,6 +162,26 @@ static int route_prefix_new_static(Network *network, const char *filename, return 0; } +void network_verify_prefixes(Network *network) { + Prefix *prefix; + + assert(network); + + HASHMAP_FOREACH(prefix, network->prefixes_by_section) + if (section_is_invalid(prefix->section)) + prefix_free(prefix); +} + +void network_verify_route_prefixes(Network *network) { + RoutePrefix *prefix; + + assert(network); + + HASHMAP_FOREACH(prefix, network->route_prefixes_by_section) + if (section_is_invalid(prefix->section)) + route_prefix_free(prefix); +} + int config_parse_prefix(const char *unit, const char *filename, unsigned line, diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 6fe1c947ba..d549be5f8e 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -41,6 +41,9 @@ struct RoutePrefix { Prefix *prefix_free(Prefix *prefix); RoutePrefix *route_prefix_free(RoutePrefix *prefix); +void network_verify_prefixes(Network *network); +void network_verify_route_prefixes(Network *network); + int radv_emit_dns(Link *link); int radv_configure(Link *link); int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, From b5ce40472c88629006f868b0e9368ce206db1af7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 06:10:02 +0900 Subject: [PATCH 067/138] network: cleanup networkd-radv.h --- src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-radv.c | 4 ++-- src/network/networkd-radv.h | 20 ++++++++++++-------- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 6a774001b8..3b5056e105 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -21,6 +21,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "networkd-network.h" #include "networkd-neighbor.h" #include "networkd-nexthop.h" +#include "networkd-radv.h" #include "networkd-routing-policy-rule.h" #include "networkd-sriov.h" #include "qdisc.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index f77d1bae89..b9b3ed24d2 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -21,6 +21,7 @@ #include "networkd-neighbor.h" #include "networkd-network.h" #include "networkd-nexthop.h" +#include "networkd-radv.h" #include "networkd-routing-policy-rule.h" #include "networkd-sriov.h" #include "parse-util.h" diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 9762b3a5e7..9b6a83cb66 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -7,11 +7,11 @@ #include #include "dns-domain.h" -#include "networkd-address.h" +#include "networkd-link.h" #include "networkd-manager.h" +#include "networkd-network.h" #include "networkd-radv.h" #include "parse-util.h" -#include "sd-radv.h" #include "string-util.h" #include "string-table.h" #include "strv.h" diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index d549be5f8e..af554aeef7 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -5,13 +5,17 @@ Copyright © 2017 Intel Corporation. All rights reserved. ***/ +#include +#include + +#include "sd-radv.h" + +#include "in-addr-util.h" #include "conf-parser.h" -#include "networkd-address.h" -#include "networkd-link.h" #include "networkd-util.h" -typedef struct Prefix Prefix; -typedef struct RoutePrefix RoutePrefix; +typedef struct Network Network; +typedef struct Link Link; typedef enum RADVPrefixDelegation { RADV_PREFIX_DELEGATION_NONE = 0, @@ -22,21 +26,21 @@ typedef enum RADVPrefixDelegation { _RADV_PREFIX_DELEGATION_INVALID = -1, } RADVPrefixDelegation; -struct Prefix { +typedef struct Prefix { Network *network; NetworkConfigSection *section; sd_radv_prefix *radv_prefix; bool assign; -}; +} Prefix; -struct RoutePrefix { +typedef struct RoutePrefix { Network *network; NetworkConfigSection *section; sd_radv_route_prefix *radv_route_prefix; -}; +} RoutePrefix; Prefix *prefix_free(Prefix *prefix); RoutePrefix *route_prefix_free(RoutePrefix *prefix); From a8d4a2109118d06bb0550f1fc6fdf8482fece36c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 06:17:04 +0900 Subject: [PATCH 068/138] network: fix indentation --- src/network/networkd-radv.c | 163 +++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 75 deletions(-) diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 9b6a83cb66..cb6051b657 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -48,8 +48,7 @@ static int prefix_new(Prefix **ret) { return 0; } -static int prefix_new_static(Network *network, const char *filename, - unsigned section_line, Prefix **ret) { +static int prefix_new_static(Network *network, const char *filename, unsigned section_line, Prefix **ret) { _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; _cleanup_(prefix_freep) Prefix *prefix = NULL; int r; @@ -121,8 +120,7 @@ static int route_prefix_new(RoutePrefix **ret) { return 0; } -static int route_prefix_new_static(Network *network, const char *filename, - unsigned section_line, RoutePrefix **ret) { +static int route_prefix_new_static(Network *network, const char *filename, unsigned section_line, RoutePrefix **ret) { _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; _cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL; int r; @@ -182,16 +180,17 @@ void network_verify_route_prefixes(Network *network) { route_prefix_free(prefix); } -int config_parse_prefix(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) { +int config_parse_prefix( + 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) { Network *network = userdata; _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; @@ -226,16 +225,18 @@ int config_parse_prefix(const char *unit, return 0; } -int config_parse_prefix_flags(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) { +int config_parse_prefix_flags( + 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) { + Network *network = userdata; _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; int r; @@ -270,16 +271,18 @@ int config_parse_prefix_flags(const char *unit, return 0; } -int config_parse_prefix_lifetime(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) { +int config_parse_prefix_lifetime( + 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) { + Network *network = userdata; _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; usec_t usec; @@ -358,16 +361,17 @@ int config_parse_prefix_assign( return 0; } -int config_parse_route_prefix(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) { +int config_parse_route_prefix( + 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) { Network *network = userdata; _cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL; @@ -402,16 +406,18 @@ int config_parse_route_prefix(const char *unit, return 0; } -int config_parse_route_prefix_lifetime(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) { +int config_parse_route_prefix_lifetime( + 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) { + Network *network = userdata; _cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL; usec_t usec; @@ -447,8 +453,7 @@ int config_parse_route_prefix_lifetime(const char *unit, return 0; } -static int radv_get_ip6dns(Network *network, struct in6_addr **dns, - size_t *n_dns) { +static int radv_get_ip6dns(Network *network, struct in6_addr **dns, size_t *n_dns) { _cleanup_free_ struct in6_addr *addresses = NULL; size_t i, n_addresses = 0, n_allocated = 0; @@ -672,8 +677,13 @@ int radv_configure(Link *link) { return 0; } -int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, - uint32_t lifetime_preferred, uint32_t lifetime_valid) { +int radv_add_prefix( + Link *link, + const struct in6_addr *prefix, + uint8_t prefix_len, + uint32_t lifetime_preferred, + uint32_t lifetime_valid) { + _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL; int r; @@ -819,10 +829,10 @@ int config_parse_radv_search_domains( } static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = { - [RADV_PREFIX_DELEGATION_NONE] = "no", + [RADV_PREFIX_DELEGATION_NONE] = "no", [RADV_PREFIX_DELEGATION_STATIC] = "static", - [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6", - [RADV_PREFIX_DELEGATION_BOTH] = "yes", + [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6", + [RADV_PREFIX_DELEGATION_BOTH] = "yes", }; DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN( @@ -830,21 +840,24 @@ DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN( RADVPrefixDelegation, RADV_PREFIX_DELEGATION_BOTH); -DEFINE_CONFIG_PARSE_ENUM(config_parse_router_prefix_delegation, - radv_prefix_delegation, - RADVPrefixDelegation, - "Invalid router prefix delegation"); +DEFINE_CONFIG_PARSE_ENUM( + config_parse_router_prefix_delegation, + radv_prefix_delegation, + RADVPrefixDelegation, + "Invalid router prefix delegation"); + +int config_parse_router_preference( + 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) { -int config_parse_router_preference(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) { Network *network = userdata; assert(filename); From be023c670b84dde9cb758cf01173bb9330b22078 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 30 Sep 2020 06:28:44 +0900 Subject: [PATCH 069/138] network: make network_get_ipv6_dns() always set return value on success --- src/network/networkd-radv.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index cb6051b657..04bbb8a62b 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -453,15 +453,15 @@ int config_parse_route_prefix_lifetime( return 0; } -static int radv_get_ip6dns(Network *network, struct in6_addr **dns, size_t *n_dns) { +static int network_get_ipv6_dns(Network *network, struct in6_addr **ret_addresses, size_t *ret_size) { _cleanup_free_ struct in6_addr *addresses = NULL; - size_t i, n_addresses = 0, n_allocated = 0; + size_t n_addresses = 0, n_allocated = 0; assert(network); - assert(dns); - assert(n_dns); + assert(ret_addresses); + assert(ret_size); - for (i = 0; i < network->n_dns; i++) { + for (size_t i = 0; i < network->n_dns; i++) { union in_addr_union *addr; if (network->dns[i]->family != AF_INET6) @@ -480,11 +480,8 @@ static int radv_get_ip6dns(Network *network, struct in6_addr **dns, size_t *n_dn addresses[n_addresses++] = addr->in6; } - if (addresses) { - *dns = TAKE_PTR(addresses); - - *n_dns = n_addresses; - } + *ret_addresses = TAKE_PTR(addresses); + *ret_size = n_addresses; return n_addresses; } @@ -521,7 +518,7 @@ static int radv_set_dns(Link *link, Link *uplink) { lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC; - r = radv_get_ip6dns(link->network, &dns, &n_dns); + r = network_get_ipv6_dns(link->network, &dns, &n_dns); if (r > 0) goto set_dns; @@ -531,7 +528,7 @@ static int radv_set_dns(Link *link, Link *uplink) { return 0; } - r = radv_get_ip6dns(uplink->network, &dns, &n_dns); + r = network_get_ipv6_dns(uplink->network, &dns, &n_dns); if (r > 0) goto set_dns; } From 141318f777b7a1568debe01b7d566612180d7535 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 09:27:28 +0900 Subject: [PATCH 070/138] network: move link_request_set_routes() --- src/network/networkd-dhcp4.c | 8 ++-- src/network/networkd-dhcp6.c | 16 +++---- src/network/networkd-link.c | 87 +----------------------------------- src/network/networkd-link.h | 1 - src/network/networkd-ndisc.c | 8 ++-- src/network/networkd-route.c | 85 +++++++++++++++++++++++++++++++++++ src/network/networkd-route.h | 2 + 7 files changed, 105 insertions(+), 102 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index eddeb0d5ef..8dd89c22a2 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -698,7 +698,7 @@ static int dhcp4_address_ready_callback(Address *address) { return r; /* Reconfigure static routes as kernel may remove some routes when lease expires. */ - r = link_request_set_routes(link); + r = link_set_routes(link); if (r < 0) return r; @@ -755,9 +755,9 @@ static int dhcp4_update_address(Link *link, bool announce) { link_set_state(link, LINK_STATE_CONFIGURING); link->dhcp4_configured = false; - /* address_handler calls link_request_set_routes() and link_request_set_nexthop(). Before they - * are called, the related flags must be cleared. Otherwise, the link becomes configured state - * before routes are configured. */ + /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are called, the + * related flags must be cleared. Otherwise, the link becomes configured state before routes + * are configured. */ link->static_routes_configured = false; link->static_nexthops_configured = false; diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 7996e825c2..f0642c9f72 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -342,7 +342,7 @@ static int dhcp6_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin return 1; } - r = link_request_set_routes(link); + r = link_set_routes(link); if (r < 0) { link_enter_failed(link); return 1; @@ -607,9 +607,9 @@ static int dhcp6_pd_finalize(Link *link) { link->dhcp6_pd_address_configured = true; } else { log_link_debug(link, "Setting DHCPv6 PD addresses"); - /* address_handler calls link_request_set_routes() and link_request_set_nexthop(). - * Before they are called, the related flags must be cleared. Otherwise, the link - * becomes configured state before routes are configured. */ + /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are + * called, the related flags must be cleared. Otherwise, the link becomes configured + * state before routes are configured. */ link->static_routes_configured = false; link->static_nexthops_configured = false; } @@ -952,7 +952,7 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * return 1; } - r = link_request_set_routes(link); + r = link_set_routes(link); if (r < 0) { link_enter_failed(link); return 1; @@ -1075,9 +1075,9 @@ static int dhcp6_lease_ip_acquired(sd_dhcp6_client *client, Link *link) { link->dhcp6_address_configured = true; else { log_link_debug(link, "Setting DHCPv6 addresses"); - /* address_handler calls link_request_set_routes() and link_request_set_nexthop(). - * Before they are called, the related flags must be cleared. Otherwise, the link - * becomes configured state before routes are configured. */ + /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are + * called, the related flags must be cleared. Otherwise, the link becomes configured + * state before routes are configured. */ link->static_routes_configured = false; link->static_nexthops_configured = false; } diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 5c29af2c2d..0722bc2f66 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -929,89 +929,6 @@ static void link_enter_configured(Link *link) { link_dirty(link); } -static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(link); - assert(link->route_messages > 0); - assert(IN_SET(link->state, LINK_STATE_CONFIGURING, - LINK_STATE_FAILED, LINK_STATE_LINGER)); - - link->route_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_message_warning_errno(link, m, r, "Could not set route"); - link_enter_failed(link); - return 1; - } - - if (link->route_messages == 0) { - log_link_debug(link, "Routes set"); - link->static_routes_configured = true; - link_set_nexthop(link); - } - - return 1; -} - -int link_request_set_routes(Link *link) { - enum { - PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */ - PHASE_GATEWAY, /* Second phase: Routes with a gateway */ - _PHASE_MAX - } phase; - Route *rt; - int r; - - assert(link); - assert(link->network); - assert(link->state != _LINK_STATE_INVALID); - - link->static_routes_configured = false; - - if (!link->addresses_ready) - return 0; - - if (!link_has_carrier(link) && !link->network->configure_without_carrier) - /* During configuring addresses, the link lost its carrier. As networkd is dropping - * the addresses now, let's not configure the routes either. */ - return 0; - - r = link_set_routing_policy_rules(link); - if (r < 0) - return r; - - /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */ - for (phase = 0; phase < _PHASE_MAX; phase++) - LIST_FOREACH(routes, rt, link->network->static_routes) { - if (rt->gateway_from_dhcp) - continue; - - if ((in_addr_is_null(rt->family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY)) - continue; - - r = route_configure(rt, link, route_handler, NULL); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set routes: %m"); - if (r > 0) - link->route_messages++; - } - - if (link->route_messages == 0) { - link->static_routes_configured = true; - link_set_nexthop(link); - } else { - log_link_debug(link, "Setting routes"); - link_set_state(link, LINK_STATE_CONFIGURING); - } - - return 0; -} - void link_check_ready(Link *link) { Address *a; @@ -1161,7 +1078,7 @@ static int static_address_ready_callback(Address *address) { link->addresses_ready = true; - return link_request_set_routes(link); + return link_set_routes(link); } static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { @@ -1328,7 +1245,7 @@ static int link_request_set_addresses(Link *link) { if (link->address_messages == 0) { link->addresses_configured = true; link->addresses_ready = true; - r = link_request_set_routes(link); + r = link_set_routes(link); if (r < 0) return r; } else { diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 1550db8a23..aadbddc910 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -240,7 +240,6 @@ LinkState link_state_from_string(const char *s) _pure_; uint32_t link_get_vrf_table(Link *link); uint32_t link_get_dhcp_route_table(Link *link); uint32_t link_get_ipv6_accept_ra_route_table(Link *link); -int link_request_set_routes(Link *link); int link_reconfigure(Link *link, bool force); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 68a66649f0..64b27276e0 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -368,7 +368,7 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * return 1; } - r = link_request_set_routes(link); + r = link_set_routes(link); if (r < 0) { link_enter_failed(link); return 1; @@ -1133,9 +1133,9 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { else { log_link_debug(link, "Setting SLAAC addresses."); - /* address_handler calls link_request_set_routes() and link_request_set_nexthop(). - * Before they are called, the related flags must be cleared. Otherwise, the link - * becomes configured state before routes are configured. */ + /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are + * called, the related flags must be cleared. Otherwise, the link becomes configured + * state before routes are configured. */ link->static_routes_configured = false; link->static_nexthops_configured = false; } diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 2610b24c82..f4b794f5c3 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -10,7 +10,9 @@ #include "networkd-ipv4ll.h" #include "networkd-manager.h" #include "networkd-ndisc.h" +#include "networkd-nexthop.h" #include "networkd-route.h" +#include "networkd-routing-policy-rule.h" #include "parse-util.h" #include "set.h" #include "socket-netlink.h" @@ -821,6 +823,89 @@ int route_configure( return 1; } +static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->route_messages > 0); + assert(IN_SET(link->state, LINK_STATE_CONFIGURING, + LINK_STATE_FAILED, LINK_STATE_LINGER)); + + link->route_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_message_warning_errno(link, m, r, "Could not set route"); + link_enter_failed(link); + return 1; + } + + if (link->route_messages == 0) { + log_link_debug(link, "Routes set"); + link->static_routes_configured = true; + link_set_nexthop(link); + } + + return 1; +} + +int link_set_routes(Link *link) { + enum { + PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */ + PHASE_GATEWAY, /* Second phase: Routes with a gateway */ + _PHASE_MAX + } phase; + Route *rt; + int r; + + assert(link); + assert(link->network); + assert(link->state != _LINK_STATE_INVALID); + + link->static_routes_configured = false; + + if (!link->addresses_ready) + return 0; + + if (!link_has_carrier(link) && !link->network->configure_without_carrier) + /* During configuring addresses, the link lost its carrier. As networkd is dropping + * the addresses now, let's not configure the routes either. */ + return 0; + + r = link_set_routing_policy_rules(link); + if (r < 0) + return r; + + /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */ + for (phase = 0; phase < _PHASE_MAX; phase++) + LIST_FOREACH(routes, rt, link->network->static_routes) { + if (rt->gateway_from_dhcp) + continue; + + if ((in_addr_is_null(rt->family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY)) + continue; + + r = route_configure(rt, link, route_handler, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set routes: %m"); + if (r > 0) + link->route_messages++; + } + + if (link->route_messages == 0) { + link->static_routes_configured = true; + link_set_nexthop(link); + } else { + log_link_debug(link, "Setting routes"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + int network_add_ipv4ll_route(Network *network) { _cleanup_(route_free_or_set_invalidp) Route *n = NULL; int r; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 75651fa512..9b13391904 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -71,6 +71,8 @@ void route_free(Route *route); int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback, Route **ret); int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback); +int link_set_routes(Link *link); + int route_get(Link *link, Route *in, Route **ret); int route_add(Link *link, Route *in, Route **ret); int route_add_foreign(Link *link, Route *in, Route **ret); From 4468f01b674864c6388d5cac62f7085d10f9c2e5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 09:29:07 +0900 Subject: [PATCH 071/138] network: move manager_rtnl_process_route() --- src/network/networkd-manager.c | 254 --------------------------------- src/network/networkd-route.c | 254 +++++++++++++++++++++++++++++++++ src/network/networkd-route.h | 2 + 3 files changed, 256 insertions(+), 254 deletions(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index cd0ad82e2e..5cd925a27c 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -285,260 +285,6 @@ static int manager_connect_udev(Manager *m) { return 0; } -static int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - _cleanup_(route_freep) Route *tmp = NULL; - Route *route = NULL; - Link *link = NULL; - uint32_t ifindex; - uint16_t type; - unsigned char table; - int r; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_message_warning_errno(message, r, "rtnl: failed to receive route message, ignoring"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); - return 0; - } else if (!IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE)) { - log_warning("rtnl: received unexpected message type %u when processing route, ignoring.", type); - return 0; - } - - r = sd_netlink_message_read_u32(message, RTA_OIF, &ifindex); - if (r == -ENODATA) { - log_debug("rtnl: received route message without ifindex, ignoring"); - return 0; - } else if (r < 0) { - log_warning_errno(r, "rtnl: could not get ifindex from route message, ignoring: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received route message with invalid ifindex %d, ignoring.", ifindex); - return 0; - } - - r = link_get(m, ifindex, &link); - if (r < 0 || !link) { - /* when enumerating we might be out of sync, but we will - * get the route again, so just ignore it */ - if (!m->enumerating) - log_warning("rtnl: received route message for link (%d) we do not know about, ignoring", ifindex); - return 0; - } - - r = route_new(&tmp); - if (r < 0) - return log_oom(); - - r = sd_rtnl_message_route_get_family(message, &tmp->family); - if (r < 0) { - log_link_warning(link, "rtnl: received route message without family, ignoring"); - return 0; - } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { - log_link_debug(link, "rtnl: received route message with invalid family '%i', ignoring", tmp->family); - return 0; - } - - r = sd_rtnl_message_route_get_protocol(message, &tmp->protocol); - if (r < 0) { - log_warning_errno(r, "rtnl: received route message without route protocol: %m"); - return 0; - } - - switch (tmp->family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, RTA_DST, &tmp->dst.in); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &tmp->gw.in); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in_addr(message, RTA_SRC, &tmp->src.in); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &tmp->prefsrc.in); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); - return 0; - } - - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, RTA_DST, &tmp->dst.in6); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &tmp->gw.in6); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &tmp->src.in6); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &tmp->prefsrc.in6); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); - return 0; - } - - break; - - default: - assert_not_reached("Received route message with unsupported address family"); - return 0; - } - - r = sd_rtnl_message_route_get_dst_prefixlen(message, &tmp->dst_prefixlen); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_route_get_src_prefixlen(message, &tmp->src_prefixlen); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid source prefixlen, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_route_get_scope(message, &tmp->scope); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid scope, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_route_get_tos(message, &tmp->tos); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid tos, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_route_get_type(message, &tmp->type); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid type, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_route_get_table(message, &table); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m"); - return 0; - } - tmp->table = table; - - r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid priority, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_enter_container(message, RTA_METRICS); - if (r < 0 && r != -ENODATA) { - log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container: %m"); - return 0; - } - if (r >= 0) { - r = sd_netlink_message_read_u32(message, RTAX_INITCWND, &tmp->initcwnd); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid initcwnd, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, RTAX_INITRWND, &tmp->initrwnd); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid initrwnd, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_exit_container(message); - if (r < 0) { - log_link_error_errno(link, r, "rtnl: Could not exit from RTA_METRICS container: %m"); - return 0; - } - } - - (void) route_get(link, tmp, &route); - - if (DEBUG_LOGGING) { - _cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL, - *buf_src = NULL, *buf_gw = NULL, *buf_prefsrc = NULL; - char buf_scope[ROUTE_SCOPE_STR_MAX], buf_table[ROUTE_TABLE_STR_MAX], - buf_protocol[ROUTE_PROTOCOL_STR_MAX]; - - if (!in_addr_is_null(tmp->family, &tmp->dst)) { - (void) in_addr_to_string(tmp->family, &tmp->dst, &buf_dst); - (void) asprintf(&buf_dst_prefixlen, "/%u", tmp->dst_prefixlen); - } - if (!in_addr_is_null(tmp->family, &tmp->src)) - (void) in_addr_to_string(tmp->family, &tmp->src, &buf_src); - if (!in_addr_is_null(tmp->family, &tmp->gw)) - (void) in_addr_to_string(tmp->family, &tmp->gw, &buf_gw); - if (!in_addr_is_null(tmp->family, &tmp->prefsrc)) - (void) in_addr_to_string(tmp->family, &tmp->prefsrc, &buf_prefsrc); - - log_link_debug(link, - "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s", - (!route && !link->manager->manage_foreign_routes) ? "Ignoring received foreign" : - type == RTM_DELROUTE ? "Forgetting" : - route ? "Received remembered" : "Remembering", - strna(buf_dst), strempty(buf_dst_prefixlen), - strna(buf_src), strna(buf_gw), strna(buf_prefsrc), - format_route_scope(tmp->scope, buf_scope, sizeof buf_scope), - format_route_table(tmp->table, buf_table, sizeof buf_table), - format_route_protocol(tmp->protocol, buf_protocol, sizeof buf_protocol), - strna(route_type_to_string(tmp->type))); - } - - switch (type) { - case RTM_NEWROUTE: - if (!route && link->manager->manage_foreign_routes) { - /* A route appeared that we did not request */ - r = route_add_foreign(link, tmp, &route); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m"); - return 0; - } - } - - break; - - case RTM_DELROUTE: - route_free(route); - break; - - default: - assert_not_reached("Received route message with invalid RTNL message type"); - } - - return 1; -} - int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_free_ char *buf = NULL; Link *link = NULL; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index f4b794f5c3..98370a9440 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -906,6 +906,260 @@ int link_set_routes(Link *link) { return 0; } +int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { + _cleanup_(route_freep) Route *tmp = NULL; + Route *route = NULL; + Link *link = NULL; + uint32_t ifindex; + uint16_t type; + unsigned char table; + int r; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_message_warning_errno(message, r, "rtnl: failed to receive route message, ignoring"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE)) { + log_warning("rtnl: received unexpected message type %u when processing route, ignoring.", type); + return 0; + } + + r = sd_netlink_message_read_u32(message, RTA_OIF, &ifindex); + if (r == -ENODATA) { + log_debug("rtnl: received route message without ifindex, ignoring"); + return 0; + } else if (r < 0) { + log_warning_errno(r, "rtnl: could not get ifindex from route message, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received route message with invalid ifindex %d, ignoring.", ifindex); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0 || !link) { + /* when enumerating we might be out of sync, but we will + * get the route again, so just ignore it */ + if (!m->enumerating) + log_warning("rtnl: received route message for link (%d) we do not know about, ignoring", ifindex); + return 0; + } + + r = route_new(&tmp); + if (r < 0) + return log_oom(); + + r = sd_rtnl_message_route_get_family(message, &tmp->family); + if (r < 0) { + log_link_warning(link, "rtnl: received route message without family, ignoring"); + return 0; + } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { + log_link_debug(link, "rtnl: received route message with invalid family '%i', ignoring", tmp->family); + return 0; + } + + r = sd_rtnl_message_route_get_protocol(message, &tmp->protocol); + if (r < 0) { + log_warning_errno(r, "rtnl: received route message without route protocol: %m"); + return 0; + } + + switch (tmp->family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, RTA_DST, &tmp->dst.in); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &tmp->gw.in); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in_addr(message, RTA_SRC, &tmp->src.in); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &tmp->prefsrc.in); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); + return 0; + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, RTA_DST, &tmp->dst.in6); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &tmp->gw.in6); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &tmp->src.in6); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &tmp->prefsrc.in6); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); + return 0; + } + + break; + + default: + assert_not_reached("Received route message with unsupported address family"); + return 0; + } + + r = sd_rtnl_message_route_get_dst_prefixlen(message, &tmp->dst_prefixlen); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_src_prefixlen(message, &tmp->src_prefixlen); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid source prefixlen, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_scope(message, &tmp->scope); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid scope, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_tos(message, &tmp->tos); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid tos, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_type(message, &tmp->type); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid type, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_table(message, &table); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m"); + return 0; + } + tmp->table = table; + + r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid priority, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_enter_container(message, RTA_METRICS); + if (r < 0 && r != -ENODATA) { + log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container: %m"); + return 0; + } + if (r >= 0) { + r = sd_netlink_message_read_u32(message, RTAX_INITCWND, &tmp->initcwnd); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid initcwnd, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, RTAX_INITRWND, &tmp->initrwnd); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid initrwnd, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_exit_container(message); + if (r < 0) { + log_link_error_errno(link, r, "rtnl: Could not exit from RTA_METRICS container: %m"); + return 0; + } + } + + (void) route_get(link, tmp, &route); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL, + *buf_src = NULL, *buf_gw = NULL, *buf_prefsrc = NULL; + char buf_scope[ROUTE_SCOPE_STR_MAX], buf_table[ROUTE_TABLE_STR_MAX], + buf_protocol[ROUTE_PROTOCOL_STR_MAX]; + + if (!in_addr_is_null(tmp->family, &tmp->dst)) { + (void) in_addr_to_string(tmp->family, &tmp->dst, &buf_dst); + (void) asprintf(&buf_dst_prefixlen, "/%u", tmp->dst_prefixlen); + } + if (!in_addr_is_null(tmp->family, &tmp->src)) + (void) in_addr_to_string(tmp->family, &tmp->src, &buf_src); + if (!in_addr_is_null(tmp->family, &tmp->gw)) + (void) in_addr_to_string(tmp->family, &tmp->gw, &buf_gw); + if (!in_addr_is_null(tmp->family, &tmp->prefsrc)) + (void) in_addr_to_string(tmp->family, &tmp->prefsrc, &buf_prefsrc); + + log_link_debug(link, + "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s", + (!route && !link->manager->manage_foreign_routes) ? "Ignoring received foreign" : + type == RTM_DELROUTE ? "Forgetting" : + route ? "Received remembered" : "Remembering", + strna(buf_dst), strempty(buf_dst_prefixlen), + strna(buf_src), strna(buf_gw), strna(buf_prefsrc), + format_route_scope(tmp->scope, buf_scope, sizeof buf_scope), + format_route_table(tmp->table, buf_table, sizeof buf_table), + format_route_protocol(tmp->protocol, buf_protocol, sizeof buf_protocol), + strna(route_type_to_string(tmp->type))); + } + + switch (type) { + case RTM_NEWROUTE: + if (!route && link->manager->manage_foreign_routes) { + /* A route appeared that we did not request */ + r = route_add_foreign(link, tmp, &route); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m"); + return 0; + } + } + + break; + + case RTM_DELROUTE: + route_free(route); + break; + + default: + assert_not_reached("Received route message with invalid RTNL message type"); + } + + return 1; +} + int network_add_ipv4ll_route(Network *network) { _cleanup_(route_free_or_set_invalidp) Route *n = NULL; int r; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 9b13391904..cf637e67c2 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -73,6 +73,8 @@ int route_remove(Route *route, Link *link, link_netlink_message_handler_t callba int link_set_routes(Link *link); +int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); + int route_get(Link *link, Route *in, Route **ret); int route_add(Link *link, Route *in, Route **ret); int route_add_foreign(Link *link, Route *in, Route **ret); From 169948e9d27a91c7c0ea3a42d4ccac3838ef75cd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 09:31:29 +0900 Subject: [PATCH 072/138] network: make route_free() return NULL --- src/network/networkd-route.c | 6 +++--- src/network/networkd-route.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 98370a9440..0236ac3262 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -128,9 +128,9 @@ static int route_new_static(Network *network, const char *filename, unsigned sec return 0; } -void route_free(Route *route) { +Route *route_free(Route *route) { if (!route) - return; + return NULL; if (route->network) { LIST_REMOVE(routes, route->network->static_routes, route); @@ -164,7 +164,7 @@ void route_free(Route *route) { sd_event_source_unref(route->expire); - free(route); + return mfree(route); } void route_hash_func(const Route *route, struct siphash *state) { diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index cf637e67c2..bcd960e35f 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -67,7 +67,7 @@ int route_compare_func(const Route *a, const Route *b); extern const struct hash_ops route_hash_ops; int route_new(Route **ret); -void route_free(Route *route); +Route *route_free(Route *route); int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback, Route **ret); int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback); From 779804dd6059c755c67ad199ef2e308d41344a82 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 09:38:31 +0900 Subject: [PATCH 073/138] network: introduce link_drop_foreign_routes() --- src/network/networkd-link.c | 52 +--------------------------------- src/network/networkd-route.c | 55 ++++++++++++++++++++++++++++++++++++ src/network/networkd-route.h | 1 + 3 files changed, 57 insertions(+), 51 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0722bc2f66..b9053ad659 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2497,22 +2497,6 @@ static bool link_is_static_address_configured(Link *link, Address *address) { return false; } -static bool link_is_static_route_configured(Link *link, Route *route) { - Route *net_route; - - assert(link); - assert(route); - - if (!link->network) - return false; - - LIST_FOREACH(routes, net_route, link->network->static_routes) - if (route_equal(net_route, route)) - return true; - - return false; -} - static bool link_address_is_dynamic(Link *link, Address *address) { Route *route; @@ -2583,7 +2567,6 @@ static int link_enumerate_ipv6_tentative_addresses(Link *link) { static int link_drop_foreign_config(Link *link) { Address *address; - Route *route; int r; /* The kernel doesn't notify us about tentative addresses; @@ -2620,40 +2603,7 @@ static int link_drop_foreign_config(Link *link) { if (r < 0) return r; - SET_FOREACH(route, link->routes_foreign) { - /* do not touch routes managed by the kernel */ - if (route->protocol == RTPROT_KERNEL) - continue; - - /* do not touch multicast route added by kernel */ - /* FIXME: Why the kernel adds this route with protocol RTPROT_BOOT??? We need to investigate that. - * https://tools.ietf.org/html/rfc4862#section-5.4 may explain why. */ - if (route->protocol == RTPROT_BOOT && - route->family == AF_INET6 && - route->dst_prefixlen == 8 && - in_addr_equal(AF_INET6, &route->dst, &(union in_addr_union) { .in6 = {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}} })) - continue; - - if (route->protocol == RTPROT_STATIC && link->network && - FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) - continue; - - if (route->protocol == RTPROT_DHCP && link->network && - FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) - continue; - - if (link_is_static_route_configured(link, route)) { - r = route_add(link, route, NULL); - if (r < 0) - return r; - } else { - r = route_remove(route, link, NULL); - if (r < 0) - return r; - } - } - - return 0; + return link_drop_foreign_routes(link); } static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 0236ac3262..d7ec9097b3 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -511,6 +511,61 @@ int route_remove(Route *route, Link *link, return 0; } +static bool link_is_static_route_configured(Link *link, Route *route) { + Route *net_route; + + assert(link); + assert(route); + + if (!link->network) + return false; + + LIST_FOREACH(routes, net_route, link->network->static_routes) + if (route_equal(net_route, route)) + return true; + + return false; +} + +int link_drop_foreign_routes(Link *link) { + Route *route; + int k, r = 0; + + assert(link); + + SET_FOREACH(route, link->routes_foreign) { + /* do not touch routes managed by the kernel */ + if (route->protocol == RTPROT_KERNEL) + continue; + + /* do not touch multicast route added by kernel */ + /* FIXME: Why the kernel adds this route with protocol RTPROT_BOOT??? We need to investigate that. + * https://tools.ietf.org/html/rfc4862#section-5.4 may explain why. */ + if (route->protocol == RTPROT_BOOT && + route->family == AF_INET6 && + route->dst_prefixlen == 8 && + in_addr_equal(AF_INET6, &route->dst, &(union in_addr_union) { .in6 = {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}} })) + continue; + + if (route->protocol == RTPROT_STATIC && link->network && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + + if (route->protocol == RTPROT_DHCP && link->network && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + + if (link_is_static_route_configured(link, route)) + k = route_add(link, route, NULL); + else + k = route_remove(route, link, NULL); + if (k < 0 && r >= 0) + r = k; + } + + return r; +} + int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { Route *route = userdata; int r; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index bcd960e35f..d362298294 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -72,6 +72,7 @@ int route_configure(Route *route, Link *link, link_netlink_message_handler_t cal int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback); int link_set_routes(Link *link); +int link_drop_foreign_routes(Link *link); int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); From 62f0ea5fae2371795fd7a49daeda7c398f89aea0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 09:40:31 +0900 Subject: [PATCH 074/138] network: introduce link_drop_routes() --- src/network/networkd-link.c | 13 +++---------- src/network/networkd-route.c | 19 +++++++++++++++++++ src/network/networkd-route.h | 1 + 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index b9053ad659..dea1e723c3 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2637,7 +2637,6 @@ static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m static int link_drop_config(Link *link) { Address *address, *pool_address; - Route *route; int r; SET_FOREACH(address, link->addresses) { @@ -2664,15 +2663,9 @@ static int link_drop_config(Link *link) { if (r < 0) return r; - SET_FOREACH(route, link->routes) { - /* do not touch routes managed by the kernel */ - if (route->protocol == RTPROT_KERNEL) - continue; - - r = route_remove(route, link, NULL); - if (r < 0) - return r; - } + r = link_drop_routes(link); + if (r < 0) + return r; ndisc_flush(link); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index d7ec9097b3..87006a6c44 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -566,6 +566,25 @@ int link_drop_foreign_routes(Link *link) { return r; } +int link_drop_routes(Link *link) { + Route *route; + int k, r = 0; + + assert(link); + + SET_FOREACH(route, link->routes) { + /* do not touch routes managed by the kernel */ + if (route->protocol == RTPROT_KERNEL) + continue; + + k = route_remove(route, link, NULL); + if (k < 0 && r >= 0) + r = k; + } + + return r; +} + int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { Route *route = userdata; int r; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index d362298294..d5760a96a6 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -72,6 +72,7 @@ int route_configure(Route *route, Link *link, link_netlink_message_handler_t cal int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback); int link_set_routes(Link *link); +int link_drop_routes(Link *link); int link_drop_foreign_routes(Link *link); int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); From 731ff05b3218aa7dce03bf53ff1be41e56212b5b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 09:52:07 +0900 Subject: [PATCH 075/138] network: introduce link_deserialize_routes() --- src/network/networkd-link.c | 62 ++------------------------------- src/network/networkd-route.c | 66 ++++++++++++++++++++++++++++++++++++ src/network/networkd-route.h | 1 + 3 files changed, 70 insertions(+), 59 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index dea1e723c3..0217300be6 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3391,65 +3391,9 @@ network_file_fail: return log_link_error_errno(link, r, "Failed to add address: %m"); } - for (const char *p = routes; p; ) { - _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; - _cleanup_(route_freep) Route *tmp = NULL; - _cleanup_free_ char *route_str = NULL; - char *prefixlen_str; - Route *route; - - r = extract_first_word(&p, &route_str, NULL, 0); - if (r < 0) - log_link_debug_errno(link, r, "failed to parse ROUTES: %m"); - if (r <= 0) - break; - - prefixlen_str = strchr(route_str, '/'); - if (!prefixlen_str) { - log_link_debug(link, "Failed to parse route %s", route_str); - continue; - } - *prefixlen_str++ = '\0'; - - r = route_new(&tmp); - if (r < 0) - return log_oom(); - - r = sscanf(prefixlen_str, - "%hhu/%hhu/%"SCNu32"/%"PRIu32"/"USEC_FMT, - &tmp->dst_prefixlen, - &tmp->tos, - &tmp->priority, - &tmp->table, - &tmp->lifetime); - if (r != 5) { - log_link_debug(link, - "Failed to parse destination prefix length, tos, priority, table or expiration %s", - prefixlen_str); - continue; - } - - r = in_addr_from_string_auto(route_str, &tmp->family, &tmp->dst); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str); - continue; - } - - r = route_add(link, tmp, &route); - if (r < 0) - return log_link_error_errno(link, r, "Failed to add route: %m"); - - if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) { - r = sd_event_add_time(link->manager->event, &expire, - clock_boottime_or_monotonic(), - route->lifetime, 0, route_expire_handler, route); - if (r < 0) - log_link_warning_errno(link, r, "Could not arm route expiration handler: %m"); - } - - sd_event_source_unref(route->expire); - route->expire = TAKE_PTR(expire); - } + r = link_deserialize_routes(link, routes); + if (r < 0) + log_link_warning_errno(link, r, "Failed to load routes from %s, ignoring: %m", link->state_file); if (dhcp4_address) { r = in_addr_from_string(AF_INET, dhcp4_address, &address); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 87006a6c44..0ac6ccd794 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1234,6 +1234,72 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma return 1; } +int link_deserialize_routes(Link *link, const char *routes) { + int r; + + assert(link); + + for (const char *p = routes;; ) { + _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; + _cleanup_(route_freep) Route *tmp = NULL; + _cleanup_free_ char *route_str = NULL; + char *prefixlen_str; + Route *route; + + r = extract_first_word(&p, &route_str, NULL, 0); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to parse ROUTES=: %m"); + if (r == 0) + return 0; + + prefixlen_str = strchr(route_str, '/'); + if (!prefixlen_str) { + log_link_debug(link, "Failed to parse route, ignoring: %s", route_str); + continue; + } + *prefixlen_str++ = '\0'; + + r = route_new(&tmp); + if (r < 0) + return log_oom(); + + r = sscanf(prefixlen_str, + "%hhu/%hhu/%"SCNu32"/%"PRIu32"/"USEC_FMT, + &tmp->dst_prefixlen, + &tmp->tos, + &tmp->priority, + &tmp->table, + &tmp->lifetime); + if (r != 5) { + log_link_debug(link, + "Failed to parse destination prefix length, tos, priority, table or expiration: %s", + prefixlen_str); + continue; + } + + r = in_addr_from_string_auto(route_str, &tmp->family, &tmp->dst); + if (r < 0) { + log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str); + continue; + } + + r = route_add(link, tmp, &route); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to add route: %m"); + + if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) { + r = sd_event_add_time(link->manager->event, &expire, + clock_boottime_or_monotonic(), + route->lifetime, 0, route_expire_handler, route); + if (r < 0) + log_link_debug_errno(link, r, "Could not arm route expiration handler: %m"); + } + + sd_event_source_unref(route->expire); + route->expire = TAKE_PTR(expire); + } +} + int network_add_ipv4ll_route(Network *network) { _cleanup_(route_free_or_set_invalidp) Route *n = NULL; int r; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index d5760a96a6..02b7c1b3ad 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -74,6 +74,7 @@ int route_remove(Route *route, Link *link, link_netlink_message_handler_t callba int link_set_routes(Link *link); int link_drop_routes(Link *link); int link_drop_foreign_routes(Link *link); +int link_deserialize_routes(Link *link, const char *routes); int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); From 565194127a92fe80b6254b4ed9482c8473197586 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 11:56:12 +0900 Subject: [PATCH 076/138] network: introduce link_serialize_routes() --- src/network/networkd-link.c | 20 +++----------------- src/network/networkd-route.c | 25 +++++++++++++++++++++++++ src/network/networkd-route.h | 1 + 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0217300be6..4daefb8dbe 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3975,7 +3975,6 @@ int link_save(Link *link) { const char *admin_state, *oper_state, *carrier_state, *address_state; _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; - Route *route; Address *a; int r; @@ -4210,22 +4209,9 @@ int link_save(Link *link) { /************************************************************/ - fputs("ROUTES=", f); - space = false; - SET_FOREACH(route, link->routes) { - _cleanup_free_ char *route_str = NULL; - - r = in_addr_to_string(route->family, &route->dst, &route_str); - if (r < 0) - goto fail; - - fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%"PRIu32"/"USEC_FMT, - space ? " " : "", route_str, - route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime); - space = true; - } - - fputc('\n', f); + r = link_serialize_routes(link, f); + if (r < 0) + goto fail; } print_link_hashmap(f, "CARRIER_BOUND_TO=", link->bound_to_links); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 0ac6ccd794..ad837099c8 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1234,6 +1234,31 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma return 1; } +int link_serialize_routes(Link *link, FILE *f) { + bool space = false; + Route *route; + + assert(link); + assert(link->network); + assert(f); + + fputs("ROUTES=", f); + SET_FOREACH(route, link->routes) { + _cleanup_free_ char *route_str = NULL; + + if (in_addr_to_string(route->family, &route->dst, &route_str) < 0) + continue; + + fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%"PRIu32"/"USEC_FMT, + space ? " " : "", route_str, + route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime); + space = true; + } + fputc('\n', f); + + return 0; +} + int link_deserialize_routes(Link *link, const char *routes) { int r; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 02b7c1b3ad..3cff8bba41 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -74,6 +74,7 @@ int route_remove(Route *route, Link *link, link_netlink_message_handler_t callba int link_set_routes(Link *link); int link_drop_routes(Link *link); int link_drop_foreign_routes(Link *link); +int link_serialize_routes(Link *link, FILE *f); int link_deserialize_routes(Link *link, const char *routes); int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); From d9940a3f8a5a5d4e67e67ff5386c7962e3d4adaa Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 10:08:39 +0900 Subject: [PATCH 077/138] network: introduce network_verify_routes() --- src/network/networkd-network.c | 8 +++----- src/network/networkd-route.c | 12 +++++++++++- src/network/networkd-route.h | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index b9b3ed24d2..db192cb475 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -156,7 +156,6 @@ static int network_resolve_stacked_netdevs(Network *network) { int network_verify(Network *network) { Address *address, *address_next; - Route *route, *route_next; TrafficControl *tc; SRIOV *sr_iov; @@ -219,6 +218,8 @@ int network_verify(Network *network) { address_free(address); } if (network->n_static_routes > 0) { + Route *route; + log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.", network->filename); while ((route = network->static_routes)) @@ -298,10 +299,7 @@ int network_verify(Network *network) { if (address_section_verify(address) < 0) address_free(address); - LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes) - if (route_section_verify(route, network) < 0) - route_free(route); - + network_verify_routes(network); network_verify_nexthops(network); network_verify_fdb_entries(network); network_verify_mdb_entries(network); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index ad837099c8..65ab7f46c1 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -2162,7 +2162,7 @@ int config_parse_multipath_route( return 0; } -int route_section_verify(Route *route, Network *network) { +static int route_section_verify(Route *route, Network *network) { if (section_is_invalid(route->section)) return -EINVAL; @@ -2202,3 +2202,13 @@ int route_section_verify(Route *route, Network *network) { return 0; } + +void network_verify_routes(Network *network) { + Route *route, *route_next; + + assert(network); + + LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes) + if (route_section_verify(route, network) < 0) + route_free(route); +} diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 3cff8bba41..42eda8e762 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -85,12 +85,12 @@ int route_add_foreign(Link *link, Route *in, Route **ret); bool route_equal(Route *r1, Route *r2); int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata); -int route_section_verify(Route *route, Network *network); DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free); int network_add_ipv4ll_route(Network *network); int network_add_default_route_on_device(Network *network); +void network_verify_routes(Network *network); const char* route_type_to_string(int t) _const_; int route_type_from_string(const char *s) _pure_; From 74154c2e28bf0b397baa4cb33840d5945c2c2ae0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 10:16:25 +0900 Subject: [PATCH 078/138] network: make several functions static --- src/network/networkd-route.c | 227 ++++++++++++++++++----------------- src/network/networkd-route.h | 23 +--- 2 files changed, 117 insertions(+), 133 deletions(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 65ab7f46c1..460f3623a7 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -25,6 +25,116 @@ #define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U +static const char * const route_type_table[__RTN_MAX] = { + [RTN_UNICAST] = "unicast", + [RTN_LOCAL] = "local", + [RTN_BROADCAST] = "broadcast", + [RTN_ANYCAST] = "anycast", + [RTN_MULTICAST] = "multicast", + [RTN_BLACKHOLE] = "blackhole", + [RTN_UNREACHABLE] = "unreachable", + [RTN_PROHIBIT] = "prohibit", + [RTN_THROW] = "throw", + [RTN_NAT] = "nat", + [RTN_XRESOLVE] = "xresolve", +}; + +assert_cc(__RTN_MAX <= UCHAR_MAX); +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_type, int); + +static const char * const route_scope_table[] = { + [RT_SCOPE_UNIVERSE] = "global", + [RT_SCOPE_SITE] = "site", + [RT_SCOPE_LINK] = "link", + [RT_SCOPE_HOST] = "host", + [RT_SCOPE_NOWHERE] = "nowhere", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_scope, int); + +#define ROUTE_SCOPE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("nowhere") + 1) +static const char *format_route_scope(int scope, char *buf, size_t size) { + const char *s; + char *p = buf; + + s = route_scope_to_string(scope); + if (s) + strpcpy(&p, size, s); + else + strpcpyf(&p, size, "%d", scope); + + return buf; +} + +static const char * const route_table_table[] = { + [RT_TABLE_DEFAULT] = "default", + [RT_TABLE_MAIN] = "main", + [RT_TABLE_LOCAL] = "local", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_table, int); + +#define ROUTE_TABLE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("default") + 1) +static const char *format_route_table(int table, char *buf, size_t size) { + const char *s; + char *p = buf; + + s = route_table_to_string(table); + if (s) + strpcpy(&p, size, s); + else + strpcpyf(&p, size, "%d", table); + + return buf; +} + +static const char * const route_protocol_table[] = { + [RTPROT_KERNEL] = "kernel", + [RTPROT_BOOT] = "boot", + [RTPROT_STATIC] = "static", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_protocol, int); + +static const char * const route_protocol_full_table[] = { + [RTPROT_REDIRECT] = "redirect", + [RTPROT_KERNEL] = "kernel", + [RTPROT_BOOT] = "boot", + [RTPROT_STATIC] = "static", + [RTPROT_GATED] = "gated", + [RTPROT_RA] = "ra", + [RTPROT_MRT] = "mrt", + [RTPROT_ZEBRA] = "zebra", + [RTPROT_BIRD] = "bird", + [RTPROT_DNROUTED] = "dnrouted", + [RTPROT_XORP] = "xorp", + [RTPROT_NTK] = "ntk", + [RTPROT_DHCP] = "dhcp", + [RTPROT_MROUTED] = "mrouted", + [RTPROT_BABEL] = "babel", + [RTPROT_BGP] = "bgp", + [RTPROT_ISIS] = "isis", + [RTPROT_OSPF] = "ospf", + [RTPROT_RIP] = "rip", + [RTPROT_EIGRP] = "eigrp", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(route_protocol_full, int); + +#define ROUTE_PROTOCOL_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("redirect") + 1) +static const char *format_route_protocol(int protocol, char *buf, size_t size) { + const char *s; + char *p = buf; + + s = route_protocol_full_to_string(protocol); + if (s) + strpcpy(&p, size, s); + else + strpcpyf(&p, size, "%d", protocol); + + return buf; +} + static unsigned routes_max(void) { static thread_local unsigned cached = 0; @@ -282,7 +392,7 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( route_compare_func, route_free); -bool route_equal(Route *r1, Route *r2) { +static bool route_equal(Route *r1, Route *r2) { if (r1 == r2) return true; @@ -292,7 +402,7 @@ bool route_equal(Route *r1, Route *r2) { return route_compare_func(r1, r2) == 0; } -int route_get(Link *link, Route *in, Route **ret) { +static int route_get(Link *link, Route *in, Route **ret) { Route *existing; @@ -362,11 +472,11 @@ static int route_add_internal(Link *link, Set **routes, Route *in, Route **ret) return 0; } -int route_add_foreign(Link *link, Route *in, Route **ret) { +static int route_add_foreign(Link *link, Route *in, Route **ret) { return route_add_internal(link, &link->routes_foreign, in, ret); } -int route_add(Link *link, Route *in, Route **ret) { +static int route_add(Link *link, Route *in, Route **ret) { Route *route; int r; @@ -585,7 +695,7 @@ int link_drop_routes(Link *link) { return r; } -int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { +static int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { Route *route = userdata; int r; @@ -1378,113 +1488,6 @@ int network_add_default_route_on_device(Network *network) { return 0; } -static const char * const route_type_table[__RTN_MAX] = { - [RTN_UNICAST] = "unicast", - [RTN_LOCAL] = "local", - [RTN_BROADCAST] = "broadcast", - [RTN_ANYCAST] = "anycast", - [RTN_MULTICAST] = "multicast", - [RTN_BLACKHOLE] = "blackhole", - [RTN_UNREACHABLE] = "unreachable", - [RTN_PROHIBIT] = "prohibit", - [RTN_THROW] = "throw", - [RTN_NAT] = "nat", - [RTN_XRESOLVE] = "xresolve", -}; - -assert_cc(__RTN_MAX <= UCHAR_MAX); -DEFINE_STRING_TABLE_LOOKUP(route_type, int); - -static const char * const route_scope_table[] = { - [RT_SCOPE_UNIVERSE] = "global", - [RT_SCOPE_SITE] = "site", - [RT_SCOPE_LINK] = "link", - [RT_SCOPE_HOST] = "host", - [RT_SCOPE_NOWHERE] = "nowhere", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_scope, int); - -const char *format_route_scope(int scope, char *buf, size_t size) { - const char *s; - char *p = buf; - - s = route_scope_to_string(scope); - if (s) - strpcpy(&p, size, s); - else - strpcpyf(&p, size, "%d", scope); - - return buf; -} - -static const char * const route_table_table[] = { - [RT_TABLE_DEFAULT] = "default", - [RT_TABLE_MAIN] = "main", - [RT_TABLE_LOCAL] = "local", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_table, int); - -const char *format_route_table(int table, char *buf, size_t size) { - const char *s; - char *p = buf; - - s = route_table_to_string(table); - if (s) - strpcpy(&p, size, s); - else - strpcpyf(&p, size, "%d", table); - - return buf; -} - -static const char * const route_protocol_table[] = { - [RTPROT_KERNEL] = "kernel", - [RTPROT_BOOT] = "boot", - [RTPROT_STATIC] = "static", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_protocol, int); - -static const char * const route_protocol_full_table[] = { - [RTPROT_REDIRECT] = "redirect", - [RTPROT_KERNEL] = "kernel", - [RTPROT_BOOT] = "boot", - [RTPROT_STATIC] = "static", - [RTPROT_GATED] = "gated", - [RTPROT_RA] = "ra", - [RTPROT_MRT] = "mrt", - [RTPROT_ZEBRA] = "zebra", - [RTPROT_BIRD] = "bird", - [RTPROT_DNROUTED] = "dnrouted", - [RTPROT_XORP] = "xorp", - [RTPROT_NTK] = "ntk", - [RTPROT_DHCP] = "dhcp", - [RTPROT_MROUTED] = "mrouted", - [RTPROT_BABEL] = "babel", - [RTPROT_BGP] = "bgp", - [RTPROT_ISIS] = "isis", - [RTPROT_OSPF] = "ospf", - [RTPROT_RIP] = "rip", - [RTPROT_EIGRP] = "eigrp", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(route_protocol_full, int); - -const char *format_route_protocol(int protocol, char *buf, size_t size) { - const char *s; - char *p = buf; - - s = route_protocol_full_to_string(protocol); - if (s) - strpcpy(&p, size, s); - else - strpcpyf(&p, size, "%d", protocol); - - return buf; -} - int config_parse_gateway( const char *unit, const char *filename, diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 42eda8e762..7bbe16e7e0 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -68,6 +68,8 @@ extern const struct hash_ops route_hash_ops; int route_new(Route **ret); Route *route_free(Route *route); +DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free); + int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback, Route **ret); int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback); @@ -79,31 +81,10 @@ int link_deserialize_routes(Link *link, const char *routes); int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); -int route_get(Link *link, Route *in, Route **ret); -int route_add(Link *link, Route *in, Route **ret); -int route_add_foreign(Link *link, Route *in, Route **ret); -bool route_equal(Route *r1, Route *r2); - -int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata); - -DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free); - int network_add_ipv4ll_route(Network *network); int network_add_default_route_on_device(Network *network); void network_verify_routes(Network *network); -const char* route_type_to_string(int t) _const_; -int route_type_from_string(const char *s) _pure_; - -#define ROUTE_SCOPE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("nowhere") + 1) -const char *format_route_scope(int scope, char *buf, size_t size); - -#define ROUTE_TABLE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("default") + 1) -const char *format_route_table(int table, char *buf, size_t size); - -#define ROUTE_PROTOCOL_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("redirect") + 1) -const char *format_route_protocol(int protocol, char *buf, size_t size); - CONFIG_PARSER_PROTOTYPE(config_parse_gateway); CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src); CONFIG_PARSER_PROTOTYPE(config_parse_destination); From 833f3663a07a868a023579801afb08522e3ecf79 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 22:16:46 +0900 Subject: [PATCH 079/138] network: introduce hashmap_find_free_section_line() --- src/network/networkd-util.c | 12 ++++++++++++ src/network/networkd-util.h | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c index ce9319d942..bae4ee5cba 100644 --- a/src/network/networkd-util.c +++ b/src/network/networkd-util.c @@ -151,3 +151,15 @@ int network_config_section_new(const char *filename, unsigned line, NetworkConfi void network_config_section_free(NetworkConfigSection *cs) { free(cs); } + +unsigned hashmap_find_free_section_line(Hashmap *hashmap) { + NetworkConfigSection *cs; + unsigned n = 0; + void *entry; + + HASHMAP_FOREACH_KEY(entry, cs, hashmap) + if (n < cs->line) + n = cs->line; + + return n + 1; +} diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h index 2b6541d57e..ce169fa731 100644 --- a/src/network/networkd-util.h +++ b/src/network/networkd-util.h @@ -5,7 +5,7 @@ #include "sd-netlink.h" #include "conf-parser.h" -#include "hash-funcs.h" +#include "hashmap.h" #include "log.h" #include "macro.h" #include "string-util.h" @@ -52,6 +52,7 @@ int network_config_section_new(const char *filename, unsigned line, NetworkConfi void network_config_section_free(NetworkConfigSection *network); DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free); extern const struct hash_ops network_config_hash_ops; +unsigned hashmap_find_free_section_line(Hashmap *hashmap); static inline bool section_is_invalid(NetworkConfigSection *section) { /* If this returns false, then it does _not_ mean the section is valid. */ From 2a54a0446b2ff2cd8f4fcded06fcc59602140079 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 10:41:55 +0900 Subject: [PATCH 080/138] network: drop list of static routes [Route] sections are managed by both LIST and Hashmap. Let's drop the list. --- src/network/networkd-dhcp4.c | 2 +- src/network/networkd-ndisc.c | 2 +- src/network/networkd-network.c | 16 ++------ src/network/networkd-network.h | 2 - src/network/networkd-route.c | 74 +++++++++++++++------------------- src/network/networkd-route.h | 2 - 6 files changed, 39 insertions(+), 59 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 8dd89c22a2..18ce0c61bb 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -384,7 +384,7 @@ static int link_set_dhcp_routes(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not set router: %m"); - LIST_FOREACH(routes, rt, link->network->static_routes) { + HASHMAP_FOREACH(rt, link->network->routes_by_section) { if (!rt->gateway_from_dhcp) continue; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 64b27276e0..256f6cc659 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -490,7 +490,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { return log_link_error_errno(link, r, "Could not set default route: %m"); Route *route_gw; - LIST_FOREACH(routes, route_gw, link->network->static_routes) { + HASHMAP_FOREACH(route_gw, link->network->routes_by_section) { if (!route_gw->gateway_from_dhcp) continue; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index db192cb475..aa9a3346dc 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -217,14 +217,10 @@ int network_verify(Network *network) { while ((address = network->static_addresses)) address_free(address); } - if (network->n_static_routes > 0) { - Route *route; - + if (!hashmap_isempty(network->routes_by_section)) log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.", network->filename); - while ((route = network->static_routes)) - route_free(route); - } + network->routes_by_section = hashmap_free_with_destructor(network->routes_by_section, route_free); } if (network->link_local < 0) @@ -624,7 +620,6 @@ failure: static Network *network_free(Network *network) { Address *address; - Route *route; if (!network) return NULL; @@ -681,15 +676,12 @@ static Network *network_free(Network *network) { netdev_unref(network->vrf); hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref); - while ((route = network->static_routes)) - route_free(route); - while ((address = network->static_addresses)) address_free(address); set_free_free(network->ipv6_proxy_ndp_addresses); hashmap_free(network->addresses_by_section); - hashmap_free(network->routes_by_section); + hashmap_free_with_destructor(network->routes_by_section, route_free); hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free); hashmap_free_with_destructor(network->fdb_entries_by_section, fdb_entry_free); hashmap_free_with_destructor(network->mdb_entries_by_section, mdb_entry_free); @@ -814,7 +806,7 @@ bool network_has_static_ipv6_configurations(Network *network) { if (address->family == AF_INET6) return true; - LIST_FOREACH(routes, route, network->static_routes) + HASHMAP_FOREACH(route, network->routes_by_section) if (route->family == AF_INET6) return true; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index b7a93fb942..8470941709 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -280,10 +280,8 @@ struct Network { char *lldp_mud; /* LLDP MUD URL */ LIST_HEAD(Address, static_addresses); - LIST_HEAD(Route, static_routes); unsigned n_static_addresses; - unsigned n_static_routes; Hashmap *addresses_by_section; Hashmap *routes_by_section; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 460f3623a7..453a33e1ce 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -194,22 +194,20 @@ static int route_new_static(Network *network, const char *filename, unsigned sec assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; - route = hashmap_get(network->routes_by_section, n); - if (route) { - *ret = TAKE_PTR(route); - - return 0; - } + route = hashmap_get(network->routes_by_section, n); + if (route) { + *ret = TAKE_PTR(route); + return 0; } - if (network->n_static_routes >= routes_max()) + if (hashmap_size(network->routes_by_section) >= routes_max()) return -E2BIG; r = route_new(&route); @@ -218,23 +216,17 @@ static int route_new_static(Network *network, const char *filename, unsigned sec route->protocol = RTPROT_STATIC; route->network = network; - LIST_PREPEND(routes, network->static_routes, route); - network->n_static_routes++; + route->section = TAKE_PTR(n); - if (filename) { - route->section = TAKE_PTR(n); + r = hashmap_ensure_allocated(&network->routes_by_section, &network_config_hash_ops); + if (r < 0) + return r; - r = hashmap_ensure_allocated(&network->routes_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->routes_by_section, route->section, route); - if (r < 0) - return r; - } + r = hashmap_put(network->routes_by_section, route->section, route); + if (r < 0) + return r; *ret = TAKE_PTR(route); - return 0; } @@ -243,13 +235,8 @@ Route *route_free(Route *route) { return NULL; if (route->network) { - LIST_REMOVE(routes, route->network->static_routes, route); - - assert(route->network->n_static_routes > 0); - route->network->n_static_routes--; - - if (route->section) - hashmap_remove(route->network->routes_by_section, route->section); + assert(route->section); + hashmap_remove(route->network->routes_by_section, route->section); } network_config_section_free(route->section); @@ -630,7 +617,7 @@ static bool link_is_static_route_configured(Link *link, Route *route) { if (!link->network) return false; - LIST_FOREACH(routes, net_route, link->network->static_routes) + HASHMAP_FOREACH(net_route, link->network->routes_by_section) if (route_equal(net_route, route)) return true; @@ -1065,7 +1052,7 @@ int link_set_routes(Link *link) { /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */ for (phase = 0; phase < _PHASE_MAX; phase++) - LIST_FOREACH(routes, rt, link->network->static_routes) { + HASHMAP_FOREACH(rt, link->network->routes_by_section) { if (rt->gateway_from_dhcp) continue; @@ -1437,6 +1424,7 @@ int link_deserialize_routes(Link *link, const char *routes) { int network_add_ipv4ll_route(Network *network) { _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + unsigned section_line; int r; assert(network); @@ -1444,8 +1432,10 @@ int network_add_ipv4ll_route(Network *network) { if (!network->ipv4ll_route) return 0; + section_line = hashmap_find_free_section_line(network->routes_by_section); + /* IPv4LLRoute= is in [Network] section. */ - r = route_new_static(network, NULL, 0, &n); + r = route_new_static(network, network->filename, section_line, &n); if (r < 0) return r; @@ -1467,6 +1457,7 @@ int network_add_ipv4ll_route(Network *network) { int network_add_default_route_on_device(Network *network) { _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + unsigned section_line; int r; assert(network); @@ -1474,8 +1465,10 @@ int network_add_default_route_on_device(Network *network) { if (!network->default_route_on_device) return 0; + section_line = hashmap_find_free_section_line(network->routes_by_section); + /* DefaultRouteOnDevice= is in [Network] section. */ - r = route_new_static(network, NULL, 0, &n); + r = route_new_static(network, network->filename, section_line, &n); if (r < 0) return r; @@ -1511,9 +1504,8 @@ int config_parse_gateway( assert(data); if (streq(section, "Network")) { - /* we are not in an Route section, so treat - * this as the special '0' section */ - r = route_new_static(network, NULL, 0, &n); + /* we are not in an Route section, so use line number instead */ + r = route_new_static(network, filename, line, &n); if (r == -ENOMEM) return log_oom(); if (r < 0) { @@ -2207,11 +2199,11 @@ static int route_section_verify(Route *route, Network *network) { } void network_verify_routes(Network *network) { - Route *route, *route_next; + Route *route; assert(network); - LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes) + HASHMAP_FOREACH(route, network->routes_by_section) if (route_section_verify(route, network) < 0) route_free(route); } diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 7bbe16e7e0..676bea3d70 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -58,8 +58,6 @@ struct Route { usec_t lifetime; sd_event_source *expire; - - LIST_FIELDS(Route, routes); }; void route_hash_func(const Route *route, struct siphash *state); From e2263711ba066e4275e6d9138dc10de86d9b08b0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 10:55:06 +0900 Subject: [PATCH 081/138] network: cleanup networkd-route.h --- src/network/networkd-ndisc.c | 1 - src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.h | 1 - src/network/networkd-route.c | 6 +----- src/network/networkd-route.h | 21 +++++++++++++-------- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 256f6cc659..545574e126 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -12,7 +12,6 @@ #include "networkd-dhcp6.h" #include "networkd-manager.h" #include "networkd-ndisc.h" -#include "networkd-route.h" #include "string-table.h" #include "string-util.h" #include "strv.h" diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 3b5056e105..1d899464d8 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -22,6 +22,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "networkd-neighbor.h" #include "networkd-nexthop.h" #include "networkd-radv.h" +#include "networkd-route.h" #include "networkd-routing-policy-rule.h" #include "networkd-sriov.h" #include "qdisc.h" diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 8470941709..c56c24656a 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -22,7 +22,6 @@ #include "networkd-lldp-tx.h" #include "networkd-ndisc.h" #include "networkd-radv.h" -#include "networkd-route.h" #include "networkd-util.h" #include "ordered-set.h" #include "resolve-util.h" diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 453a33e1ce..e59f634fb1 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -3,18 +3,14 @@ #include #include "alloc-util.h" -#include "conf-parser.h" -#include "in-addr-util.h" -#include "missing_network.h" #include "netlink-util.h" #include "networkd-ipv4ll.h" #include "networkd-manager.h" -#include "networkd-ndisc.h" +#include "networkd-network.h" #include "networkd-nexthop.h" #include "networkd-route.h" #include "networkd-routing-policy-rule.h" #include "parse-util.h" -#include "set.h" #include "socket-netlink.h" #include "string-table.h" #include "string-util.h" diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 676bea3d70..ac545d9b78 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -1,15 +1,20 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include +#include +#include + +#include "sd-netlink.h" + #include "conf-parser.h" -#include "macro.h" - -typedef struct Route Route; -typedef struct NetworkConfigSection NetworkConfigSection; - -#include "networkd-network.h" +#include "in-addr-util.h" +#include "networkd-link.h" #include "networkd-util.h" +typedef struct Manager Manager; +typedef struct Network Network; + typedef struct MultipathRouteVia { uint16_t family; union in_addr_union address; @@ -21,7 +26,7 @@ typedef struct MultipathRoute { uint32_t weight; } MultipathRoute; -struct Route { +typedef struct Route { Network *network; NetworkConfigSection *section; @@ -58,7 +63,7 @@ struct Route { usec_t lifetime; sd_event_source *expire; -}; +} Route; void route_hash_func(const Route *route, struct siphash *state); int route_compare_func(const Route *a, const Route *b); From 682c65b04cc84732efb4c2c03878f1b099bf1f91 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 11:17:49 +0900 Subject: [PATCH 082/138] network: introduce link_set_addresses() --- src/network/networkd-address.c | 171 ++++++++++++++++++++++++++++++++ src/network/networkd-address.h | 2 + src/network/networkd-link.c | 172 ++------------------------------- 3 files changed, 180 insertions(+), 165 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 76c91ef9dd..454be9a066 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -747,6 +747,177 @@ int address_configure( return 1; } +static int static_address_ready_callback(Address *address) { + Address *a; + Link *link; + + assert(address); + assert(address->link); + + link = address->link; + + if (!link->addresses_configured) + return 0; + + SET_FOREACH(a, link->static_addresses) + if (!address_is_ready(a)) { + _cleanup_free_ char *str = NULL; + + (void) in_addr_to_string(a->family, &a->in_addr, &str); + log_link_debug(link, "an address %s/%u is not ready", strnull(str), a->prefixlen); + return 0; + } + + /* This should not be called again */ + SET_FOREACH(a, link->static_addresses) + a->callback = NULL; + + link->addresses_ready = true; + + return link_set_routes(link); +} + +static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(rtnl); + assert(m); + assert(link); + assert(link->ifname); + assert(link->address_messages > 0); + assert(IN_SET(link->state, LINK_STATE_CONFIGURING, + LINK_STATE_FAILED, LINK_STATE_LINGER)); + + link->address_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_message_warning_errno(link, m, r, "Could not set address"); + link_enter_failed(link); + return 1; + } else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + if (link->address_messages == 0) { + Address *a; + + log_link_debug(link, "Addresses set"); + link->addresses_configured = true; + + /* When all static addresses are already ready, then static_address_ready_callback() + * will not be called automatically. So, call it here. */ + a = set_first(link->static_addresses); + if (!a) { + log_link_warning(link, "No static address is stored."); + link_enter_failed(link); + return 1; + } + if (!a->callback) { + log_link_warning(link, "Address ready callback is not set."); + link_enter_failed(link); + return 1; + } + r = a->callback(a); + if (r < 0) + link_enter_failed(link); + } + + return 1; +} + +static int static_address_configure(Address *address, Link *link, bool update) { + Address *ret; + int r; + + assert(address); + assert(link); + + r = address_configure(address, link, address_handler, update, &ret); + if (r < 0) + return log_link_warning_errno(link, r, "Could not configure static address: %m"); + + link->address_messages++; + + r = set_ensure_put(&link->static_addresses, &address_hash_ops, ret); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to store static address: %m"); + + ret->callback = static_address_ready_callback; + + return 0; +} + +int link_set_addresses(Link *link) { + Address *ad; + int r; + + assert(link); + assert(link->network); + + if (link->address_remove_messages != 0) { + log_link_debug(link, "Removing old addresses, new addresses will be configured later."); + link->request_static_addresses = true; + return 0; + } + + LIST_FOREACH(addresses, ad, link->network->static_addresses) { + bool update; + + if (ad->family == AF_INET6 && !in_addr_is_null(ad->family, &ad->in_addr_peer)) + update = address_get(link, ad->family, &ad->in_addr_peer, ad->prefixlen, NULL) > 0; + else + update = address_get(link, ad->family, &ad->in_addr, ad->prefixlen, NULL) > 0; + + r = static_address_configure(ad, link, update); + if (r < 0) + return r; + } + + if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) { + Prefix *p; + + HASHMAP_FOREACH(p, link->network->prefixes_by_section) { + _cleanup_(address_freep) Address *address = NULL; + + if (!p->assign) + continue; + + r = address_new(&address); + if (r < 0) + return log_oom(); + + r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen); + if (r < 0) + return log_link_warning_errno(link, r, "Could not get RA prefix: %m"); + + r = generate_ipv6_eui_64_address(link, &address->in_addr.in6); + if (r < 0) + return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m"); + + address->family = AF_INET6; + r = static_address_configure(address, link, true); + if (r < 0) + return r; + } + } + + if (link->address_messages == 0) { + link->addresses_configured = true; + link->addresses_ready = true; + r = link_set_routes(link); + if (r < 0) + return r; + } else { + log_link_debug(link, "Setting addresses"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { _cleanup_free_ char *pretty = NULL; Address *address; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 1378901b8b..b8a397d6cb 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -75,6 +75,8 @@ int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret); DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free); +int link_set_addresses(Link *link); + void address_hash_func(const Address *a, struct siphash *state); int address_compare_func(const Address *a1, const Address *a2); extern const struct hash_ops address_hash_ops; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 4daefb8dbe..929fbddd9c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1051,123 +1051,13 @@ void link_check_ready(Link *link) { return; } -static int static_address_ready_callback(Address *address) { - Address *a; - Link *link; - - assert(address); - assert(address->link); - - link = address->link; - - if (!link->addresses_configured) - return 0; - - SET_FOREACH(a, link->static_addresses) - if (!address_is_ready(a)) { - _cleanup_free_ char *str = NULL; - - (void) in_addr_to_string(a->family, &a->in_addr, &str); - log_link_debug(link, "an address %s/%u is not ready", strnull(str), a->prefixlen); - return 0; - } - - /* This should not be called again */ - SET_FOREACH(a, link->static_addresses) - a->callback = NULL; - - link->addresses_ready = true; - - return link_set_routes(link); -} - -static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(rtnl); - assert(m); - assert(link); - assert(link->ifname); - assert(link->address_messages > 0); - assert(IN_SET(link->state, LINK_STATE_CONFIGURING, - LINK_STATE_FAILED, LINK_STATE_LINGER)); - - link->address_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_message_warning_errno(link, m, r, "Could not set address"); - link_enter_failed(link); - return 1; - } else if (r >= 0) - (void) manager_rtnl_process_address(rtnl, m, link->manager); - - if (link->address_messages == 0) { - Address *a; - - log_link_debug(link, "Addresses set"); - link->addresses_configured = true; - - /* When all static addresses are already ready, then static_address_ready_callback() - * will not be called automatically. So, call it here. */ - a = set_first(link->static_addresses); - if (!a) { - log_link_warning(link, "No static address is stored."); - link_enter_failed(link); - return 1; - } - if (!a->callback) { - log_link_warning(link, "Address ready callback is not set."); - link_enter_failed(link); - return 1; - } - r = a->callback(a); - if (r < 0) - link_enter_failed(link); - } - - return 1; -} - -static int static_address_configure(Address *address, Link *link, bool update) { - Address *ret; - int r; - - assert(address); - assert(link); - - r = address_configure(address, link, address_handler, update, &ret); - if (r < 0) - return log_link_warning_errno(link, r, "Could not configure static address: %m"); - - link->address_messages++; - - r = set_ensure_put(&link->static_addresses, &address_hash_ops, ret); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to store static address: %m"); - - ret->callback = static_address_ready_callback; - - return 0; -} - -static int link_request_set_addresses(Link *link) { - Address *ad; +static int link_set_static_configs(Link *link) { int r; assert(link); assert(link->network); assert(link->state != _LINK_STATE_INVALID); - if (link->address_remove_messages != 0) { - log_link_debug(link, "Removing old addresses, new addresses will be configured later."); - link->request_static_addresses = true; - return 0; - } - /* Reset all *_configured flags we are configuring. */ link->request_static_addresses = false; link->addresses_configured = false; @@ -1189,46 +1079,9 @@ static int link_request_set_addresses(Link *link) { if (r < 0) return r; - LIST_FOREACH(addresses, ad, link->network->static_addresses) { - bool update; - - if (ad->family == AF_INET6 && !in_addr_is_null(ad->family, &ad->in_addr_peer)) - update = address_get(link, ad->family, &ad->in_addr_peer, ad->prefixlen, NULL) > 0; - else - update = address_get(link, ad->family, &ad->in_addr, ad->prefixlen, NULL) > 0; - - r = static_address_configure(ad, link, update); - if (r < 0) - return r; - } - - if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) { - Prefix *p; - - HASHMAP_FOREACH(p, link->network->prefixes_by_section) { - _cleanup_(address_freep) Address *address = NULL; - - if (!p->assign) - continue; - - r = address_new(&address); - if (r < 0) - return log_oom(); - - r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen); - if (r < 0) - return log_link_warning_errno(link, r, "Could not get RA prefix: %m"); - - r = generate_ipv6_eui_64_address(link, &address->in_addr.in6); - if (r < 0) - return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m"); - - address->family = AF_INET6; - r = static_address_configure(address, link, true); - if (r < 0) - return r; - } - } + r = link_set_addresses(link); + if (r < 0) + return r; r = link_set_address_labels(link); if (r < 0) @@ -1242,17 +1095,6 @@ static int link_request_set_addresses(Link *link) { log_link_debug(link, "Offering DHCPv4 leases"); } - if (link->address_messages == 0) { - link->addresses_configured = true; - link->addresses_ready = true; - r = link_set_routes(link); - if (r < 0) - return r; - } else { - log_link_debug(link, "Setting addresses"); - link_set_state(link, LINK_STATE_CONFIGURING); - } - return 0; } @@ -2165,7 +2007,7 @@ static int link_joined(Link *link) { return 0; link_set_state(link, LINK_STATE_CONFIGURING); - return link_request_set_addresses(link); + return link_set_static_configs(link); } static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { @@ -2627,7 +2469,7 @@ static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m if (link->address_remove_messages == 0 && link->request_static_addresses) { link_set_state(link, LINK_STATE_CONFIGURING); - r = link_request_set_addresses(link); + r = link_set_addresses(link); if (r < 0) link_enter_failed(link); } @@ -3555,7 +3397,7 @@ static int link_carrier_gained(Link *link) { } link_set_state(link, LINK_STATE_CONFIGURING); - r = link_request_set_addresses(link); + r = link_set_static_configs(link); if (r < 0) return r; } From f8f2f880d4b7bee6ec64aef4c252e4064c67d133 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 11:26:12 +0900 Subject: [PATCH 083/138] network: introduce link_drop_foreign_addresses() --- src/network/networkd-address.c | 79 ++++++++++++++++++++++++++++++++++ src/network/networkd-address.h | 1 + src/network/networkd-link.c | 72 ++----------------------------- src/network/networkd-link.h | 1 + 4 files changed, 85 insertions(+), 68 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 454be9a066..86ea5c2da1 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -542,6 +542,85 @@ int address_remove( return 0; } +static bool link_is_static_address_configured(Link *link, Address *address) { + Address *net_address; + + assert(link); + assert(address); + + if (!link->network) + return false; + + LIST_FOREACH(addresses, net_address, link->network->static_addresses) + if (address_equal(net_address, address)) + return true; + else if (address->family == AF_INET6 && net_address->family == AF_INET6 && + in_addr_equal(AF_INET6, &address->in_addr, &net_address->in_addr_peer) > 0) + return true; + + return false; +} + +static bool link_address_is_dynamic(Link *link, Address *address) { + Route *route; + + assert(link); + assert(address); + + if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME) + return true; + + /* Even when the address is leased from a DHCP server, networkd assign the address + * without lifetime when KeepConfiguration=dhcp. So, let's check that we have + * corresponding routes with RTPROT_DHCP. */ + SET_FOREACH(route, link->routes_foreign) { + if (route->protocol != RTPROT_DHCP) + continue; + + if (address->family != route->family) + continue; + + if (in_addr_equal(address->family, &address->in_addr, &route->prefsrc)) + return true; + } + + return false; +} + +int link_drop_foreign_addresses(Link *link) { + Address *address; + int k, r = 0; + + assert(link); + + SET_FOREACH(address, link->addresses_foreign) { + /* we consider IPv6LL addresses to be managed by the kernel */ + if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) + continue; + + if (link_address_is_dynamic(link, address)) { + if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + } else if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + + if (link_is_static_address_configured(link, address)) { + k = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); + if (k < 0) { + log_link_error_errno(link, k, "Failed to add address: %m"); + if (r >= 0) + r = k; + } + } else { + k = address_remove(address, link, NULL); + if (k < 0 && r >= 0) + r = k; + } + } + + return r; +} + static int address_acquire(Link *link, Address *original, Address **ret) { union in_addr_union in_addr = IN_ADDR_NULL; struct in_addr broadcast = {}; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index b8a397d6cb..6633423937 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -76,6 +76,7 @@ int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret); DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free); int link_set_addresses(Link *link); +int link_drop_foreign_addresses(Link *link); void address_hash_func(const Address *a, struct siphash *state); int address_compare_func(const Address *a1, const Address *a2); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 929fbddd9c..4ea97b2acb 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -163,7 +163,7 @@ bool link_ipv4ll_enabled(Link *link, AddressFamily mask) { return link->network->link_local & mask; } -static bool link_ipv6ll_enabled(Link *link) { +bool link_ipv6ll_enabled(Link *link) { assert(link); if (!socket_ipv6_is_supported()) @@ -2320,51 +2320,6 @@ static int link_set_ipv4_accept_local(Link *link) { return 0; } -static bool link_is_static_address_configured(Link *link, Address *address) { - Address *net_address; - - assert(link); - assert(address); - - if (!link->network) - return false; - - LIST_FOREACH(addresses, net_address, link->network->static_addresses) - if (address_equal(net_address, address)) - return true; - else if (address->family == AF_INET6 && net_address->family == AF_INET6 && - in_addr_equal(AF_INET6, &address->in_addr, &net_address->in_addr_peer) > 0) - return true; - - return false; -} - -static bool link_address_is_dynamic(Link *link, Address *address) { - Route *route; - - assert(link); - assert(address); - - if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME) - return true; - - /* Even when the address is leased from a DHCP server, networkd assign the address - * without lifetime when KeepConfiguration=dhcp. So, let's check that we have - * corresponding routes with RTPROT_DHCP. */ - SET_FOREACH(route, link->routes_foreign) { - if (route->protocol != RTPROT_DHCP) - continue; - - if (address->family != route->family) - continue; - - if (in_addr_equal(address->family, &address->in_addr, &route->prefsrc)) - return true; - } - - return false; -} - static int link_enumerate_ipv6_tentative_addresses(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *addr; @@ -2408,7 +2363,6 @@ static int link_enumerate_ipv6_tentative_addresses(Link *link) { } static int link_drop_foreign_config(Link *link) { - Address *address; int r; /* The kernel doesn't notify us about tentative addresses; @@ -2419,27 +2373,9 @@ static int link_drop_foreign_config(Link *link) { return r; } - SET_FOREACH(address, link->addresses_foreign) { - /* we consider IPv6LL addresses to be managed by the kernel */ - if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) - continue; - - if (link_address_is_dynamic(link, address)) { - if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) - continue; - } else if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) - continue; - - if (link_is_static_address_configured(link, address)) { - r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Failed to add address: %m"); - } else { - r = address_remove(address, link, NULL); - if (r < 0) - return r; - } - } + r = link_drop_foreign_addresses(link); + if (r < 0) + return r; r = link_drop_foreign_neighbors(link); if (r < 0) diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index aadbddc910..670ae9783d 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -226,6 +226,7 @@ int link_save_and_clean(Link *link); int link_carrier_reset(Link *link); bool link_has_carrier(Link *link); +bool link_ipv6ll_enabled(Link *link); int link_ipv6ll_gained(Link *link, const struct in6_addr *address); int link_set_mtu(Link *link, uint32_t mtu); From d7fbb9f50c9aa06a0ae9c3129900aed7cb3e425e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 11:30:33 +0900 Subject: [PATCH 084/138] network: introduce link_drop_addresses() --- src/network/networkd-address.c | 60 ++++++++++++++++++++++++++++++++++ src/network/networkd-address.h | 1 + src/network/networkd-link.c | 52 ++--------------------------- 3 files changed, 64 insertions(+), 49 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 86ea5c2da1..bb97fdacfe 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -621,6 +621,66 @@ int link_drop_foreign_addresses(Link *link) { return r; } +static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + assert(link->address_remove_messages > 0); + + link->address_remove_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EADDRNOTAVAIL) + log_link_message_warning_errno(link, m, r, "Could not drop address"); + else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + if (link->address_remove_messages == 0 && link->request_static_addresses) { + link_set_state(link, LINK_STATE_CONFIGURING); + r = link_set_addresses(link); + if (r < 0) + link_enter_failed(link); + } + + return 1; +} + +int link_drop_addresses(Link *link) { + Address *address, *pool_address; + int k, r = 0; + + assert(link); + + SET_FOREACH(address, link->addresses) { + /* we consider IPv6LL addresses to be managed by the kernel */ + if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) + continue; + + k = address_remove(address, link, remove_static_address_handler); + if (k < 0 && r >= 0) { + r = k; + continue; + } + + link->address_remove_messages++; + + /* If this address came from an address pool, clean up the pool */ + LIST_FOREACH(addresses, pool_address, link->pool_addresses) + if (address_equal(address, pool_address)) { + LIST_REMOVE(addresses, link->pool_addresses, pool_address); + address_free(pool_address); + break; + } + } + + return r; +} + static int address_acquire(Link *link, Address *original, Address **ret) { union in_addr_union in_addr = IN_ADDR_NULL; struct in_addr broadcast = {}; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 6633423937..472e8ee79a 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -76,6 +76,7 @@ int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret); DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free); int link_set_addresses(Link *link); +int link_drop_addresses(Link *link); int link_drop_foreign_addresses(Link *link); void address_hash_func(const Address *a, struct siphash *state); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 4ea97b2acb..f2314e65f2 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2384,58 +2384,12 @@ static int link_drop_foreign_config(Link *link) { return link_drop_foreign_routes(link); } -static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(m); - assert(link); - assert(link->ifname); - assert(link->address_remove_messages > 0); - - link->address_remove_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EADDRNOTAVAIL) - log_link_message_warning_errno(link, m, r, "Could not drop address"); - else if (r >= 0) - (void) manager_rtnl_process_address(rtnl, m, link->manager); - - if (link->address_remove_messages == 0 && link->request_static_addresses) { - link_set_state(link, LINK_STATE_CONFIGURING); - r = link_set_addresses(link); - if (r < 0) - link_enter_failed(link); - } - - return 1; -} - static int link_drop_config(Link *link) { - Address *address, *pool_address; int r; - SET_FOREACH(address, link->addresses) { - /* we consider IPv6LL addresses to be managed by the kernel */ - if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) - continue; - - r = address_remove(address, link, remove_static_address_handler); - if (r < 0) - return r; - - link->address_remove_messages++; - - /* If this address came from an address pool, clean up the pool */ - LIST_FOREACH(addresses, pool_address, link->pool_addresses) - if (address_equal(address, pool_address)) { - LIST_REMOVE(addresses, link->pool_addresses, pool_address); - address_free(pool_address); - break; - } - } + r = link_drop_addresses(link); + if (r < 0) + return r; r = link_drop_neighbors(link); if (r < 0) From e1fc2c437125b7098830ef75965614b35258cd62 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 11:32:35 +0900 Subject: [PATCH 085/138] network: move manager_rtnl_process_address() --- src/network/networkd-address.c | 162 +++++++++++++++++++++++++++++++++ src/network/networkd-address.h | 2 + src/network/networkd-manager.c | 162 --------------------------------- src/network/networkd-manager.h | 2 - 4 files changed, 164 insertions(+), 164 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index bb97fdacfe..9ec8d4af1f 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1057,6 +1057,168 @@ int link_set_addresses(Link *link) { return 0; } +int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { + _cleanup_free_ char *buf = NULL; + Link *link = NULL; + uint16_t type; + unsigned char flags, prefixlen, scope; + union in_addr_union in_addr = IN_ADDR_NULL; + struct ifa_cacheinfo cinfo; + Address *address = NULL; + char valid_buf[FORMAT_TIMESPAN_MAX]; + const char *valid_str = NULL; + int ifindex, family, r; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_message_warning_errno(message, r, "rtnl: failed to receive address message, ignoring"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWADDR, RTM_DELADDR)) { + log_warning("rtnl: received unexpected message type %u when processing address, ignoring.", type); + return 0; + } + + r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received address message with invalid ifindex %d, ignoring.", ifindex); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0 || !link) { + /* when enumerating we might be out of sync, but we will get the address again, so just + * ignore it */ + if (!m->enumerating) + log_warning("rtnl: received address for link '%d' we don't know about, ignoring.", ifindex); + return 0; + } + + r = sd_rtnl_message_addr_get_family(message, &family); + if (r < 0) { + log_link_warning(link, "rtnl: received address message without family, ignoring."); + return 0; + } else if (!IN_SET(family, AF_INET, AF_INET6)) { + log_link_debug(link, "rtnl: received address message with invalid family '%i', ignoring.", family); + return 0; + } + + r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid prefixlen, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_addr_get_scope(message, &scope); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid scope, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_addr_get_flags(message, &flags); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m"); + return 0; + } + + switch (family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); + return 0; + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); + return 0; + } + + break; + + default: + assert_not_reached("Received unsupported address family"); + } + + r = in_addr_to_string(family, &in_addr, &buf); + if (r < 0) + log_link_warning_errno(link, r, "Could not print address: %m"); + + r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m"); + return 0; + } else if (r >= 0 && cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME) + valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, + cinfo.ifa_valid * USEC_PER_SEC, + USEC_PER_SEC); + + (void) address_get(link, family, &in_addr, prefixlen, &address); + + switch (type) { + case RTM_NEWADDR: + if (address) + log_link_debug(link, "Remembering updated address: %s/%u (valid %s%s)", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + else { + /* An address appeared that we did not request */ + r = address_add_foreign(link, family, &in_addr, prefixlen, &address); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to remember foreign address %s/%u, ignoring: %m", + strnull(buf), prefixlen); + return 0; + } else + log_link_debug(link, "Remembering foreign address: %s/%u (valid %s%s)", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + } + + /* address_update() logs internally, so we don't need to here. */ + r = address_update(address, flags, scope, &cinfo); + if (r < 0) + link_enter_failed(link); + + break; + + case RTM_DELADDR: + if (address) { + log_link_debug(link, "Forgetting address: %s/%u (valid %s%s)", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + (void) address_drop(address); + } else + log_link_debug(link, "Kernel removed an address we don't remember: %s/%u (valid %s%s), ignoring.", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { _cleanup_free_ char *pretty = NULL; Address *address; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 472e8ee79a..5b565b6e55 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -79,6 +79,8 @@ int link_set_addresses(Link *link); int link_drop_addresses(Link *link); int link_drop_foreign_addresses(Link *link); +int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); + void address_hash_func(const Address *a, struct siphash *state); int address_compare_func(const Address *a1, const Address *a2); extern const struct hash_ops address_hash_ops; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 5cd925a27c..00f172bc90 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -285,168 +285,6 @@ static int manager_connect_udev(Manager *m) { return 0; } -int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - _cleanup_free_ char *buf = NULL; - Link *link = NULL; - uint16_t type; - unsigned char flags, prefixlen, scope; - union in_addr_union in_addr = IN_ADDR_NULL; - struct ifa_cacheinfo cinfo; - Address *address = NULL; - char valid_buf[FORMAT_TIMESPAN_MAX]; - const char *valid_str = NULL; - int ifindex, family, r; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_message_warning_errno(message, r, "rtnl: failed to receive address message, ignoring"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); - return 0; - } else if (!IN_SET(type, RTM_NEWADDR, RTM_DELADDR)) { - log_warning("rtnl: received unexpected message type %u when processing address, ignoring.", type); - return 0; - } - - r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received address message with invalid ifindex %d, ignoring.", ifindex); - return 0; - } - - r = link_get(m, ifindex, &link); - if (r < 0 || !link) { - /* when enumerating we might be out of sync, but we will get the address again, so just - * ignore it */ - if (!m->enumerating) - log_warning("rtnl: received address for link '%d' we don't know about, ignoring.", ifindex); - return 0; - } - - r = sd_rtnl_message_addr_get_family(message, &family); - if (r < 0) { - log_link_warning(link, "rtnl: received address message without family, ignoring."); - return 0; - } else if (!IN_SET(family, AF_INET, AF_INET6)) { - log_link_debug(link, "rtnl: received address message with invalid family '%i', ignoring.", family); - return 0; - } - - r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid prefixlen, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_addr_get_scope(message, &scope); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid scope, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_addr_get_flags(message, &flags); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m"); - return 0; - } - - switch (family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); - return 0; - } - - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); - return 0; - } - - break; - - default: - assert_not_reached("Received unsupported address family"); - } - - r = in_addr_to_string(family, &in_addr, &buf); - if (r < 0) - log_link_warning_errno(link, r, "Could not print address: %m"); - - r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m"); - return 0; - } else if (r >= 0 && cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME) - valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, - cinfo.ifa_valid * USEC_PER_SEC, - USEC_PER_SEC); - - (void) address_get(link, family, &in_addr, prefixlen, &address); - - switch (type) { - case RTM_NEWADDR: - if (address) - log_link_debug(link, "Remembering updated address: %s/%u (valid %s%s)", - strnull(buf), prefixlen, - valid_str ? "for " : "forever", strempty(valid_str)); - else { - /* An address appeared that we did not request */ - r = address_add_foreign(link, family, &in_addr, prefixlen, &address); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to remember foreign address %s/%u, ignoring: %m", - strnull(buf), prefixlen); - return 0; - } else - log_link_debug(link, "Remembering foreign address: %s/%u (valid %s%s)", - strnull(buf), prefixlen, - valid_str ? "for " : "forever", strempty(valid_str)); - } - - /* address_update() logs internally, so we don't need to here. */ - r = address_update(address, flags, scope, &cinfo); - if (r < 0) - link_enter_failed(link); - - break; - - case RTM_DELADDR: - if (address) { - log_link_debug(link, "Forgetting address: %s/%u (valid %s%s)", - strnull(buf), prefixlen, - valid_str ? "for " : "forever", strempty(valid_str)); - (void) address_drop(address); - } else - log_link_debug(link, "Kernel removed an address we don't remember: %s/%u (valid %s%s), ignoring.", - strnull(buf), prefixlen, - valid_str ? "for " : "forever", strempty(valid_str)); - - break; - - default: - assert_not_reached("Received invalid RTNL message type"); - } - - return 1; -} - static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { Link *link = NULL; NetDev *netdev = NULL; diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 602ae919e9..f95367660a 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -84,8 +84,6 @@ bool manager_should_reload(Manager *m); int manager_enumerate(Manager *m); -int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); - void manager_dirty(Manager *m); int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found); From 9a0ad16b26cf5feff628ff35be49ec307c05a78b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 7 Oct 2020 02:49:11 +0900 Subject: [PATCH 086/138] network: update log messages And drop unnecessary log for in_addr_to_string(), as its result is used only for the consequent logs. --- src/network/networkd-address.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 9ec8d4af1f..14a2026e3f 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1119,19 +1119,19 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen); if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid prefixlen, ignoring: %m"); + log_link_warning_errno(link, r, "rtnl: received address message without prefixlen, ignoring: %m"); return 0; } r = sd_rtnl_message_addr_get_scope(message, &scope); if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid scope, ignoring: %m"); + log_link_warning_errno(link, r, "rtnl: received address message without scope, ignoring: %m"); return 0; } r = sd_rtnl_message_addr_get_flags(message, &flags); if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m"); + log_link_warning_errno(link, r, "rtnl: received address message without flags, ignoring: %m"); return 0; } @@ -1158,9 +1158,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, assert_not_reached("Received unsupported address family"); } - r = in_addr_to_string(family, &in_addr, &buf); - if (r < 0) - log_link_warning_errno(link, r, "Could not print address: %m"); + (void) in_addr_to_string(family, &in_addr, &buf); r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); if (r < 0 && r != -ENODATA) { From 32400c2ff07bd93f329307346f6d55f0b882a2ce Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 11:35:44 +0900 Subject: [PATCH 087/138] network: introduce network_verify_addresses() --- src/network/networkd-address.c | 12 +++++++++++- src/network/networkd-address.h | 3 ++- src/network/networkd-network.c | 8 +++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 14a2026e3f..c6101b1cfc 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1685,7 +1685,7 @@ bool address_is_ready(const Address *a) { return !(a->flags & IFA_F_TENTATIVE); } -int address_section_verify(Address *address) { +static int address_section_verify(Address *address) { if (section_is_invalid(address->section)) return -EINVAL; @@ -1703,3 +1703,13 @@ int address_section_verify(Address *address) { return 0; } + +void network_verify_addresses(Network *network) { + Address *address, *address_next; + + assert(network); + + LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses) + if (address_section_verify(address) < 0) + address_free(address); +} diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 5b565b6e55..d3e0640c4a 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -68,7 +68,6 @@ int address_configure(Address *address, Link *link, link_netlink_message_handler int address_remove(Address *address, Link *link, link_netlink_message_handler_t callback); bool address_equal(Address *a1, Address *a2); bool address_is_ready(const Address *a); -int address_section_verify(Address *a); int configure_ipv4_duplicate_address_detection(Link *link, Address *address); int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret); @@ -81,6 +80,8 @@ int link_drop_foreign_addresses(Link *link); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); +void network_verify_addresses(Network *network); + void address_hash_func(const Address *a, struct siphash *state); int address_compare_func(const Address *a1, const Address *a2); extern const struct hash_ops address_hash_ops; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index aa9a3346dc..79ae2899d3 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -155,7 +155,6 @@ static int network_resolve_stacked_netdevs(Network *network) { } int network_verify(Network *network) { - Address *address, *address_next; TrafficControl *tc; SRIOV *sr_iov; @@ -212,6 +211,8 @@ int network_verify(Network *network) { network->dhcp_server = false; } if (network->n_static_addresses > 0) { + Address *address; + log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.", network->filename); while ((address = network->static_addresses)) @@ -291,10 +292,7 @@ int network_verify(Network *network) { network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses); } - LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses) - if (address_section_verify(address) < 0) - address_free(address); - + network_verify_addresses(network); network_verify_routes(network); network_verify_nexthops(network); network_verify_fdb_entries(network); From 3b31e2b71891444bb92705c0f287e83aa6c8f792 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 11:40:37 +0900 Subject: [PATCH 088/138] network: introduce link_serialize_addresses() --- src/network/networkd-address.c | 21 +++++++++++++++++++++ src/network/networkd-address.h | 1 + src/network/networkd-link.c | 17 +++-------------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index c6101b1cfc..4100e92ae0 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1217,6 +1217,27 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, return 1; } +int link_serialize_addresses(Link *link, FILE *f) { + bool space = false; + Address *a; + + assert(link); + + fputs("ADDRESSES=", f); + SET_FOREACH(a, link->addresses) { + _cleanup_free_ char *address_str = NULL; + + if (in_addr_to_string(a->family, &a->in_addr, &address_str) < 0) + continue; + + fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen); + space = true; + } + fputc('\n', f); + + return 0; +} + static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { _cleanup_free_ char *pretty = NULL; Address *address; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index d3e0640c4a..0eb8f298dc 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -77,6 +77,7 @@ DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free); int link_set_addresses(Link *link); int link_drop_addresses(Link *link); int link_drop_foreign_addresses(Link *link); +int link_serialize_addresses(Link *link, FILE *f); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index f2314e65f2..cfc6d188e9 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3707,7 +3707,6 @@ int link_save(Link *link) { const char *admin_state, *oper_state, *carrier_state, *address_state; _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; - Address *a; int r; assert(link); @@ -3925,19 +3924,9 @@ int link_save(Link *link) { /************************************************************/ - fputs("ADDRESSES=", f); - space = false; - SET_FOREACH(a, link->addresses) { - _cleanup_free_ char *address_str = NULL; - - r = in_addr_to_string(a->family, &a->in_addr, &address_str); - if (r < 0) - goto fail; - - fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen); - space = true; - } - fputc('\n', f); + r = link_serialize_addresses(link, f); + if (r < 0) + goto fail; /************************************************************/ From da4d3a612d8c39628dd46fc42bc47b7315f8f0c5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 11:52:21 +0900 Subject: [PATCH 089/138] network: introduce link_deserialize_addresses() --- src/network/networkd-address.c | 45 ++++++++++++++++++++++++++++++++++ src/network/networkd-address.h | 1 + src/network/networkd-link.c | 38 +++------------------------- 3 files changed, 49 insertions(+), 35 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 4100e92ae0..4dc967b435 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1238,6 +1238,51 @@ int link_serialize_addresses(Link *link, FILE *f) { return 0; } +int link_deserialize_addresses(Link *link, const char *addresses) { + int r; + + assert(link); + + for (const char *p = addresses;; ) { + _cleanup_free_ char *address_str = NULL; + union in_addr_union address; + unsigned char prefixlen; + char *prefixlen_str; + int family; + + r = extract_first_word(&p, &address_str, NULL, 0); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to parse ADDRESSES=: %m"); + if (r == 0) + return 0; + + prefixlen_str = strchr(address_str, '/'); + if (!prefixlen_str) { + log_link_debug(link, "Failed to parse address and prefix length, ignoring: %s", address_str); + continue; + } + *prefixlen_str++ = '\0'; + + r = sscanf(prefixlen_str, "%hhu", &prefixlen); + if (r != 1) { + log_link_debug(link, "Failed to parse prefixlen: %s", prefixlen_str); + continue; + } + + r = in_addr_from_string_auto(address_str, &family, &address); + if (r < 0) { + log_link_debug_errno(link, r, "Failed to parse address: %s", address_str); + continue; + } + + r = address_add(link, family, &address, prefixlen, NULL); + if (r < 0) + log_link_debug_errno(link, r, "Failed to add address: %m"); + } + + return 0; +} + static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { _cleanup_free_ char *pretty = NULL; Address *address; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 0eb8f298dc..52774d48aa 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -78,6 +78,7 @@ int link_set_addresses(Link *link); int link_drop_addresses(Link *link); int link_drop_foreign_addresses(Link *link); int link_serialize_addresses(Link *link, FILE *f); +int link_deserialize_addresses(Link *link, const char *addresses); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index cfc6d188e9..f21be25209 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3087,41 +3087,9 @@ static int link_load(Link *link) { network_file_fail: - for (const char *p = addresses; p; ) { - _cleanup_free_ char *address_str = NULL; - char *prefixlen_str; - int family; - unsigned char prefixlen; - - r = extract_first_word(&p, &address_str, NULL, 0); - if (r < 0) - log_link_warning_errno(link, r, "failed to parse ADDRESSES: %m"); - if (r <= 0) - break; - - prefixlen_str = strchr(address_str, '/'); - if (!prefixlen_str) { - log_link_debug(link, "Failed to parse address and prefix length %s", address_str); - continue; - } - *prefixlen_str++ = '\0'; - - r = sscanf(prefixlen_str, "%hhu", &prefixlen); - if (r != 1) { - log_link_error(link, "Failed to parse prefixlen %s", prefixlen_str); - continue; - } - - r = in_addr_from_string_auto(address_str, &family, &address); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to parse address %s: %m", address_str); - continue; - } - - r = address_add(link, family, &address, prefixlen, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Failed to add address: %m"); - } + r = link_deserialize_addresses(link, addresses); + if (r < 0) + log_link_warning_errno(link, r, "Failed to load addresses from %s, ignoring: %m", link->state_file); r = link_deserialize_routes(link, routes); if (r < 0) From b87d6a828454601b103f53d70c7513209f3f18ae Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 12:05:20 +0900 Subject: [PATCH 090/138] network: move link_configure_ipv4_dad() --- src/network/networkd-address.c | 20 +++++++++++++++++++- src/network/networkd-address.h | 2 +- src/network/networkd-link.c | 18 ------------------ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 4dc967b435..5fa3bf50c8 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1324,7 +1324,7 @@ static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { return; } -int configure_ipv4_duplicate_address_detection(Link *link, Address *address) { +static int ipv4_dad_configure(Link *link, Address *address) { int r; assert(link); @@ -1361,6 +1361,24 @@ int configure_ipv4_duplicate_address_detection(Link *link, Address *address) { return 0; } +int link_configure_ipv4_dad(Link *link) { + Address *address; + int r; + + assert(link); + assert(link->network); + + LIST_FOREACH(addresses, address, link->network->static_addresses) + if (address->family == AF_INET && + FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) { + r = ipv4_dad_configure(link, address); + if (r < 0) + return log_link_error_errno(link, r, "Failed to configure IPv4ACD: %m"); + } + + return 0; +} + int config_parse_broadcast( const char *unit, const char *filename, diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 52774d48aa..658ef1baca 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -68,7 +68,6 @@ int address_configure(Address *address, Link *link, link_netlink_message_handler int address_remove(Address *address, Link *link, link_netlink_message_handler_t callback); bool address_equal(Address *a1, Address *a2); bool address_is_ready(const Address *a); -int configure_ipv4_duplicate_address_detection(Link *link, Address *address); int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret); @@ -79,6 +78,7 @@ int link_drop_addresses(Link *link); int link_drop_foreign_addresses(Link *link); int link_serialize_addresses(Link *link, FILE *f); int link_deserialize_addresses(Link *link, const char *addresses); +int link_configure_ipv4_dad(Link *link); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index f21be25209..2896a1bada 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2404,24 +2404,6 @@ static int link_drop_config(Link *link) { return 0; } -static int link_configure_ipv4_dad(Link *link) { - Address *address; - int r; - - assert(link); - assert(link->network); - - LIST_FOREACH(addresses, address, link->network->static_addresses) - if (address->family == AF_INET && - FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) { - r = configure_ipv4_duplicate_address_detection(link, address); - if (r < 0) - return log_link_error_errno(link, r, "Failed to configure IPv4ACD: %m"); - } - - return 0; -} - static int link_configure_traffic_control(Link *link) { TrafficControl *tc; int r; From 2488e4d934ddc7ea2c8a743ab7a93ad88ee34fe5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 12:12:25 +0900 Subject: [PATCH 091/138] network: introduce link_stop_ipv4_dad() --- src/network/networkd-address.c | 21 +++++++++++++++++++++ src/network/networkd-address.h | 1 + src/network/networkd-link.c | 11 +++-------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 5fa3bf50c8..3f985c849f 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1379,6 +1379,27 @@ int link_configure_ipv4_dad(Link *link) { return 0; } +int link_stop_ipv4_dad(Link *link) { + Address *address; + int k, r = 0; + + assert(link); + + if (!link->network) + return 0; + + LIST_FOREACH(addresses, address, link->network->static_addresses) { + if (!address->acd) + continue; + + k = sd_ipv4acd_stop(address->acd); + if (k < 0 && r >= 0) + r = k; + } + + return r; +} + int config_parse_broadcast( const char *unit, const char *filename, diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 658ef1baca..a78fadc885 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -79,6 +79,7 @@ int link_drop_foreign_addresses(Link *link); int link_serialize_addresses(Link *link, FILE *f); int link_deserialize_addresses(Link *link, const char *addresses); int link_configure_ipv4_dad(Link *link); +int link_stop_ipv4_dad(Link *link); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 2896a1bada..dc6960b00b 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -813,7 +813,6 @@ static void link_enter_unmanaged(Link *link) { int link_stop_clients(Link *link, bool may_keep_dhcp) { int r = 0, k; - Address *ad; assert(link); assert(link->manager); @@ -836,13 +835,9 @@ int link_stop_clients(Link *link, bool may_keep_dhcp) { r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m"); } - if (link->network) - LIST_FOREACH(addresses, ad, link->network->static_addresses) - if (ad->acd && sd_ipv4acd_is_running(ad->acd) == 0) { - k = sd_ipv4acd_stop(ad->acd); - if (k < 0) - r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client: %m"); - } + k = link_stop_ipv4_dad(link); + if (k < 0) + r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client: %m"); if (link->dhcp6_client) { k = sd_dhcp6_client_stop(link->dhcp6_client); From 7818f8589adf34101e70ad7340acd03baa4a4def Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 12:18:37 +0900 Subject: [PATCH 092/138] network: make address_free() return NULL --- src/network/networkd-address.c | 6 +++--- src/network/networkd-address.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 3f985c849f..d14da8195e 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -110,9 +110,9 @@ static int address_new_static(Network *network, const char *filename, unsigned s return 0; } -void address_free(Address *address) { +Address *address_free(Address *address) { if (!address) - return; + return NULL; if (address->network) { LIST_REMOVE(addresses, address->network->static_addresses, address); @@ -149,7 +149,7 @@ void address_free(Address *address) { network_config_section_free(address->section); free(address->label); - free(address); + return mfree(address); } static uint32_t address_prefix(const Address *a) { diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index a78fadc885..097cafc315 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -57,7 +57,7 @@ struct Address { }; int address_new(Address **ret); -void address_free(Address *address); +Address *address_free(Address *address); int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); From 9cd9fc8f447329281d6d1614e1a86011c8cbec5c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 12:34:19 +0900 Subject: [PATCH 093/138] network: drop list of static addresses [Address] sections are managed by both LIST and Hashmap. Let's drop the list and manage them by OrderedHashmap. --- src/network/networkd-address-pool.c | 2 +- src/network/networkd-address.c | 71 ++++++++++++----------------- src/network/networkd-dhcp-server.c | 2 +- src/network/networkd-network.c | 18 ++------ src/network/networkd-network.h | 6 +-- src/network/networkd-route.c | 2 +- src/network/test-networkd-conf.c | 14 +++--- 7 files changed, 46 insertions(+), 69 deletions(-) diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index b4a94f0728..e867323dbb 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -107,7 +107,7 @@ static bool address_pool_prefix_is_taken( ORDERED_HASHMAP_FOREACH(n, p->manager->networks) { Address *a; - LIST_FOREACH(addresses, a, n->static_addresses) { + ORDERED_HASHMAP_FOREACH(a, n->addresses_by_section) { if (a->family != p->family) continue; diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index d14da8195e..d2c08a0f32 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -67,22 +67,20 @@ static int address_new_static(Network *network, const char *filename, unsigned s assert(network); assert(ret); - assert(!!filename == (section_line > 0)); + assert(filename); + assert(section_line > 0); - if (filename) { - r = network_config_section_new(filename, section_line, &n); - if (r < 0) - return r; + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; - address = hashmap_get(network->addresses_by_section, n); - if (address) { - *ret = TAKE_PTR(address); - - return 0; - } + address = ordered_hashmap_get(network->addresses_by_section, n); + if (address) { + *ret = TAKE_PTR(address); + return 0; } - if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX) + if (ordered_hashmap_size(network->addresses_by_section) >= STATIC_ADDRESSES_PER_NETWORK_MAX) return -E2BIG; r = address_new(&address); @@ -90,23 +88,17 @@ static int address_new_static(Network *network, const char *filename, unsigned s return r; address->network = network; - LIST_APPEND(addresses, network->static_addresses, address); - network->n_static_addresses++; + address->section = TAKE_PTR(n); - if (filename) { - address->section = TAKE_PTR(n); + r = ordered_hashmap_ensure_allocated(&network->addresses_by_section, &network_config_hash_ops); + if (r < 0) + return r; - r = hashmap_ensure_allocated(&network->addresses_by_section, &network_config_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(network->addresses_by_section, address->section, address); - if (r < 0) - return r; - } + r = ordered_hashmap_put(network->addresses_by_section, address->section, address); + if (r < 0) + return r; *ret = TAKE_PTR(address); - return 0; } @@ -115,12 +107,8 @@ Address *address_free(Address *address) { return NULL; if (address->network) { - LIST_REMOVE(addresses, address->network->static_addresses, address); - assert(address->network->n_static_addresses > 0); - address->network->n_static_addresses--; - - if (address->section) - hashmap_remove(address->network->addresses_by_section, address->section); + assert(address->section); + ordered_hashmap_remove(address->network->addresses_by_section, address->section); } if (address->link && !address->acd) { @@ -551,7 +539,7 @@ static bool link_is_static_address_configured(Link *link, Address *address) { if (!link->network) return false; - LIST_FOREACH(addresses, net_address, link->network->static_addresses) + ORDERED_HASHMAP_FOREACH(net_address, link->network->addresses_by_section) if (address_equal(net_address, address)) return true; else if (address->family == AF_INET6 && net_address->family == AF_INET6 && @@ -1002,7 +990,7 @@ int link_set_addresses(Link *link) { return 0; } - LIST_FOREACH(addresses, ad, link->network->static_addresses) { + ORDERED_HASHMAP_FOREACH(ad, link->network->addresses_by_section) { bool update; if (ad->family == AF_INET6 && !in_addr_is_null(ad->family, &ad->in_addr_peer)) @@ -1368,7 +1356,7 @@ int link_configure_ipv4_dad(Link *link) { assert(link); assert(link->network); - LIST_FOREACH(addresses, address, link->network->static_addresses) + ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section) if (address->family == AF_INET && FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) { r = ipv4_dad_configure(link, address); @@ -1388,7 +1376,7 @@ int link_stop_ipv4_dad(Link *link) { if (!link->network) return 0; - LIST_FOREACH(addresses, address, link->network->static_addresses) { + ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section) { if (!address->acd) continue; @@ -1473,11 +1461,10 @@ int config_parse_address(const char *unit, assert(rvalue); assert(data); - if (streq(section, "Network")) { - /* we are not in an Address section, so treat - * this as the special '0' section */ - r = address_new_static(network, NULL, 0, &n); - } else + if (streq(section, "Network")) + /* we are not in an Address section, so use line number instead. */ + r = address_new_static(network, filename, line, &n); + else r = address_new_static(network, filename, section_line, &n); if (r == -ENOMEM) return log_oom(); @@ -1810,11 +1797,11 @@ static int address_section_verify(Address *address) { } void network_verify_addresses(Network *network) { - Address *address, *address_next; + Address *address; assert(network); - LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses) + ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section) if (address_section_verify(address) < 0) address_free(address); } diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 890d9b55a1..ddc58cb9c0 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -21,7 +21,7 @@ static Address* link_find_dhcp_server_address(Link *link) { assert(link->network); /* The first statically configured address if there is any */ - LIST_FOREACH(addresses, address, link->network->static_addresses) + ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section) if (address->family == AF_INET && !in_addr_is_null(address->family, &address->in_addr)) return address; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 79ae2899d3..c1c1ff502e 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -210,17 +210,14 @@ int network_verify(Network *network) { network->filename); network->dhcp_server = false; } - if (network->n_static_addresses > 0) { - Address *address; - + if (!ordered_hashmap_isempty(network->addresses_by_section)) log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.", network->filename); - while ((address = network->static_addresses)) - address_free(address); - } if (!hashmap_isempty(network->routes_by_section)) log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.", network->filename); + + network->addresses_by_section = ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free); network->routes_by_section = hashmap_free_with_destructor(network->routes_by_section, route_free); } @@ -617,8 +614,6 @@ failure: } static Network *network_free(Network *network) { - Address *address; - if (!network) return NULL; @@ -674,11 +669,8 @@ static Network *network_free(Network *network) { netdev_unref(network->vrf); hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref); - while ((address = network->static_addresses)) - address_free(address); - set_free_free(network->ipv6_proxy_ndp_addresses); - hashmap_free(network->addresses_by_section); + ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free); hashmap_free_with_destructor(network->routes_by_section, route_free); hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free); hashmap_free_with_destructor(network->fdb_entries_by_section, fdb_entry_free); @@ -800,7 +792,7 @@ bool network_has_static_ipv6_configurations(Network *network) { assert(network); - LIST_FOREACH(addresses, address, network->static_addresses) + ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section) if (address->family == AF_INET6) return true; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index c56c24656a..f6ebda4a14 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -278,11 +278,7 @@ struct Network { LLDPEmit lldp_emit; /* LLDP transmission */ char *lldp_mud; /* LLDP MUD URL */ - LIST_HEAD(Address, static_addresses); - - unsigned n_static_addresses; - - Hashmap *addresses_by_section; + OrderedHashmap *addresses_by_section; Hashmap *routes_by_section; Hashmap *nexthops_by_section; Hashmap *fdb_entries_by_section; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index e59f634fb1..3d25f6f489 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -2182,7 +2182,7 @@ static int route_section_verify(Route *route, Network *network) { route->scope = RT_SCOPE_LINK; } - if (network->n_static_addresses == 0 && + if (ordered_hashmap_isempty(network->addresses_by_section) && in_addr_is_null(route->family, &route->gw) == 0 && route->gateway_onlink < 0) { log_warning("%s: Gateway= without static address configured. " diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c index 5d338e6f1a..030e50688a 100644 --- a/src/network/test-networkd-conf.c +++ b/src/network/test-networkd-conf.c @@ -176,14 +176,16 @@ static void test_config_parse_address_one(const char *rvalue, int family, unsign assert_se(network->filename = strdup("hogehoge.network")); assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0); assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0); - assert_se(network->n_static_addresses == 1); + assert_se(ordered_hashmap_size(network->addresses_by_section) == 1); assert_se(network_verify(network) >= 0); - assert_se(network->n_static_addresses == n_addresses); + assert_se(ordered_hashmap_size(network->addresses_by_section) == n_addresses); if (n_addresses > 0) { - assert_se(network->static_addresses); - assert_se(network->static_addresses->prefixlen == prefixlen); - assert_se(network->static_addresses->family == family); - assert_se(in_addr_equal(family, &network->static_addresses->in_addr, u)); + Address *a; + + assert_se(a = ordered_hashmap_first(network->addresses_by_section)); + assert_se(a->prefixlen == prefixlen); + assert_se(a->family == family); + assert_se(in_addr_equal(family, &a->in_addr, u)); /* TODO: check Address.in_addr and Address.broadcast */ } } From aa651e88dea18cfb217da300f03eea08c8c594f2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 13:39:02 +0900 Subject: [PATCH 094/138] network: manage addresses from pool by Set --- src/network/networkd-address-pool.c | 2 +- src/network/networkd-address.c | 31 +++++++++++++++++------------ src/network/networkd-address.h | 2 -- src/network/networkd-dhcp-server.c | 2 +- src/network/networkd-link.c | 8 +------- src/network/networkd-link.h | 3 +-- 6 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index e867323dbb..5f5a170718 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -94,7 +94,7 @@ static bool address_pool_prefix_is_taken( } /* Don't clash with addresses already pulled from the pool, but not assigned yet */ - LIST_FOREACH(addresses, a, l->pool_addresses) { + SET_FOREACH(a, l->pool_addresses) { if (a->family != p->family) continue; diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index d2c08a0f32..1502251fc4 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -657,13 +657,9 @@ int link_drop_addresses(Link *link) { link->address_remove_messages++; - /* If this address came from an address pool, clean up the pool */ - LIST_FOREACH(addresses, pool_address, link->pool_addresses) - if (address_equal(address, pool_address)) { - LIST_REMOVE(addresses, link->pool_addresses, pool_address); - address_free(pool_address); - break; - } + SET_FOREACH(pool_address, link->pool_addresses) + if (address_equal(address, pool_address)) + address_free(set_remove(link->pool_addresses, pool_address)); } return r; @@ -681,8 +677,12 @@ static int address_acquire(Link *link, Address *original, Address **ret) { /* Something useful was configured? just use it */ r = in_addr_is_null(original->family, &original->in_addr); - if (r <= 0) + if (r < 0) return r; + if (r == 0) { + *ret = NULL; + return 0; + } /* The address is configured to be 0.0.0.0 or [::] by the user? * Then let's acquire something more useful from the pool. */ @@ -722,11 +722,14 @@ static int address_acquire(Link *link, Address *original, Address **ret) { na->broadcast = broadcast; na->in_addr = in_addr; - LIST_PREPEND(addresses, link->pool_addresses, na); + r = set_ensure_put(&link->pool_addresses, &address_hash_ops, na); + if (r < 0) + return r; + if (r == 0) + return -EEXIST; *ret = TAKE_PTR(na); - - return 0; + return 1; } int address_configure( @@ -737,7 +740,7 @@ int address_configure( Address **ret) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - Address *a; + Address *acquired_address, *a; int r; assert(address); @@ -754,9 +757,11 @@ int address_configure( return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG), "Too many addresses are configured, refusing: %m"); - r = address_acquire(link, address, &address); + r = address_acquire(link, address, &acquired_address); if (r < 0) return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m"); + if (acquired_address) + address = acquired_address; if (DEBUG_LOGGING) { _cleanup_free_ char *str = NULL; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 097cafc315..5b930314c0 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -52,8 +52,6 @@ struct Address { address_ready_callback_t callback; sd_ipv4acd *acd; - - LIST_FIELDS(Address, addresses); }; int address_new(Address **ret); diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index ddc58cb9c0..9195f0680f 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -27,7 +27,7 @@ static Address* link_find_dhcp_server_address(Link *link) { return address; /* If that didn't work, find a suitable address we got from the pool */ - LIST_FOREACH(addresses, address, link->pool_addresses) + SET_FOREACH(address, link->pool_addresses) if (address->family == AF_INET) return address; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index dc6960b00b..ef3a20befb 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -707,8 +707,6 @@ static void link_free_engines(Link *link) { } static Link *link_free(Link *link) { - Address *address; - assert(link); link_ntp_settings_clear(link); @@ -732,6 +730,7 @@ static Link *link_free(Link *link) { link->addresses = set_free(link->addresses); link->addresses_foreign = set_free(link->addresses_foreign); + link->pool_addresses = set_free(link->pool_addresses); link->static_addresses = set_free(link->static_addresses); link->dhcp6_addresses = set_free(link->dhcp6_addresses); link->dhcp6_addresses_old = set_free(link->dhcp6_addresses_old); @@ -739,11 +738,6 @@ static Link *link_free(Link *link) { link->dhcp6_pd_addresses_old = set_free(link->dhcp6_pd_addresses_old); link->ndisc_addresses = set_free(link->ndisc_addresses); - while ((address = link->pool_addresses)) { - LIST_REMOVE(addresses, link->pool_addresses, address); - address_free(address); - } - link_lldp_emit_stop(link); link_free_engines(link); free(link->lease_file); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 670ae9783d..361646ec4d 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -89,6 +89,7 @@ typedef struct Link { Set *addresses; Set *addresses_foreign; + Set *pool_addresses; Set *static_addresses; Set *neighbors; Set *neighbors_foreign; @@ -127,8 +128,6 @@ typedef struct Link { bool ipv6_mtu_set:1; bool bridge_mdb_configured:1; - LIST_HEAD(Address, pool_addresses); - sd_dhcp_server *dhcp_server; sd_ndisc *ndisc; From 67a58eb37880f9310b200cb6f786dd5e59236739 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 13:50:36 +0900 Subject: [PATCH 095/138] network: make several functions static --- src/network/networkd-address.c | 8 ++++---- src/network/networkd-address.h | 4 ---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 1502251fc4..d82d54d418 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -283,11 +283,11 @@ static int address_add_internal(Link *link, Set **addresses, return 0; } -int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { +static int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { return address_add_internal(link, &link->addresses_foreign, family, in_addr, prefixlen, ret); } -int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { +static int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { Address *address; int r; @@ -337,7 +337,7 @@ static int address_release(Address *address) { return 0; } -int address_update( +static int address_update( Address *address, unsigned char flags, unsigned char scope, @@ -382,7 +382,7 @@ int address_update( return 0; } -int address_drop(Address *address) { +static int address_drop(Address *address) { Link *link; bool ready; int r; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 5b930314c0..b936e3e87a 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -56,12 +56,8 @@ struct Address { int address_new(Address **ret); Address *address_free(Address *address); -int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); -int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); bool address_exists(Link *link, int family, const union in_addr_union *in_addr); -int address_update(Address *address, unsigned char flags, unsigned char scope, const struct ifa_cacheinfo *cinfo); -int address_drop(Address *address); int address_configure(Address *address, Link *link, link_netlink_message_handler_t callback, bool update, Address **ret); int address_remove(Address *address, Link *link, link_netlink_message_handler_t callback); bool address_equal(Address *a1, Address *a2); From 093e35334dbc8b17a6a64151699ad21c30d1f9df Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 14:01:59 +0900 Subject: [PATCH 096/138] network: header cleanup --- src/network/netdev/macsec.c | 1 - src/network/networkd-address-pool.c | 1 + src/network/networkd-address.c | 7 +------ src/network/networkd-address.h | 22 +++++++++------------- src/network/networkd-dhcp-server.c | 1 + src/network/networkd-dhcp4.c | 1 + src/network/networkd-dhcp6.c | 1 + src/network/networkd-link.c | 1 + src/network/networkd-link.h | 1 - src/network/networkd-ndisc.c | 1 + src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 - 13 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/network/netdev/macsec.c b/src/network/netdev/macsec.c index 9d3b8d6e4c..9f0e6f25c1 100644 --- a/src/network/netdev/macsec.c +++ b/src/network/netdev/macsec.c @@ -13,7 +13,6 @@ #include "memory-util.h" #include "netlink-util.h" #include "network-internal.h" -#include "networkd-address.h" #include "networkd-manager.h" #include "path-util.h" #include "socket-util.h" diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index 5f5a170718..24a6bff2a1 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -2,6 +2,7 @@ #include "alloc-util.h" #include "networkd-address-pool.h" +#include "networkd-address.h" #include "networkd-manager.h" #include "set.h" #include "string-util.h" diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index d82d54d418..170adfbbf6 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -3,20 +3,15 @@ #include #include "alloc-util.h" -#include "conf-parser.h" #include "firewall-util.h" #include "memory-util.h" -#include "missing_network.h" #include "netlink-util.h" #include "networkd-address.h" #include "networkd-manager.h" -#include "networkd-ndisc.h" +#include "networkd-network.h" #include "parse-util.h" -#include "set.h" -#include "socket-util.h" #include "string-util.h" #include "strv.h" -#include "utf8.h" #define ADDRESSES_PER_LINK_MAX 2048U #define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index b936e3e87a..ec1f51927e 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -3,26 +3,22 @@ #include #include - -#include "conf-parser.h" -#include "in-addr-util.h" - -typedef struct Address Address; - -#include "networkd-link.h" -#include "networkd-network.h" -#include "networkd-util.h" +#include #include "sd-ipv4acd.h" +#include "conf-parser.h" +#include "in-addr-util.h" +#include "networkd-link.h" +#include "networkd-util.h" + #define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU +typedef struct Manager Manager; typedef struct Network Network; -typedef struct Link Link; -typedef struct NetworkConfigSection NetworkConfigSection; typedef int (*address_ready_callback_t)(Address *address); -struct Address { +typedef struct Address { Network *network; NetworkConfigSection *section; @@ -52,7 +48,7 @@ struct Address { address_ready_callback_t callback; sd_ipv4acd *acd; -}; +} Address; int address_new(Address **ret); Address *address_free(Address *address); diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 9195f0680f..a0ef756df8 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -4,6 +4,7 @@ #include "fd-util.h" #include "fileio.h" +#include "networkd-address.h" #include "networkd-dhcp-server.h" #include "networkd-link.h" #include "networkd-manager.h" diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 18ce0c61bb..59c68744c0 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -11,6 +11,7 @@ #include "hostname-util.h" #include "parse-util.h" #include "network-internal.h" +#include "networkd-address.h" #include "networkd-dhcp4.h" #include "networkd-link.h" #include "networkd-manager.h" diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index f0642c9f72..4b99c5f308 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -14,6 +14,7 @@ #include "hostname-util.h" #include "missing_network.h" #include "network-internal.h" +#include "networkd-address.h" #include "networkd-dhcp6.h" #include "networkd-link.h" #include "networkd-manager.h" diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index ef3a20befb..0083959591 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -21,6 +21,7 @@ #include "netlink-util.h" #include "network-internal.h" #include "networkd-address-label.h" +#include "networkd-address.h" #include "networkd-can.h" #include "networkd-dhcp-server.h" #include "networkd-dhcp4.h" diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 361646ec4d..510d3f8c03 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -15,7 +15,6 @@ #include "sd-radv.h" #include "sd-netlink.h" -#include "list.h" #include "log-link.h" #include "network-util.h" #include "networkd-util.h" diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 545574e126..6a21f12907 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -9,6 +9,7 @@ #include "sd-ndisc.h" #include "missing_network.h" +#include "networkd-address.h" #include "networkd-dhcp6.h" #include "networkd-manager.h" #include "networkd-ndisc.h" diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 1d899464d8..a5680adc16 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -7,6 +7,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "netem.h" #include "network-internal.h" #include "networkd-address-label.h" +#include "networkd-address.h" #include "networkd-can.h" #include "networkd-conf.h" #include "networkd-dhcp-common.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c1c1ff502e..3c6f45c61b 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -15,6 +15,7 @@ #include "networkd-dhcp-server.h" #include "network-internal.h" #include "networkd-address-label.h" +#include "networkd-address.h" #include "networkd-fdb.h" #include "networkd-manager.h" #include "networkd-mdb.h" diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index f6ebda4a14..99cce40533 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -12,7 +12,6 @@ #include "conf-parser.h" #include "hashmap.h" #include "netdev.h" -#include "networkd-address.h" #include "networkd-brvlan.h" #include "networkd-dhcp-common.h" #include "networkd-dhcp4.h" From ed76f585217bf544274d350512254d0c2e70d408 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 14:15:57 +0900 Subject: [PATCH 097/138] network: move functions related to address pool --- src/network/networkd-address-pool.c | 52 +++++++++++++++++++++++++++-- src/network/networkd-address-pool.h | 4 +-- src/network/networkd-address.c | 2 +- src/network/networkd-manager.c | 49 +-------------------------- src/network/networkd-manager.h | 2 -- 5 files changed, 54 insertions(+), 55 deletions(-) diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index 24a6bff2a1..12ce45036b 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -39,7 +39,7 @@ static int address_pool_new( return 0; } -int address_pool_new_from_string( +static int address_pool_new_from_string( Manager *m, AddressPool **ret, int family, @@ -71,6 +71,33 @@ void address_pool_free(AddressPool *p) { free(p); } +int address_pool_setup_default(Manager *m) { + AddressPool *p; + int r; + + assert(m); + + /* Add in the well-known private address ranges. */ + + r = address_pool_new_from_string(m, &p, AF_INET6, "fd00::", 8); + if (r < 0) + return r; + + r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8); + if (r < 0) + return r; + + r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12); + if (r < 0) + return r; + + r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16); + if (r < 0) + return r; + + return 0; +} + static bool address_pool_prefix_is_taken( AddressPool *p, const union in_addr_union *u, @@ -120,7 +147,7 @@ static bool address_pool_prefix_is_taken( return false; } -int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) { +static int address_pool_acquire_one(AddressPool *p, int family, unsigned prefixlen, union in_addr_union *found) { union in_addr_union u; unsigned i; int r; @@ -129,6 +156,9 @@ int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union assert(prefixlen > 0); assert(found); + if (p->family != family) + return 0; + if (p->prefixlen >= prefixlen) return 0; @@ -154,3 +184,21 @@ int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union return 0; } + +int address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) { + AddressPool *p; + int r; + + assert(m); + assert(IN_SET(family, AF_INET, AF_INET6)); + assert(prefixlen > 0); + assert(found); + + LIST_FOREACH(address_pools, p, m->address_pools) { + r = address_pool_acquire_one(p, family, prefixlen, found); + if (r != 0) + return r; + } + + return 0; +} diff --git a/src/network/networkd-address-pool.h b/src/network/networkd-address-pool.h index 7db1c4f26c..0c5cd5cedd 100644 --- a/src/network/networkd-address-pool.h +++ b/src/network/networkd-address-pool.h @@ -19,7 +19,7 @@ struct AddressPool { LIST_FIELDS(AddressPool, address_pools); }; -int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen); void address_pool_free(AddressPool *p); -int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found); +int address_pool_setup_default(Manager *m); +int address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 170adfbbf6..0efb3eafb2 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -681,7 +681,7 @@ static int address_acquire(Link *link, Address *original, Address **ret) { /* The address is configured to be 0.0.0.0 or [::] by the user? * Then let's acquire something more useful from the pool. */ - r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr); + r = address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr); if (r < 0) return r; if (r == 0) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 00f172bc90..137424929f 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -48,33 +48,6 @@ /* use 128 MB for receive socket kernel queue. */ #define RCVBUF_SIZE (128*1024*1024) -static int setup_default_address_pool(Manager *m) { - AddressPool *p; - int r; - - assert(m); - - /* Add in the well-known private address ranges. */ - - r = address_pool_new_from_string(m, &p, AF_INET6, "fd00::", 8); - if (r < 0) - return r; - - r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8); - if (r < 0) - return r; - - r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12); - if (r < 0) - return r; - - r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16); - if (r < 0) - return r; - - return 0; -} - static int manager_reset_all(Manager *m) { Link *link; int r; @@ -868,7 +841,7 @@ int manager_new(Manager **ret) { if (r < 0) return r; - r = setup_default_address_pool(m); + r = address_pool_setup_default(m); if (r < 0) return r; @@ -1136,26 +1109,6 @@ int manager_enumerate(Manager *m) { return 0; } -int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) { - AddressPool *p; - int r; - - assert(m); - assert(prefixlen > 0); - assert(found); - - LIST_FOREACH(address_pools, p, m->address_pools) { - if (p->family != family) - continue; - - r = address_pool_acquire(p, prefixlen, found); - if (r != 0) - return r; - } - - return 0; -} - Link* manager_find_uplink(Manager *m, Link *exclude) { _cleanup_free_ struct local_address *gateways = NULL; int n, i; diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index f95367660a..c4e44421e2 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -86,8 +86,6 @@ int manager_enumerate(Manager *m); void manager_dirty(Manager *m); -int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found); - Link* manager_find_uplink(Manager *m, Link *exclude); int manager_set_hostname(Manager *m, const char *hostname); From 3fe721c6742cfcb96e63ff124ba035909cc55fa0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 14:38:22 +0900 Subject: [PATCH 098/138] network: drop unused argument --- src/network/networkd-address-pool.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index 12ce45036b..44fab4dd1b 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -11,7 +11,6 @@ static int address_pool_new( Manager *m, - AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen) { @@ -19,7 +18,6 @@ static int address_pool_new( AddressPool *p; assert(m); - assert(ret); assert(u); p = new(AddressPool, 1); @@ -35,13 +33,11 @@ static int address_pool_new( LIST_PREPEND(address_pools, m->address_pools, p); - *ret = p; return 0; } static int address_pool_new_from_string( Manager *m, - AddressPool **ret, int family, const char *p, unsigned prefixlen) { @@ -50,14 +46,13 @@ static int address_pool_new_from_string( int r; assert(m); - assert(ret); assert(p); r = in_addr_from_string(family, p, &u); if (r < 0) return r; - return address_pool_new(m, ret, family, &u, prefixlen); + return address_pool_new(m, family, &u, prefixlen); } void address_pool_free(AddressPool *p) { @@ -72,26 +67,24 @@ void address_pool_free(AddressPool *p) { } int address_pool_setup_default(Manager *m) { - AddressPool *p; int r; assert(m); /* Add in the well-known private address ranges. */ - - r = address_pool_new_from_string(m, &p, AF_INET6, "fd00::", 8); + r = address_pool_new_from_string(m, AF_INET6, "fd00::", 8); if (r < 0) return r; - r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8); + r = address_pool_new_from_string(m, AF_INET, "10.0.0.0", 8); if (r < 0) return r; - r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12); + r = address_pool_new_from_string(m, AF_INET, "172.16.0.0", 12); if (r < 0) return r; - r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16); + r = address_pool_new_from_string(m, AF_INET, "192.168.0.0", 16); if (r < 0) return r; From bfbf150ee6a985e11bae580f5778ff1b02b17dba Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 14:46:29 +0900 Subject: [PATCH 099/138] network: manage address pools by OrderedSet --- src/network/networkd-address-pool.c | 25 +++++++++---------------- src/network/networkd-address-pool.h | 12 ++---------- src/network/networkd-address.c | 1 + src/network/networkd-manager.c | 5 ++--- src/network/networkd-manager.h | 9 ++++----- 5 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index 44fab4dd1b..c732b6c56e 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -15,7 +15,8 @@ static int address_pool_new( const union in_addr_union *u, unsigned prefixlen) { - AddressPool *p; + _cleanup_free_ AddressPool *p = NULL; + int r; assert(m); assert(u); @@ -31,8 +32,11 @@ static int address_pool_new( .in_addr = *u, }; - LIST_PREPEND(address_pools, m->address_pools, p); + r = ordered_set_ensure_put(&m->address_pools, NULL, p); + if (r < 0) + return r; + TAKE_PTR(p); return 0; } @@ -55,17 +59,6 @@ static int address_pool_new_from_string( return address_pool_new(m, family, &u, prefixlen); } -void address_pool_free(AddressPool *p) { - - if (!p) - return; - - if (p->manager) - LIST_REMOVE(address_pools, p->manager->address_pools, p); - - free(p); -} - int address_pool_setup_default(Manager *m) { int r; @@ -76,7 +69,7 @@ int address_pool_setup_default(Manager *m) { if (r < 0) return r; - r = address_pool_new_from_string(m, AF_INET, "10.0.0.0", 8); + r = address_pool_new_from_string(m, AF_INET, "192.168.0.0", 16); if (r < 0) return r; @@ -84,7 +77,7 @@ int address_pool_setup_default(Manager *m) { if (r < 0) return r; - r = address_pool_new_from_string(m, AF_INET, "192.168.0.0", 16); + r = address_pool_new_from_string(m, AF_INET, "10.0.0.0", 8); if (r < 0) return r; @@ -187,7 +180,7 @@ int address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_ad assert(prefixlen > 0); assert(found); - LIST_FOREACH(address_pools, p, m->address_pools) { + ORDERED_SET_FOREACH(p, m->address_pools) { r = address_pool_acquire_one(p, family, prefixlen, found); if (r != 0) return r; diff --git a/src/network/networkd-address-pool.h b/src/network/networkd-address-pool.h index 0c5cd5cedd..c53fe7407f 100644 --- a/src/network/networkd-address-pool.h +++ b/src/network/networkd-address-pool.h @@ -1,25 +1,17 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -typedef struct AddressPool AddressPool; - #include "in-addr-util.h" -#include "list.h" typedef struct Manager Manager; -struct AddressPool { +typedef struct AddressPool { Manager *manager; int family; unsigned prefixlen; - union in_addr_union in_addr; - - LIST_FIELDS(AddressPool, address_pools); -}; - -void address_pool_free(AddressPool *p); +} AddressPool; int address_pool_setup_default(Manager *m); int address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 0efb3eafb2..82be47aae2 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -6,6 +6,7 @@ #include "firewall-util.h" #include "memory-util.h" #include "netlink-util.h" +#include "networkd-address-pool.h" #include "networkd-address.h" #include "networkd-manager.h" #include "networkd-network.h" diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 137424929f..524dbedb1e 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -24,6 +24,7 @@ #include "local-addresses.h" #include "netlink-util.h" #include "network-internal.h" +#include "networkd-address-pool.h" #include "networkd-dhcp-server-bus.h" #include "networkd-dhcp6.h" #include "networkd-link-bus.h" @@ -855,7 +856,6 @@ int manager_new(Manager **ret) { } void manager_free(Manager *m) { - AddressPool *pool; Link *link; if (!m) @@ -878,8 +878,7 @@ void manager_free(Manager *m) { m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref); - while ((pool = m->address_pools)) - address_pool_free(pool); + ordered_set_free_free(m->address_pools); /* routing_policy_rule_free() access m->rules and m->rules_foreign. * So, it is necessary to set NULL after the sets are freed. */ diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index c4e44421e2..2e250f1509 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -10,12 +10,11 @@ #include "dhcp-identifier.h" #include "hashmap.h" -#include "list.h" -#include "time-util.h" - -#include "networkd-address-pool.h" #include "networkd-link.h" #include "networkd-network.h" +#include "ordered-set.h" +#include "set.h" +#include "time-util.h" struct Manager { sd_netlink *rtnl; @@ -45,7 +44,7 @@ struct Manager { OrderedHashmap *networks; Hashmap *dhcp6_prefixes; Set *dhcp6_pd_prefixes; - LIST_HEAD(AddressPool, address_pools); + OrderedSet *address_pools; usec_t network_dirs_ts_usec; From ac49887e8c61e38a2b0cc0225f1175292b402749 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 15:48:01 +0900 Subject: [PATCH 100/138] network: move link_get_xxx_route_table() --- src/network/networkd-link.c | 18 ------------------ src/network/networkd-link.h | 4 ---- src/network/networkd-route.c | 18 ++++++++++++++++++ src/network/networkd-route.h | 3 +++ 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0083959591..c73389e25c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -54,24 +54,6 @@ #include "util.h" #include "vrf.h" -uint32_t link_get_vrf_table(Link *link) { - return link->network->vrf ? VRF(link->network->vrf)->table : RT_TABLE_MAIN; -} - -uint32_t link_get_dhcp_route_table(Link *link) { - /* When the interface is part of an VRF use the VRFs routing table, unless - * another table is explicitly specified. */ - if (link->network->dhcp_route_table_set) - return link->network->dhcp_route_table; - return link_get_vrf_table(link); -} - -uint32_t link_get_ipv6_accept_ra_route_table(Link *link) { - if (link->network->ipv6_accept_ra_route_table_set) - return link->network->ipv6_accept_ra_route_table; - return link_get_vrf_table(link); -} - DUID* link_get_duid(Link *link) { if (link->network->duid.type != _DUID_TYPE_INVALID) return &link->network->duid; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 510d3f8c03..25c7bd98da 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -236,10 +236,6 @@ int link_stop_clients(Link *link, bool may_keep_dhcp); const char* link_state_to_string(LinkState s) _const_; LinkState link_state_from_string(const char *s) _pure_; -uint32_t link_get_vrf_table(Link *link); -uint32_t link_get_dhcp_route_table(Link *link); -uint32_t link_get_ipv6_accept_ra_route_table(Link *link); - int link_reconfigure(Link *link, bool force); int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 3d25f6f489..c8ae8d5bce 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -21,6 +21,24 @@ #define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U +static uint32_t link_get_vrf_table(Link *link) { + return link->network->vrf ? VRF(link->network->vrf)->table : RT_TABLE_MAIN; +} + +uint32_t link_get_dhcp_route_table(Link *link) { + /* When the interface is part of an VRF use the VRFs routing table, unless + * another table is explicitly specified. */ + if (link->network->dhcp_route_table_set) + return link->network->dhcp_route_table; + return link_get_vrf_table(link); +} + +uint32_t link_get_ipv6_accept_ra_route_table(Link *link) { + if (link->network->ipv6_accept_ra_route_table_set) + return link->network->ipv6_accept_ra_route_table; + return link_get_vrf_table(link); +} + static const char * const route_type_table[__RTN_MAX] = { [RTN_UNICAST] = "unicast", [RTN_LOCAL] = "local", diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index ac545d9b78..ada1059aad 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -82,6 +82,9 @@ int link_drop_foreign_routes(Link *link); int link_serialize_routes(Link *link, FILE *f); int link_deserialize_routes(Link *link, const char *routes); +uint32_t link_get_dhcp_route_table(Link *link); +uint32_t link_get_ipv6_accept_ra_route_table(Link *link); + int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int network_add_ipv4ll_route(Network *network); From 67c311abd3e930e30ff3ff0ef73d159f7360b61f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 16:09:25 +0900 Subject: [PATCH 101/138] network: unify link_dhcp{4,6}_enabled() --- src/network/networkd-dhcp-common.c | 27 +++++++++++++++++++++ src/network/networkd-dhcp-common.h | 10 ++++++++ src/network/networkd-link.c | 39 ------------------------------ 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index ecf9bcea85..3ea3a5a7ba 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -1,15 +1,42 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include +#include + #include "dhcp-internal.h" #include "dhcp6-internal.h" #include "escape.h" #include "in-addr-util.h" #include "networkd-dhcp-common.h" +#include "networkd-link.h" #include "networkd-network.h" #include "parse-util.h" +#include "socket-util.h" #include "string-table.h" #include "strv.h" +bool link_dhcp_enabled(Link *link, int family) { + assert(link); + assert(IN_SET(family, AF_INET, AF_INET6)); + + if (family == AF_INET6 && !socket_ipv6_is_supported()) + return false; + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->bond) + return false; + + if (link->iftype == ARPHRD_CAN) + return false; + + return link->network->dhcp & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6); +} + int config_parse_dhcp( const char* unit, const char *filename, diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h index 01400a2385..1032ec2bda 100644 --- a/src/network/networkd-dhcp-common.h +++ b/src/network/networkd-dhcp-common.h @@ -7,6 +7,8 @@ #define DHCP_ROUTE_METRIC 1024 +typedef struct Link Link; + typedef enum DHCPUseDomains { DHCP_USE_DOMAINS_NO, DHCP_USE_DOMAINS_YES, @@ -35,6 +37,14 @@ typedef struct DUID { usec_t llt_time; } DUID; +bool link_dhcp_enabled(Link *link, int family); +static inline bool link_dhcp4_enabled(Link *link) { + return link_dhcp_enabled(link, AF_INET); +} +static inline bool link_dhcp6_enabled(Link *link) { + return link_dhcp_enabled(link, AF_INET6); +} + const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index c73389e25c..dcdfbe2ac4 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -61,45 +61,6 @@ DUID* link_get_duid(Link *link) { return &link->manager->duid; } -static bool link_dhcp6_enabled(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return false; - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->network->bond) - return false; - - if (link->iftype == ARPHRD_CAN) - return false; - - return link->network->dhcp & ADDRESS_FAMILY_IPV6; -} - -static bool link_dhcp4_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->network->bond) - return false; - - if (link->iftype == ARPHRD_CAN) - return false; - - return link->network->dhcp & ADDRESS_FAMILY_IPV4; -} - static bool link_dhcp4_server_enabled(Link *link) { assert(link); From 6f7a17ff0cc07d82a4e4a034997d3ee0943b7689 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 16:23:28 +0900 Subject: [PATCH 102/138] network: unify link_ipv{4,6}_forward_enabled() --- src/network/networkd-link.c | 25 ++++--------------------- src/network/networkd-link.h | 8 ++++++++ 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index dcdfbe2ac4..e41ed6b334 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -162,25 +162,11 @@ static bool link_radv_enabled(Link *link) { return link->network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE; } -static bool link_ipv4_forward_enabled(Link *link) { +bool link_ip_forward_enabled(Link *link, int family) { assert(link); + assert(IN_SET(family, AF_INET, AF_INET6)); - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID) - return false; - - return link->network->ip_forward & ADDRESS_FAMILY_IPV4; -} - -static bool link_ipv6_forward_enabled(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) + if (family == AF_INET6 && !socket_ipv6_is_supported()) return false; if (link->flags & IFF_LOOPBACK) @@ -189,10 +175,7 @@ static bool link_ipv6_forward_enabled(Link *link) { if (!link->network) return false; - if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID) - return false; - - return link->network->ip_forward & ADDRESS_FAMILY_IPV6; + return link->network->ip_forward & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6); } static bool link_proxy_arp_enabled(Link *link) { diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 25c7bd98da..6a4ef4f6bf 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -227,6 +227,14 @@ bool link_has_carrier(Link *link); bool link_ipv6ll_enabled(Link *link); int link_ipv6ll_gained(Link *link, const struct in6_addr *address); +bool link_ip_forward_enabled(Link *link, int family); +static inline bool link_ipv4_forward_enabled(Link *link) { + return link_ip_forward_enabled(link, AF_INET); +} +static inline bool link_ipv6_forward_enabled(Link *link) { + return link_ip_forward_enabled(link, AF_INET6); +} + int link_set_mtu(Link *link, uint32_t mtu); bool link_ipv4ll_enabled(Link *link, AddressFamily mask); From 062c020fb6e4d6008ea930af9f2d934fb72e25bb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 16:30:23 +0900 Subject: [PATCH 103/138] network: move link_ipv6_accept_ra_enabled() --- src/network/networkd-link.c | 30 ------------------------------ src/network/networkd-ndisc.c | 33 ++++++++++++++++++++++++++++++++- src/network/networkd-ndisc.h | 2 ++ 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index e41ed6b334..357848ee57 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -193,36 +193,6 @@ static bool link_proxy_arp_enabled(Link *link) { return true; } -static bool link_ipv6_accept_ra_enabled(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return false; - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (!link_ipv6ll_enabled(link)) - return false; - - /* If unset use system default (enabled if local forwarding is disabled. - * disabled if local forwarding is enabled). - * If set, ignore or enforce RA independent of local forwarding state. - */ - if (link->network->ipv6_accept_ra < 0) - /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */ - return !link_ipv6_forward_enabled(link); - else if (link->network->ipv6_accept_ra > 0) - /* accept RA even if ip_forward is enabled */ - return true; - else - /* ignore RA */ - return false; -} - static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) { assert(link); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 6a21f12907..89f2b0475b 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -3,8 +3,9 @@ Copyright © 2014 Intel Corporation. All rights reserved. ***/ -#include #include +#include +#include #include "sd-ndisc.h" @@ -35,6 +36,36 @@ #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e) +bool link_ipv6_accept_ra_enabled(Link *link) { + assert(link); + + if (!socket_ipv6_is_supported()) + return false; + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (!link_ipv6ll_enabled(link)) + return false; + + /* If unset use system default (enabled if local forwarding is disabled. + * disabled if local forwarding is enabled). + * If set, ignore or enforce RA independent of local forwarding state. + */ + if (link->network->ipv6_accept_ra < 0) + /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */ + return !link_ipv6_forward_enabled(link); + else if (link->network->ipv6_accept_ra > 0) + /* accept RA even if ip_forward is enabled */ + return true; + else + /* ignore RA */ + return false; +} + static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force); static int ndisc_address_callback(Address *address) { diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 927f555bc6..fd7bb0e97f 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -69,6 +69,8 @@ static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) { return ((char*) n) + ALIGN(sizeof(NDiscDNSSL)); } +bool link_ipv6_accept_ra_enabled(Link *link); + int ndisc_configure(Link *link); void ndisc_vacuum(Link *link); void ndisc_flush(Link *link); From 5ae0fb7fb75efeea1a965cda1ff9181f0bcd47d2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 16:35:54 +0900 Subject: [PATCH 104/138] network: move link_dhcp4_server_enabled() --- src/network/networkd-dhcp-server.c | 42 ++++++++++++++++++++++++++++++ src/network/networkd-link.c | 41 ++++------------------------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index a0ef756df8..0155ab2de2 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -1,5 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include +#include +#include + #include "sd-dhcp-server.h" #include "fd-util.h" @@ -15,6 +19,24 @@ #include "string-util.h" #include "strv.h" +static bool link_dhcp4_server_enabled(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->bond) + return false; + + if (link->iftype == ARPHRD_CAN) + return false; + + return link->network->dhcp_server; +} + static Address* link_find_dhcp_server_address(Link *link) { Address *address; @@ -231,6 +253,24 @@ int dhcp4_server_configure(Link *link) { Address *address; int r; + assert(link); + + if (!link_dhcp4_server_enabled(link)) + return 0; + + if (!(link->flags & IFF_UP)) + return 0; + + if (!link->dhcp_server) { + r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex); + if (r < 0) + return r; + + r = sd_dhcp_server_attach_event(link->dhcp_server, link->manager->event, 0); + if (r < 0) + return r; + } + address = link_find_dhcp_server_address(link); if (!address) return log_link_error_errno(link, SYNTHETIC_ERRNO(EBUSY), @@ -342,6 +382,8 @@ int dhcp4_server_configure(Link *link) { r = sd_dhcp_server_start(link->dhcp_server); if (r < 0) return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m"); + + log_link_debug(link, "Offering DHCPv4 leases"); } return 0; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 357848ee57..0610af16d5 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -61,24 +61,6 @@ DUID* link_get_duid(Link *link) { return &link->manager->duid; } -static bool link_dhcp4_server_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->network->bond) - return false; - - if (link->iftype == ARPHRD_CAN) - return false; - - return link->network->dhcp_server; -} - bool link_ipv4ll_enabled(Link *link, AddressFamily mask) { assert(link); assert((mask & ~(ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) == 0); @@ -974,12 +956,9 @@ static int link_set_static_configs(Link *link) { return r; /* now that we can figure out a default address for the dhcp server, start it */ - if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) { - r = dhcp4_server_configure(link); - if (r < 0) - return r; - log_link_debug(link, "Offering DHCPv4 leases"); - } + r = dhcp4_server_configure(link); + if (r < 0) + return r; return 0; } @@ -2414,16 +2393,6 @@ static int link_configure(Link *link) { return r; } - if (link_dhcp4_server_enabled(link)) { - r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex); - if (r < 0) - return r; - - r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0); - if (r < 0) - return r; - } - if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link)) { r = dhcp6_configure(link); @@ -2684,7 +2653,7 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for if (r < 0) return r; - if (link_dhcp4_server_enabled(link)) + if (link->dhcp_server) (void) sd_dhcp_server_stop(link->dhcp_server); r = link_drop_config(link); @@ -3174,7 +3143,7 @@ static int link_carrier_lost(Link *link) { return r; } - if (link_dhcp4_server_enabled(link)) + if (link->dhcp_server) (void) sd_dhcp_server_stop(link->dhcp_server); r = link_drop_config(link); From 086b8853d1902bd984144d08cae0e69e11bd583b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 16:39:45 +0900 Subject: [PATCH 105/138] network: move link_radv_enabled() --- src/network/networkd-link.c | 19 ++++--------------- src/network/networkd-radv.c | 12 ++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0610af16d5..0f48402cb6 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -135,15 +135,6 @@ static bool link_ipv6_enabled(Link *link) { return false; } -static bool link_radv_enabled(Link *link) { - assert(link); - - if (!link_ipv6ll_enabled(link)) - return false; - - return link->network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE; -} - bool link_ip_forward_enabled(Link *link, int family) { assert(link); assert(IN_SET(family, AF_INET, AF_INET6)); @@ -1185,7 +1176,7 @@ static int link_acquire_ipv6_conf(Link *link) { return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m"); } - if (link_radv_enabled(link)) { + if (link->radv) { assert(link->radv); assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); @@ -2406,11 +2397,9 @@ static int link_configure(Link *link) { return r; } - if (link_radv_enabled(link)) { - r = radv_configure(link); - if (r < 0) - return r; - } + r = radv_configure(link); + if (r < 0) + return r; if (link_lldp_rx_enabled(link)) { r = link_lldp_rx_configure(link); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 04bbb8a62b..81350a3e05 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -602,12 +602,24 @@ int radv_emit_dns(Link *link) { return 0; } +static bool link_radv_enabled(Link *link) { + assert(link); + + if (!link_ipv6ll_enabled(link)) + return false; + + return link->network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE; +} + int radv_configure(Link *link) { int r; assert(link); assert(link->network); + if (!link_radv_enabled(link)) + return 0; + r = sd_radv_new(&link->radv); if (r < 0) return r; From 256c75fd1fe70ae6fdd290ff40e312992ac6f6ca Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 17:03:36 +0900 Subject: [PATCH 106/138] network: move DUID related functions --- src/network/networkd-dhcp-common.c | 189 +++++++++++++++++++++++++++++ src/network/networkd-dhcp-common.h | 5 + src/network/networkd-link.c | 142 +--------------------- src/network/networkd-link.h | 4 +- src/network/networkd-manager.c | 48 -------- src/network/networkd-manager.h | 1 - 6 files changed, 196 insertions(+), 193 deletions(-) diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index 3ea3a5a7ba..d3053d0354 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -9,6 +9,7 @@ #include "in-addr-util.h" #include "networkd-dhcp-common.h" #include "networkd-link.h" +#include "networkd-manager.h" #include "networkd-network.h" #include "parse-util.h" #include "socket-util.h" @@ -37,6 +38,194 @@ bool link_dhcp_enabled(Link *link, int family) { return link->network->dhcp & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6); } +DUID* link_get_duid(Link *link) { + if (link->network->duid.type != _DUID_TYPE_INVALID) + return &link->network->duid; + else + return &link->manager->duid; +} + +static int duid_set_uuid(DUID *duid, sd_id128_t uuid) { + assert(duid); + + if (duid->raw_data_len > 0) + return 0; + + if (duid->type != DUID_TYPE_UUID) + return -EINVAL; + + memcpy(&duid->raw_data, &uuid, sizeof(sd_id128_t)); + duid->raw_data_len = sizeof(sd_id128_t); + + return 1; +} + +static int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + Manager *manager = userdata; + const sd_bus_error *e; + const void *a; + size_t sz; + DUID *duid; + Link *link; + int r; + + assert(m); + assert(manager); + + e = sd_bus_message_get_error(m); + if (e) { + log_error_errno(sd_bus_error_get_errno(e), + "Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s", + e->message); + goto configure; + } + + r = sd_bus_message_read_array(m, 'y', &a, &sz); + if (r < 0) + goto configure; + + if (sz != sizeof(sd_id128_t)) { + log_error("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID."); + goto configure; + } + + memcpy(&manager->product_uuid, a, sz); + while ((duid = set_steal_first(manager->duids_requesting_uuid))) + (void) duid_set_uuid(duid, manager->product_uuid); + + manager->duids_requesting_uuid = set_free(manager->duids_requesting_uuid); + +configure: + while ((link = set_steal_first(manager->links_requesting_uuid))) { + link_unref(link); + + r = link_configure(link); + if (r < 0) + link_enter_failed(link); + } + + manager->links_requesting_uuid = set_free(manager->links_requesting_uuid); + + /* To avoid calling GetProductUUID() bus method so frequently, set the flag below + * even if the method fails. */ + manager->has_product_uuid = true; + + return 1; +} + +int manager_request_product_uuid(Manager *m, Link *link) { + int r; + + assert(m); + + if (m->has_product_uuid) + return 0; + + log_debug("Requesting product UUID"); + + if (link) { + DUID *duid; + + assert_se(duid = link_get_duid(link)); + + r = set_ensure_put(&m->links_requesting_uuid, NULL, link); + if (r < 0) + return log_oom(); + if (r > 0) + link_ref(link); + + r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid); + if (r < 0) + return log_oom(); + } + + if (!m->bus || sd_bus_is_ready(m->bus) <= 0) { + log_debug("Not connected to system bus, requesting product UUID later."); + return 0; + } + + r = sd_bus_call_method_async( + m->bus, + NULL, + "org.freedesktop.hostname1", + "/org/freedesktop/hostname1", + "org.freedesktop.hostname1", + "GetProductUUID", + get_product_uuid_handler, + m, + "b", + false); + if (r < 0) + return log_warning_errno(r, "Failed to get product UUID: %m"); + + return 0; +} + +static bool link_requires_uuid(Link *link) { + const DUID *duid; + + assert(link); + assert(link->manager); + assert(link->network); + + duid = link_get_duid(link); + if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0) + return false; + + if (link_dhcp4_enabled(link) && IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY)) + return true; + + if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link)) + return true; + + return false; +} + +int link_configure_duid(Link *link) { + Manager *m; + DUID *duid; + int r; + + assert(link); + assert(link->manager); + assert(link->network); + + m = link->manager; + duid = link_get_duid(link); + + if (!link_requires_uuid(link)) + return 1; + + if (m->has_product_uuid) { + (void) duid_set_uuid(duid, m->product_uuid); + return 1; + } + + if (!m->links_requesting_uuid) { + r = manager_request_product_uuid(m, link); + if (r < 0) { + if (r == -ENOMEM) + return r; + + log_link_warning_errno(link, r, + "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m"); + return 1; + } + } else { + r = set_put(m->links_requesting_uuid, link); + if (r < 0) + return log_oom(); + if (r > 0) + link_ref(link); + + r = set_put(m->duids_requesting_uuid, duid); + if (r < 0) + return log_oom(); + } + + return 0; +} + int config_parse_dhcp( const char* unit, const char *filename, diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h index 1032ec2bda..e3982a7ef1 100644 --- a/src/network/networkd-dhcp-common.h +++ b/src/network/networkd-dhcp-common.h @@ -8,6 +8,7 @@ #define DHCP_ROUTE_METRIC 1024 typedef struct Link Link; +typedef struct Manager Manager; typedef enum DHCPUseDomains { DHCP_USE_DOMAINS_NO, @@ -45,6 +46,10 @@ static inline bool link_dhcp6_enabled(Link *link) { return link_dhcp_enabled(link, AF_INET6); } +DUID* link_get_duid(Link *link); +int link_configure_duid(Link *link); +int manager_request_product_uuid(Manager *m, Link *link); + const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0f48402cb6..5835f76cef 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -54,13 +54,6 @@ #include "util.h" #include "vrf.h" -DUID* link_get_duid(Link *link) { - if (link->network->duid.type != _DUID_TYPE_INVALID) - return &link->network->duid; - else - return &link->manager->duid; -} - bool link_ipv4ll_enabled(Link *link, AddressFamily mask) { assert(link); assert((mask & ~(ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) == 0); @@ -2302,7 +2295,7 @@ static int link_configure_sr_iov(Link *link) { return 0; } -static int link_configure(Link *link) { +int link_configure(Link *link) { int r; assert(link); @@ -2468,139 +2461,6 @@ static int link_configure_continue(Link *link) { return link_enter_join_netdev(link); } -static int duid_set_uuid(DUID *duid, sd_id128_t uuid) { - assert(duid); - - if (duid->raw_data_len > 0) - return 0; - - if (duid->type != DUID_TYPE_UUID) - return -EINVAL; - - memcpy(&duid->raw_data, &uuid, sizeof(sd_id128_t)); - duid->raw_data_len = sizeof(sd_id128_t); - - return 1; -} - -int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - Manager *manager = userdata; - const sd_bus_error *e; - const void *a; - size_t sz; - DUID *duid; - Link *link; - int r; - - assert(m); - assert(manager); - - e = sd_bus_message_get_error(m); - if (e) { - log_error_errno(sd_bus_error_get_errno(e), - "Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s", - e->message); - goto configure; - } - - r = sd_bus_message_read_array(m, 'y', &a, &sz); - if (r < 0) - goto configure; - - if (sz != sizeof(sd_id128_t)) { - log_error("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID."); - goto configure; - } - - memcpy(&manager->product_uuid, a, sz); - while ((duid = set_steal_first(manager->duids_requesting_uuid))) - (void) duid_set_uuid(duid, manager->product_uuid); - - manager->duids_requesting_uuid = set_free(manager->duids_requesting_uuid); - -configure: - while ((link = set_steal_first(manager->links_requesting_uuid))) { - link_unref(link); - - r = link_configure(link); - if (r < 0) - link_enter_failed(link); - } - - manager->links_requesting_uuid = set_free(manager->links_requesting_uuid); - - /* To avoid calling GetProductUUID() bus method so frequently, set the flag below - * even if the method fails. */ - manager->has_product_uuid = true; - - return 1; -} - -static bool link_requires_uuid(Link *link) { - const DUID *duid; - - assert(link); - assert(link->manager); - assert(link->network); - - duid = link_get_duid(link); - if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0) - return false; - - if (link_dhcp4_enabled(link) && IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY)) - return true; - - if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link)) - return true; - - return false; -} - -static int link_configure_duid(Link *link) { - Manager *m; - DUID *duid; - int r; - - assert(link); - assert(link->manager); - assert(link->network); - - m = link->manager; - duid = link_get_duid(link); - - if (!link_requires_uuid(link)) - return 1; - - if (m->has_product_uuid) { - (void) duid_set_uuid(duid, m->product_uuid); - return 1; - } - - if (!m->links_requesting_uuid) { - r = manager_request_product_uuid(m, link); - if (r < 0) { - if (r == -ENOMEM) - return r; - - log_link_warning_errno(link, r, - "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m"); - return 1; - } - } else { - r = set_put(m->links_requesting_uuid, link); - if (r < 0) - return log_oom(); - if (r > 0) - link_ref(link); - - r = set_put(m->duids_requesting_uuid, duid); - if (r < 0) - return log_oom(); - } - - return 0; -} - static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool force) { Network *network; int r; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 6a4ef4f6bf..43451ee2de 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -191,9 +191,6 @@ typedef struct Link { typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*); -DUID *link_get_duid(Link *link); -int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error); - void link_ntp_settings_clear(Link *link); void link_dns_settings_clear(Link *link); Link *link_unref(Link *link); @@ -244,6 +241,7 @@ int link_stop_clients(Link *link, bool may_keep_dhcp); const char* link_state_to_string(LinkState s) _const_; LinkState link_state_from_string(const char *s) _pure_; +int link_configure(Link *link); int link_reconfigure(Link *link, bool force); int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 524dbedb1e..e8d270987d 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1244,51 +1244,3 @@ int manager_set_timezone(Manager *m, const char *tz) { return 0; } - -int manager_request_product_uuid(Manager *m, Link *link) { - int r; - - assert(m); - - if (m->has_product_uuid) - return 0; - - log_debug("Requesting product UUID"); - - if (link) { - DUID *duid; - - assert_se(duid = link_get_duid(link)); - - r = set_ensure_put(&m->links_requesting_uuid, NULL, link); - if (r < 0) - return log_oom(); - if (r > 0) - link_ref(link); - - r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid); - if (r < 0) - return log_oom(); - } - - if (!m->bus || sd_bus_is_ready(m->bus) <= 0) { - log_debug("Not connected to system bus, requesting product UUID later."); - return 0; - } - - r = sd_bus_call_method_async( - m->bus, - NULL, - "org.freedesktop.hostname1", - "/org/freedesktop/hostname1", - "org.freedesktop.hostname1", - "GetProductUUID", - get_product_uuid_handler, - m, - "b", - false); - if (r < 0) - return log_warning_errno(r, "Failed to get product UUID: %m"); - - return 0; -} diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 2e250f1509..142a6eb358 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -89,6 +89,5 @@ Link* manager_find_uplink(Manager *m, Link *exclude); int manager_set_hostname(Manager *m, const char *hostname); int manager_set_timezone(Manager *m, const char *timezone); -int manager_request_product_uuid(Manager *m, Link *link); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); From 34d7f2c99e6fa86fe4072d684fb33a438061bb89 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 17:37:54 +0900 Subject: [PATCH 107/138] network: merge link_set_bridge_vlan() and br_vlan_configure() --- src/network/networkd-brvlan.c | 28 ++++++++++++++-------------- src/network/networkd-brvlan.h | 4 +--- src/network/networkd-link.c | 19 +++---------------- 3 files changed, 18 insertions(+), 33 deletions(-) diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c index bbe01037d1..23ca4f9fac 100644 --- a/src/network/networkd-brvlan.c +++ b/src/network/networkd-brvlan.c @@ -146,26 +146,26 @@ static int set_brvlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *lin return 1; } -int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap) { +int link_set_bridge_vlan(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - sd_netlink *rtnl; - uint16_t flags; int r; assert(link); assert(link->manager); - assert(br_vid_bitmap); - assert(br_untagged_bitmap); assert(link->network); - /* pvid might not be in br_vid_bitmap yet */ - if (pvid) - set_bit(pvid, br_vid_bitmap); + if (!link->network->use_br_vlan) + return 0; - rtnl = link->manager->rtnl; + if (!link->network->bridge && !streq_ptr(link->kind, "bridge")) + return 0; + + /* pvid might not be in br_vid_bitmap yet */ + if (link->network->pvid) + set_bit(link->network->pvid, link->network->br_vid_bitmap); /* create new RTM message */ - r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, link->ifindex); + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); @@ -179,14 +179,14 @@ int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32 /* master needs flag self */ if (!link->network->bridge) { - flags = BRIDGE_FLAGS_SELF; - r = sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(uint16_t)); + uint16_t flags = BRIDGE_FLAGS_SELF; + r = sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(flags)); if (r < 0) return log_link_error_errno(link, r, "Could not open IFLA_BRIDGE_FLAGS: %m"); } /* add vlan info */ - r = append_vlan_info_data(link, req, pvid, br_vid_bitmap, br_untagged_bitmap); + r = append_vlan_info_data(link, req, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap); if (r < 0) return log_link_error_errno(link, r, "Could not append VLANs: %m"); @@ -195,7 +195,7 @@ int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32 return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); /* send message to the kernel */ - r = netlink_call_async(rtnl, NULL, req, set_brvlan_handler, + r = netlink_call_async(link->manager->rtnl, NULL, req, set_brvlan_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-brvlan.h b/src/network/networkd-brvlan.h index 7533034021..d13ea30151 100644 --- a/src/network/networkd-brvlan.h +++ b/src/network/networkd-brvlan.h @@ -5,8 +5,6 @@ Copyright © 2016 BISDN GmbH. All rights reserved. ***/ -#include - #include "conf-parser.h" #define BRIDGE_VLAN_BITMAP_MAX 4096 @@ -14,7 +12,7 @@ typedef struct Link Link; -int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap); +int link_set_bridge_vlan(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_pvid); CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_vlan); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 5835f76cef..10bea3b7ff 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -947,16 +947,6 @@ static int link_set_static_configs(Link *link) { return 0; } -static int link_set_bridge_vlan(Link *link) { - int r; - - r = br_vlan_configure(link, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap); - if (r < 0) - log_link_error_errno(link, r, "Failed to assign VLANs to bridge port: %m"); - - return r; -} - static int link_set_proxy_arp(Link *link) { int r; @@ -1842,12 +1832,9 @@ static int link_joined(Link *link) { log_link_error_errno(link, r, "Failed to add to bond master's slave list: %m"); } - if (link->network->use_br_vlan && - (link->network->bridge || streq_ptr("bridge", link->kind))) { - r = link_set_bridge_vlan(link); - if (r < 0) - log_link_error_errno(link, r, "Could not set bridge vlan: %m"); - } + r = link_set_bridge_vlan(link); + if (r < 0) + log_link_error_errno(link, r, "Could not set bridge vlan: %m"); /* Skip setting up addresses until it gets carrier, or it would try to set addresses twice, From 200543791ab11f1379216650eb7949113974e4a3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 17:45:37 +0900 Subject: [PATCH 108/138] network: move link_configure_traffic_control() --- src/network/networkd-link.c | 21 --------------------- src/network/tc/tc.c | 23 ++++++++++++++++++++++- src/network/tc/tc.h | 2 +- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 10bea3b7ff..59ac24ccdf 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2240,27 +2240,6 @@ static int link_drop_config(Link *link) { return 0; } -static int link_configure_traffic_control(Link *link) { - TrafficControl *tc; - int r; - - link->tc_configured = false; - link->tc_messages = 0; - - ORDERED_HASHMAP_FOREACH(tc, link->network->tc_by_section) { - r = traffic_control_configure(link, tc); - if (r < 0) - return r; - } - - if (link->tc_messages == 0) - link->tc_configured = true; - else - log_link_debug(link, "Configuring traffic control"); - - return 0; -} - static int link_configure_sr_iov(Link *link) { SRIOV *sr_iov; int r; diff --git a/src/network/tc/tc.c b/src/network/tc/tc.c index 30a00133d6..8554716d76 100644 --- a/src/network/tc/tc.c +++ b/src/network/tc/tc.c @@ -21,7 +21,7 @@ void traffic_control_free(TrafficControl *tc) { } } -int traffic_control_configure(Link *link, TrafficControl *tc) { +static int traffic_control_configure(Link *link, TrafficControl *tc) { assert(link); assert(tc); @@ -35,6 +35,27 @@ int traffic_control_configure(Link *link, TrafficControl *tc) { } } +int link_configure_traffic_control(Link *link) { + TrafficControl *tc; + int r; + + link->tc_configured = false; + link->tc_messages = 0; + + ORDERED_HASHMAP_FOREACH(tc, link->network->tc_by_section) { + r = traffic_control_configure(link, tc); + if (r < 0) + return r; + } + + if (link->tc_messages == 0) + link->tc_configured = true; + else + log_link_debug(link, "Configuring traffic control"); + + return 0; +} + int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact) { assert(tc); diff --git a/src/network/tc/tc.h b/src/network/tc/tc.h index defa0b774a..c822359f6c 100644 --- a/src/network/tc/tc.h +++ b/src/network/tc/tc.h @@ -28,5 +28,5 @@ typedef struct TrafficControl { #define TC(tc) (&(tc)->meta) void traffic_control_free(TrafficControl *tc); -int traffic_control_configure(Link *link, TrafficControl *tc); +int link_configure_traffic_control(Link *link); int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact); From 209af9a67a485ef647651fef7e22cfc04647c671 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 17:48:59 +0900 Subject: [PATCH 109/138] network: introduce network_verify_traffic_control() --- src/network/networkd-network.c | 7 +------ src/network/tc/tc.c | 13 ++++++++++++- src/network/tc/tc.h | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 3c6f45c61b..e93e524c3f 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -156,7 +156,6 @@ static int network_resolve_stacked_netdevs(Network *network) { } int network_verify(Network *network) { - TrafficControl *tc; SRIOV *sr_iov; assert(network); @@ -300,11 +299,7 @@ int network_verify(Network *network) { network_verify_prefixes(network); network_verify_route_prefixes(network); network_verify_routing_policy_rules(network); - - bool has_root = false, has_clsact = false; - ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section) - if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0) - traffic_control_free(tc); + network_verify_traffic_control(network); ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section) if (sr_iov_section_verify(sr_iov) < 0) diff --git a/src/network/tc/tc.c b/src/network/tc/tc.c index 8554716d76..2bb9c8f07f 100644 --- a/src/network/tc/tc.c +++ b/src/network/tc/tc.c @@ -56,7 +56,7 @@ int link_configure_traffic_control(Link *link) { return 0; } -int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact) { +static int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact) { assert(tc); switch(tc->kind) { @@ -68,3 +68,14 @@ int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, boo assert_not_reached("Invalid traffic control type"); } } + +void network_verify_traffic_control(Network *network) { + bool has_root = false, has_clsact = false; + TrafficControl *tc; + + assert(network); + + ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section) + if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0) + traffic_control_free(tc); +} diff --git a/src/network/tc/tc.h b/src/network/tc/tc.h index c822359f6c..7e277f6323 100644 --- a/src/network/tc/tc.h +++ b/src/network/tc/tc.h @@ -29,4 +29,4 @@ typedef struct TrafficControl { void traffic_control_free(TrafficControl *tc); int link_configure_traffic_control(Link *link); -int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact); +void network_verify_traffic_control(Network *network); From f3a3ff2762ebd3c470fe081e17a6c45fe48f9add Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 17:51:14 +0900 Subject: [PATCH 110/138] network: move link_configure_sr_iov() --- src/network/networkd-link.c | 21 --------------------- src/network/networkd-sriov.c | 23 ++++++++++++++++++++++- src/network/networkd-sriov.h | 3 +-- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 59ac24ccdf..04038e986c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2240,27 +2240,6 @@ static int link_drop_config(Link *link) { return 0; } -static int link_configure_sr_iov(Link *link) { - SRIOV *sr_iov; - int r; - - link->sr_iov_configured = false; - link->sr_iov_messages = 0; - - ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) { - r = sr_iov_configure(link, sr_iov); - if (r < 0) - return r; - } - - if (link->sr_iov_messages == 0) - link->sr_iov_configured = true; - else - log_link_debug(link, "Configuring SR-IOV"); - - return 0; -} - int link_configure(Link *link) { int r; diff --git a/src/network/networkd-sriov.c b/src/network/networkd-sriov.c index 7d99707343..6c96ca39d2 100644 --- a/src/network/networkd-sriov.c +++ b/src/network/networkd-sriov.c @@ -108,7 +108,7 @@ static int sr_iov_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { return 1; } -int sr_iov_configure(Link *link, SRIOV *sr_iov) { +static int sr_iov_configure(Link *link, SRIOV *sr_iov) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -226,6 +226,27 @@ int sr_iov_configure(Link *link, SRIOV *sr_iov) { return 0; } +int link_configure_sr_iov(Link *link) { + SRIOV *sr_iov; + int r; + + link->sr_iov_configured = false; + link->sr_iov_messages = 0; + + ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) { + r = sr_iov_configure(link, sr_iov); + if (r < 0) + return r; + } + + if (link->sr_iov_messages == 0) + link->sr_iov_configured = true; + else + log_link_debug(link, "Configuring SR-IOV"); + + return 0; +} + int sr_iov_section_verify(SRIOV *sr_iov) { assert(sr_iov); diff --git a/src/network/networkd-sriov.h b/src/network/networkd-sriov.h index 04cc4270f1..b32a64e827 100644 --- a/src/network/networkd-sriov.h +++ b/src/network/networkd-sriov.h @@ -34,8 +34,7 @@ typedef struct SRIOV { } SRIOV; SRIOV *sr_iov_free(SRIOV *sr_iov); - -int sr_iov_configure(Link *link, SRIOV *sr_iov); +int link_configure_sr_iov(Link *link); int sr_iov_section_verify(SRIOV *sr_iov); DEFINE_NETWORK_SECTION_FUNCTIONS(SRIOV, sr_iov_free); From bbe694f91f9da1af1fb27f9865b952905c04e5e1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 17:53:18 +0900 Subject: [PATCH 111/138] network: introduce network_verify_sr_iov() --- src/network/networkd-network.c | 7 +------ src/network/networkd-sriov.c | 12 +++++++++++- src/network/networkd-sriov.h | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index e93e524c3f..e02b7e9586 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -156,8 +156,6 @@ static int network_resolve_stacked_netdevs(Network *network) { } int network_verify(Network *network) { - SRIOV *sr_iov; - assert(network); assert(network->filename); @@ -300,10 +298,7 @@ int network_verify(Network *network) { network_verify_route_prefixes(network); network_verify_routing_policy_rules(network); network_verify_traffic_control(network); - - ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section) - if (sr_iov_section_verify(sr_iov) < 0) - sr_iov_free(sr_iov); + network_verify_sr_iov(network); return 0; } diff --git a/src/network/networkd-sriov.c b/src/network/networkd-sriov.c index 6c96ca39d2..d2a389d95d 100644 --- a/src/network/networkd-sriov.c +++ b/src/network/networkd-sriov.c @@ -247,7 +247,7 @@ int link_configure_sr_iov(Link *link) { return 0; } -int sr_iov_section_verify(SRIOV *sr_iov) { +static int sr_iov_section_verify(SRIOV *sr_iov) { assert(sr_iov); if (section_is_invalid(sr_iov->section)) @@ -262,6 +262,16 @@ int sr_iov_section_verify(SRIOV *sr_iov) { return 0; } +void network_verify_sr_iov(Network *network) { + SRIOV *sr_iov; + + assert(network); + + ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section) + if (sr_iov_section_verify(sr_iov) < 0) + sr_iov_free(sr_iov); +} + int config_parse_sr_iov_uint32( const char *unit, const char *filename, diff --git a/src/network/networkd-sriov.h b/src/network/networkd-sriov.h index b32a64e827..acd9f9b753 100644 --- a/src/network/networkd-sriov.h +++ b/src/network/networkd-sriov.h @@ -35,7 +35,7 @@ typedef struct SRIOV { SRIOV *sr_iov_free(SRIOV *sr_iov); int link_configure_sr_iov(Link *link); -int sr_iov_section_verify(SRIOV *sr_iov); +void network_verify_sr_iov(Network *network); DEFINE_NETWORK_SECTION_FUNCTIONS(SRIOV, sr_iov_free); From 571eeba9092e18b9f082f8c933ecc1ae20e8997f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 18:07:32 +0900 Subject: [PATCH 112/138] network: introduce link_deserialize_dhcp4() --- src/network/networkd-dhcp4.c | 57 +++++++++++++++++++++++++++++------- src/network/networkd-dhcp4.h | 2 ++ src/network/networkd-link.c | 24 ++------------- 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 59c68744c0..91abe888cb 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1241,6 +1241,25 @@ int dhcp4_set_client_identifier(Link *link) { return 0; } +static int dhcp4_init(Link *link) { + int r; + + assert(link); + + if (link->dhcp_client) + return 0; + + r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize); + if (r < 0) + return r; + + r = sd_dhcp_client_attach_event(link->dhcp_client, link->manager->event, 0); + if (r < 0) + return r; + + return 0; +} + int dhcp4_configure(Link *link) { sd_dhcp_option *send_option; void *request_options; @@ -1250,17 +1269,9 @@ int dhcp4_configure(Link *link) { assert(link->network); assert(link->network->dhcp & ADDRESS_FAMILY_IPV4); - if (!link->dhcp_client) { - r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) - return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to create DHCP4 client: %m"); - - r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0); - if (r < 0) - return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to attach event: %m"); - } + r = dhcp4_init(link); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to initialize DHCP4 client: %m"); r = sd_dhcp_client_set_mac(link->dhcp_client, (const uint8_t *) &link->mac, @@ -1420,6 +1431,30 @@ int dhcp4_configure(Link *link) { return dhcp4_set_client_identifier(link); } +int link_deserialize_dhcp4(Link *link, const char *dhcp4_address) { + union in_addr_union address; + int r; + + assert(link); + + if (isempty(dhcp4_address)) + return 0; + + r = in_addr_from_string(AF_INET, dhcp4_address, &address); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to parse DHCPv4 address: %s", dhcp4_address); + + r = dhcp4_init(link); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to initialize DHCPv4 client: %m"); + + r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to set initial DHCPv4 address %s: %m", dhcp4_address); + + return 0; +} + int config_parse_dhcp_max_attempts( const char *unit, const char *filename, diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index 7a80897ffc..5fe1cb323c 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -21,6 +21,8 @@ int dhcp4_configure(Link *link); int dhcp4_set_client_identifier(Link *link); int dhcp4_set_promote_secondaries(Link *link); +int link_deserialize_dhcp4(Link *link, const char *dhcp4_address); + CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 04038e986c..7f96c52a04 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2726,27 +2726,9 @@ network_file_fail: if (r < 0) log_link_warning_errno(link, r, "Failed to load routes from %s, ignoring: %m", link->state_file); - if (dhcp4_address) { - r = in_addr_from_string(AF_INET, dhcp4_address, &address); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to parse DHCPv4 address %s: %m", dhcp4_address); - goto dhcp4_address_fail; - } - - r = sd_dhcp_client_new(&link->dhcp_client, link->network ? link->network->dhcp_anonymize : 0); - if (r < 0) - return log_link_error_errno(link, r, "Failed to create DHCPv4 client: %m"); - - r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0); - if (r < 0) - return log_link_error_errno(link, r, "Failed to attach DHCPv4 event: %m"); - - r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in); - if (r < 0) - return log_link_error_errno(link, r, "Failed to set initial DHCPv4 address %s: %m", dhcp4_address); - } - -dhcp4_address_fail: + r = link_deserialize_dhcp4(link, dhcp4_address); + if (r < 0) + log_link_warning_errno(link, r, "Failed to load DHCPv4 address from %s, ignoring: %m", link->state_file); if (ipv4ll_address) { r = in_addr_from_string(AF_INET, ipv4ll_address, &address); From daad60d19e4f69478e7b596f175cebe834368acd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 18:14:25 +0900 Subject: [PATCH 113/138] network: introduce link_deserialize_ipv4ll() --- src/network/networkd-ipv4ll.c | 55 +++++++++++++++++++++++++++++------ src/network/networkd-ipv4ll.h | 1 + src/network/networkd-link.c | 25 ++-------------- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index e844799b57..ca59c86a7b 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -142,6 +142,25 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) { } } +static int ipv4ll_init(Link *link) { + int r; + + assert(link); + + if (link->ipv4ll) + return 0; + + r = sd_ipv4ll_new(&link->ipv4ll); + if (r < 0) + return r; + + r = sd_ipv4ll_attach_event(link->ipv4ll, link->manager->event, 0); + if (r < 0) + return r; + + return 0; +} + int ipv4ll_configure(Link *link) { uint64_t seed; int r; @@ -150,15 +169,9 @@ int ipv4ll_configure(Link *link) { assert(link->network); assert(link->network->link_local & (ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)); - if (!link->ipv4ll) { - r = sd_ipv4ll_new(&link->ipv4ll); - if (r < 0) - return r; - - r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0); - if (r < 0) - return r; - } + r = ipv4ll_init(link); + if (r < 0) + return r; if (link->sd_device && net_get_unique_predictable_data(link->sd_device, true, &seed) >= 0) { @@ -182,6 +195,30 @@ int ipv4ll_configure(Link *link) { return 0; } +int link_deserialize_ipv4ll(Link *link, const char *ipv4ll_address) { + union in_addr_union address; + int r; + + assert(link); + + if (isempty(ipv4ll_address)) + return 0; + + r = in_addr_from_string(AF_INET, ipv4ll_address, &address); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to parse IPv4LL address: %s", ipv4ll_address); + + r = ipv4ll_init(link); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to initialize IPv4LL client: %m"); + + r = sd_ipv4ll_set_address(link->ipv4ll, &address.in); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to set initial IPv4LL address %s: %m", ipv4ll_address); + + return 0; +} + int config_parse_ipv4ll( const char* unit, const char *filename, diff --git a/src/network/networkd-ipv4ll.h b/src/network/networkd-ipv4ll.h index 49b6fb56ad..0d2cec84c6 100644 --- a/src/network/networkd-ipv4ll.h +++ b/src/network/networkd-ipv4ll.h @@ -8,5 +8,6 @@ typedef struct Link Link; int ipv4ll_configure(Link *link); +int link_deserialize_ipv4ll(Link *link, const char *ipv4ll_address); CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 7f96c52a04..98bd4e80d5 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2679,7 +2679,6 @@ static int link_load(Link *link) { *routes = NULL, *dhcp4_address = NULL, *ipv4ll_address = NULL; - union in_addr_union address; int r; assert(link); @@ -2730,27 +2729,9 @@ network_file_fail: if (r < 0) log_link_warning_errno(link, r, "Failed to load DHCPv4 address from %s, ignoring: %m", link->state_file); - if (ipv4ll_address) { - r = in_addr_from_string(AF_INET, ipv4ll_address, &address); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to parse IPv4LL address %s: %m", ipv4ll_address); - goto ipv4ll_address_fail; - } - - r = sd_ipv4ll_new(&link->ipv4ll); - if (r < 0) - return log_link_error_errno(link, r, "Failed to create IPv4LL client: %m"); - - r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0); - if (r < 0) - return log_link_error_errno(link, r, "Failed to attach IPv4LL event: %m"); - - r = sd_ipv4ll_set_address(link->ipv4ll, &address.in); - if (r < 0) - return log_link_error_errno(link, r, "Failed to set initial IPv4LL address %s: %m", ipv4ll_address); - } - -ipv4ll_address_fail: + r = link_deserialize_ipv4ll(link, ipv4ll_address); + if (r < 0) + log_link_warning_errno(link, r, "Failed to load IPv4LL address from %s, ignoring: %m", link->state_file); return 0; } From ca21a19a2ed45d709fe62ec05c41d45b1dc996f8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 18:24:07 +0900 Subject: [PATCH 114/138] network: introduce link_serialize_ipv4ll() --- src/network/networkd-ipv4ll.c | 22 ++++++++++++++++++++++ src/network/networkd-ipv4ll.h | 1 + src/network/networkd-link.c | 13 +++---------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index ca59c86a7b..d7e4f7b233 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -195,6 +195,28 @@ int ipv4ll_configure(Link *link) { return 0; } +int link_serialize_ipv4ll(Link *link, FILE *f) { + struct in_addr address; + int r; + + assert(link); + + if (!link->ipv4ll) + return 0; + + r = sd_ipv4ll_get_address(link->ipv4ll, &address); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + fputs("IPV4LL_ADDRESS=", f); + serialize_in_addrs(f, &address, 1, false, NULL); + fputc('\n', f); + + return 0; +} + int link_deserialize_ipv4ll(Link *link, const char *ipv4ll_address) { union in_addr_union address; int r; diff --git a/src/network/networkd-ipv4ll.h b/src/network/networkd-ipv4ll.h index 0d2cec84c6..82f67bc1e2 100644 --- a/src/network/networkd-ipv4ll.h +++ b/src/network/networkd-ipv4ll.h @@ -8,6 +8,7 @@ typedef struct Link Link; int ipv4ll_configure(Link *link); +int link_serialize_ipv4ll(Link *link, FILE *f); int link_deserialize_ipv4ll(Link *link, const char *ipv4ll_address); CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 98bd4e80d5..db01654699 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3511,16 +3511,9 @@ int link_save(Link *link) { } else (void) unlink(link->lease_file); - if (link->ipv4ll) { - struct in_addr address; - - r = sd_ipv4ll_get_address(link->ipv4ll, &address); - if (r >= 0) { - fputs("IPV4LL_ADDRESS=", f); - serialize_in_addrs(f, &address, 1, false, NULL); - fputc('\n', f); - } - } + r = link_serialize_ipv4ll(link, f); + if (r < 0) + goto fail; if (link->dhcp6_client) { _cleanup_free_ char *duid = NULL; From 5460bde5c5408d5fd518d5739a679a696a420f40 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 20:15:44 +0900 Subject: [PATCH 115/138] network: introduce link_serialize_dhcp6_client() --- src/network/networkd-dhcp6.c | 21 +++++++++++++++++++++ src/network/networkd-dhcp6.h | 2 ++ src/network/networkd-link.c | 15 +++------------ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 4b99c5f308..c835e5168f 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -1472,6 +1472,27 @@ int dhcp6_configure(Link *link) { return 0; } +int link_serialize_dhcp6_client(Link *link, FILE *f) { + _cleanup_free_ char *duid = NULL; + uint32_t iaid; + int r; + + assert(link); + + if (!link->dhcp6_client) + return 0; + + r = sd_dhcp6_client_get_iaid(link->dhcp6_client, &iaid); + if (r >= 0) + fprintf(f, "DHCP6_CLIENT_IAID=0x%x\n", iaid); + + r = sd_dhcp6_client_duid_as_string(link->dhcp6_client, &duid); + if (r >= 0) + fprintf(f, "DHCP6_CLIENT_DUID=%s\n", duid); + + return 0; +} + int config_parse_dhcp6_pd_hint( const char* unit, const char *filename, diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index 214456096d..ae2cbcc988 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -32,6 +32,8 @@ int dhcp6_configure(Link *link); int dhcp6_request_address(Link *link, int ir); int dhcp6_request_prefix_delegation(Link *link); +int link_serialize_dhcp6_client(Link *link, FILE *f); + CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_client_start_mode); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index db01654699..864ad1d132 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3515,18 +3515,9 @@ int link_save(Link *link) { if (r < 0) goto fail; - if (link->dhcp6_client) { - _cleanup_free_ char *duid = NULL; - uint32_t iaid; - - r = sd_dhcp6_client_get_iaid(link->dhcp6_client, &iaid); - if (r >= 0) - fprintf(f, "DHCP6_CLIENT_IAID=0x%x\n", iaid); - - r = sd_dhcp6_client_duid_as_string(link->dhcp6_client, &duid); - if (r >= 0) - fprintf(f, "DHCP6_CLIENT_DUID=%s\n", duid); - } + r = link_serialize_dhcp6_client(link, f); + if (r < 0) + goto fail; r = fflush_and_check(f); if (r < 0) From a3adb4a6a29bb3a427faabb93751075e36e33c05 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 20:25:11 +0900 Subject: [PATCH 116/138] network: introduce ipv4ll_update_mac() --- src/network/networkd-ipv4ll.c | 30 ++++++++++++++++++++++++++++++ src/network/networkd-ipv4ll.h | 1 + src/network/networkd-link.c | 22 +++------------------- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index d7e4f7b233..706393b2f2 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -195,6 +195,36 @@ int ipv4ll_configure(Link *link) { return 0; } +int ipv4ll_update_mac(Link *link) { + bool restart; + int r; + + assert(link); + + if (!link->ipv4ll) + return 0; + + restart = sd_ipv4ll_is_running(link->ipv4ll) > 0; + + if (restart) { + r = sd_ipv4ll_stop(link->ipv4ll); + if (r < 0) + return r; + } + + r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); + if (r < 0) + return r; + + if (restart) { + r = sd_ipv4ll_start(link->ipv4ll); + if (r < 0) + return r; + } + + return 0; +} + int link_serialize_ipv4ll(Link *link, FILE *f) { struct in_addr address; int r; diff --git a/src/network/networkd-ipv4ll.h b/src/network/networkd-ipv4ll.h index 82f67bc1e2..4833e304b6 100644 --- a/src/network/networkd-ipv4ll.h +++ b/src/network/networkd-ipv4ll.h @@ -8,6 +8,7 @@ typedef struct Link Link; int ipv4ll_configure(Link *link); +int ipv4ll_update_mac(Link *link); int link_serialize_ipv4ll(Link *link, FILE *f); int link_deserialize_ipv4ll(Link *link, const char *ipv4ll_address); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 864ad1d132..5682a1447b 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3035,25 +3035,9 @@ int link_update(Link *link, sd_netlink_message *m) { mac.ether_addr_octet[4], mac.ether_addr_octet[5]); - if (link->ipv4ll) { - bool restart = sd_ipv4ll_is_running(link->ipv4ll) > 0; - - if (restart) { - r = sd_ipv4ll_stop(link->ipv4ll); - if (r < 0) - return log_link_warning_errno(link, r, "Could not stop IPv4LL client: %m"); - } - - r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); - - if (restart) { - r = sd_ipv4ll_start(link->ipv4ll); - if (r < 0) - return log_link_warning_errno(link, r, "Could not restart IPv4LL client: %m"); - } - } + r = ipv4ll_update_mac(link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); if (link->dhcp_client) { r = sd_dhcp_client_set_mac(link->dhcp_client, From d947f7f9771b06fa52604de3784f6d2c9cc77c99 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 20:29:57 +0900 Subject: [PATCH 117/138] network: introduce dhcp4_update_mac() --- src/network/networkd-dhcp4.c | 21 ++++++++++++++++++++- src/network/networkd-dhcp4.h | 2 +- src/network/networkd-link.c | 15 +++------------ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 91abe888cb..c8f4f4bf61 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1182,7 +1182,7 @@ int dhcp4_set_promote_secondaries(Link *link) { return 0; } -int dhcp4_set_client_identifier(Link *link) { +static int dhcp4_set_client_identifier(Link *link) { int r; assert(link); @@ -1431,6 +1431,25 @@ int dhcp4_configure(Link *link) { return dhcp4_set_client_identifier(link); } +int dhcp4_update_mac(Link *link) { + int r; + + assert(link); + + if (!link->dhcp_client) + return 0; + + r = sd_dhcp_client_set_mac(link->dhcp_client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); + if (r < 0) + return r; + + r = dhcp4_set_client_identifier(link); + if (r < 0) + return r; + + return 0; +} + int link_deserialize_dhcp4(Link *link, const char *dhcp4_address) { union in_addr_union address; int r; diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index 5fe1cb323c..ee3b4f1288 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -18,7 +18,7 @@ typedef enum DHCPClientIdentifier { } DHCPClientIdentifier; int dhcp4_configure(Link *link); -int dhcp4_set_client_identifier(Link *link); +int dhcp4_update_mac(Link *link); int dhcp4_set_promote_secondaries(Link *link); int link_deserialize_dhcp4(Link *link, const char *dhcp4_address); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 5682a1447b..59a0166cab 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3039,18 +3039,9 @@ int link_update(Link *link, sd_netlink_message *m) { if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); - if (link->dhcp_client) { - r = sd_dhcp_client_set_mac(link->dhcp_client, - (const uint8_t *) &link->mac, - sizeof (link->mac), - ARPHRD_ETHER); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); - - r = dhcp4_set_client_identifier(link); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set DHCP client identifier: %m"); - } + r = dhcp4_update_mac(link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); if (link->dhcp6_client) { const DUID* duid = link_get_duid(link); From eebba6dc24fb6efb38a5ee21e54d2cf2b0ab956d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 20:41:41 +0900 Subject: [PATCH 118/138] network: introduce dhcp6_update_mac() --- src/network/networkd-dhcp6.c | 86 +++++++++++++++++++++++++++--------- src/network/networkd-dhcp6.h | 1 + src/network/networkd-link.c | 39 ++-------------- 3 files changed, 68 insertions(+), 58 deletions(-) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index c835e5168f..5724d083fc 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -1344,12 +1344,43 @@ static bool dhcp6_enable_prefix_delegation(Link *dhcp6_link) { return false; } +static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) { + const DUID *duid; + int r; + + assert(link); + assert(link->network); + assert(client); + + r = sd_dhcp6_client_set_mac(client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); + if (r < 0) + return r; + + if (link->network->iaid_set) { + r = sd_dhcp6_client_set_iaid(client, link->network->iaid); + if (r < 0) + return r; + } + + duid = link_get_duid(link); + if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) + r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time); + else + r = sd_dhcp6_client_set_duid(client, + duid->type, + duid->raw_data_len > 0 ? duid->raw_data : NULL, + duid->raw_data_len); + if (r < 0) + return r; + + return 0; +} + int dhcp6_configure(Link *link) { _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; sd_dhcp6_option *vendor_option; sd_dhcp6_option *send_option; void *request_options; - const DUID *duid; int r; assert(link); @@ -1368,28 +1399,9 @@ int dhcp6_configure(Link *link) { if (r < 0) return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to attach event: %m"); - r = sd_dhcp6_client_set_mac(client, - (const uint8_t *) &link->mac, - sizeof (link->mac), ARPHRD_ETHER); + r = dhcp6_set_identifier(link, client); if (r < 0) - return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set MAC address: %m"); - - if (link->network->iaid_set) { - r = sd_dhcp6_client_set_iaid(client, link->network->iaid); - if (r < 0) - return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set IAID: %m"); - } - - duid = link_get_duid(link); - if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) - r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time); - else - r = sd_dhcp6_client_set_duid(client, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); - if (r < 0) - return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set DUID: %m"); + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set identifier: %m"); ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp6_client_send_options) { r = sd_dhcp6_client_add_option(client, send_option); @@ -1472,6 +1484,36 @@ int dhcp6_configure(Link *link) { return 0; } +int dhcp6_update_mac(Link *link) { + bool restart; + int r; + + assert(link); + + if (!link->dhcp6_client) + return 0; + + restart = sd_dhcp6_client_is_running(link->dhcp6_client) > 0; + + if (restart) { + r = sd_dhcp6_client_stop(link->dhcp6_client); + if (r < 0) + return r; + } + + r = dhcp6_set_identifier(link, link->dhcp6_client); + if (r < 0) + return r; + + if (restart) { + r = sd_dhcp6_client_start(link->dhcp6_client); + if (r < 0) + return log_link_warning_errno(link, r, "Could not restart DHCPv6 client: %m"); + } + + return 0; +} + int link_serialize_dhcp6_client(Link *link, FILE *f) { _cleanup_free_ char *duid = NULL; uint32_t iaid; diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index ae2cbcc988..4956c90915 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -29,6 +29,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6DelegatedPrefix*, dhcp6_pd_free); bool link_dhcp6_pd_is_enabled(Link *link); int dhcp6_pd_remove(Link *link); int dhcp6_configure(Link *link); +int dhcp6_update_mac(Link *link); int dhcp6_request_address(Link *link, int ir); int dhcp6_request_prefix_delegation(Link *link); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 59a0166cab..bcf193b089 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3043,42 +3043,9 @@ int link_update(Link *link, sd_netlink_message *m) { if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); - if (link->dhcp6_client) { - const DUID* duid = link_get_duid(link); - bool restart = sd_dhcp6_client_is_running(link->dhcp6_client) > 0; - - if (restart) { - r = sd_dhcp6_client_stop(link->dhcp6_client); - if (r < 0) - return log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m"); - } - - r = sd_dhcp6_client_set_mac(link->dhcp6_client, - (const uint8_t *) &link->mac, - sizeof (link->mac), - ARPHRD_ETHER); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); - - if (link->network->iaid_set) { - r = sd_dhcp6_client_set_iaid(link->dhcp6_client, link->network->iaid); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m"); - } - - r = sd_dhcp6_client_set_duid(link->dhcp6_client, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m"); - - if (restart) { - r = sd_dhcp6_client_start(link->dhcp6_client); - if (r < 0) - return log_link_warning_errno(link, r, "Could not restart DHCPv6 client: %m"); - } - } + r = dhcp6_update_mac(link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); if (link->radv) { bool restart = sd_radv_is_running(link->radv); From be9363ccab4410add5bdd6583f77f73309a94a08 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 20:55:18 +0900 Subject: [PATCH 119/138] network: introduce radv_update_mac() --- src/network/networkd-link.c | 22 +++------------------- src/network/networkd-radv.c | 30 ++++++++++++++++++++++++++++++ src/network/networkd-radv.h | 1 + 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index bcf193b089..69cc90544f 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3047,25 +3047,9 @@ int link_update(Link *link, sd_netlink_message *m) { if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); - if (link->radv) { - bool restart = sd_radv_is_running(link->radv); - - if (restart) { - r = sd_radv_stop(link->radv); - if (r < 0) - return log_link_warning_errno(link, r, "Could not stop Router Advertisement: %m"); - } - - r = sd_radv_set_mac(link->radv, &link->mac); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC for Router Advertisement: %m"); - - if (restart) { - r = sd_radv_start(link->radv); - if (r < 0) - return log_link_warning_errno(link, r, "Could not restart Router Advertisement: %m"); - } - } + r = dhcp6_update_mac(link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address for Router Advertisement: %m"); if (link->ndisc) { r = sd_ndisc_set_mac(link->ndisc, &link->mac); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 81350a3e05..dbdbdef80d 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -686,6 +686,36 @@ int radv_configure(Link *link) { return 0; } +int radv_update_mac(Link *link) { + bool restart; + int r; + + assert(link); + + if (!link->radv) + return 0; + + restart = sd_radv_is_running(link->radv); + + if (restart) { + r = sd_radv_stop(link->radv); + if (r < 0) + return r; + } + + r = sd_radv_set_mac(link->radv, &link->mac); + if (r < 0) + return r; + + if (restart) { + r = sd_radv_start(link->radv); + if (r < 0) + return r; + } + + return 0; +} + int radv_add_prefix( Link *link, const struct in6_addr *prefix, diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index af554aeef7..52ea2f2a37 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -50,6 +50,7 @@ void network_verify_route_prefixes(Network *network); int radv_emit_dns(Link *link); int radv_configure(Link *link); +int radv_update_mac(Link *link); int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, uint32_t lifetime_preferred, uint32_t lifetime_valid); From 5e0534f1c13cd50ec2b143a8b18156cd37e502f7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 06:25:44 +0900 Subject: [PATCH 120/138] network: move sysctl related functions to networkd-sysctl.c --- src/network/meson.build | 2 + src/network/networkd-link.c | 292 +-------------------------------- src/network/networkd-link.h | 9 +- src/network/networkd-ndisc.c | 3 +- src/network/networkd-network.c | 44 ----- src/network/networkd-network.h | 14 +- src/network/networkd-sysctl.c | 284 ++++++++++++++++++++++++++++++++ src/network/networkd-sysctl.h | 26 +++ 8 files changed, 321 insertions(+), 353 deletions(-) create mode 100644 src/network/networkd-sysctl.c create mode 100644 src/network/networkd-sysctl.h diff --git a/src/network/meson.build b/src/network/meson.build index 28941b4468..c2a197162f 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -111,6 +111,8 @@ sources = files(''' networkd-speed-meter.h networkd-sriov.c networkd-sriov.h + networkd-sysctl.c + networkd-sysctl.h networkd-util.c networkd-util.h networkd-wifi.c diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 69cc90544f..0f41cae3fd 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -38,6 +38,7 @@ #include "networkd-neighbor.h" #include "networkd-nexthop.h" #include "networkd-sriov.h" +#include "networkd-sysctl.h" #include "networkd-radv.h" #include "networkd-routing-policy-rule.h" #include "networkd-wifi.h" @@ -106,7 +107,7 @@ bool link_ipv6ll_enabled(Link *link) { return link->network->link_local & ADDRESS_FAMILY_IPV6; } -static bool link_ipv6_enabled(Link *link) { +bool link_ipv6_enabled(Link *link) { assert(link); if (!socket_ipv6_is_supported()) @@ -128,71 +129,6 @@ static bool link_ipv6_enabled(Link *link) { return false; } -bool link_ip_forward_enabled(Link *link, int family) { - assert(link); - assert(IN_SET(family, AF_INET, AF_INET6)); - - if (family == AF_INET6 && !socket_ipv6_is_supported()) - return false; - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - return link->network->ip_forward & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6); -} - -static bool link_proxy_arp_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->network->proxy_arp < 0) - return false; - - return true; -} - -static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return _IPV6_PRIVACY_EXTENSIONS_INVALID; - - if (link->flags & IFF_LOOPBACK) - return _IPV6_PRIVACY_EXTENSIONS_INVALID; - - if (!link->network) - return _IPV6_PRIVACY_EXTENSIONS_INVALID; - - return link->network->ipv6_privacy_extensions; -} - -static int link_update_ipv6_sysctl(Link *link) { - bool enabled; - int r; - - if (link->flags & IFF_LOOPBACK) - return 0; - - enabled = link_ipv6_enabled(link); - if (enabled) { - r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false); - if (r < 0) - return log_link_warning_errno(link, r, "Cannot enable IPv6: %m"); - - log_link_info(link, "IPv6 successfully enabled"); - } - - return 0; -} - static bool link_is_enslaved(Link *link) { if (link->flags & IFF_SLAVE) /* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */ @@ -947,19 +883,6 @@ static int link_set_static_configs(Link *link) { return 0; } -static int link_set_proxy_arp(Link *link) { - int r; - - if (!link_proxy_arp_enabled(link)) - return 0; - - r = sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0); - if (r < 0) - log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m"); - - return 0; -} - static int link_configure_continue(Link *link); static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { @@ -1983,179 +1906,6 @@ static int link_enter_join_netdev(Link *link) { return 0; } -static int link_set_ipv4_forward(Link *link) { - int r; - - if (!link_ipv4_forward_enabled(link)) - return 0; - - /* We propagate the forwarding flag from one interface to the - * global setting one way. This means: as long as at least one - * interface was configured at any time that had IP forwarding - * enabled the setting will stay on for good. We do this - * primarily to keep IPv4 and IPv6 packet forwarding behaviour - * somewhat in sync (see below). */ - - r = sysctl_write_ip_property(AF_INET, NULL, "ip_forward", "1"); - if (r < 0) - log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m"); - - return 0; -} - -static int link_set_ipv6_forward(Link *link) { - int r; - - if (!link_ipv6_forward_enabled(link)) - return 0; - - /* On Linux, the IPv6 stack does not know a per-interface - * packet forwarding setting: either packet forwarding is on - * for all, or off for all. We hence don't bother with a - * per-interface setting, but simply propagate the interface - * flag, if it is set, to the global flag, one-way. Note that - * while IPv4 would allow a per-interface flag, we expose the - * same behaviour there and also propagate the setting from - * one to all, to keep things simple (see above). */ - - r = sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1"); - if (r < 0) - log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m"); - - return 0; -} - -static int link_set_ipv6_privacy_extensions(Link *link) { - IPv6PrivacyExtensions s; - int r; - - s = link_ipv6_privacy_extensions(link); - if (s < 0) - return 0; - - r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions); - if (r < 0) - log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m"); - - return 0; -} - -static int link_set_ipv6_accept_ra(Link *link) { - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - r = sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0"); - if (r < 0) - log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m"); - - return 0; -} - -static int link_set_ipv6_dad_transmits(Link *link) { - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - if (link->network->ipv6_dad_transmits < 0) - return 0; - - r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits); - if (r < 0) - log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m"); - - return 0; -} - -static int link_set_ipv6_hop_limit(Link *link) { - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - if (link->network->ipv6_hop_limit < 0) - return 0; - - r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit); - if (r < 0) - log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m"); - - return 0; -} - -static int link_set_ipv6_mtu(Link *link) { - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (link->network->ipv6_mtu == 0) - return 0; - - /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes - * on the interface. Bump up IPv6 MTU bytes to IPV6_MTU_MIN. */ - if (link->network->ipv6_mtu < IPV6_MIN_MTU) { - log_link_notice(link, "Bumping IPv6 MTU to "STRINGIFY(IPV6_MIN_MTU)" byte minimum required"); - link->network->ipv6_mtu = IPV6_MIN_MTU; - } - - r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", link->network->ipv6_mtu); - if (r < 0) { - if (link->mtu < link->network->ipv6_mtu) - log_link_warning(link, "Cannot set IPv6 MTU %"PRIu32" higher than device MTU %"PRIu32, - link->network->ipv6_mtu, link->mtu); - else - log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m"); - } - - link->ipv6_mtu_set = true; - - return 0; -} - -static int link_set_ipv4_accept_local(Link *link) { - int r; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (link->network->ipv4_accept_local < 0) - return 0; - - r = sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local); - if (r < 0) - log_link_warning_errno(link, r, "Cannot set IPv4 accept_local flag for interface: %m"); - - return 0; -} - static int link_enumerate_ipv6_tentative_addresses(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *addr; @@ -2258,46 +2008,14 @@ int link_configure(Link *link) { if (link->iftype == ARPHRD_CAN) return link_configure_can(link); - /* If IPv6 configured that is static IPv6 address and IPv6LL autoconfiguration is enabled - * for this interface, then enable IPv6 */ - (void) link_update_ipv6_sysctl(link); - - r = link_set_proxy_arp(link); + r = link_set_sysctl(link); if (r < 0) - return r; + return r; r = link_set_ipv6_proxy_ndp_addresses(link); if (r < 0) return r; - r = link_set_ipv4_forward(link); - if (r < 0) - return r; - - r = link_set_ipv6_forward(link); - if (r < 0) - return r; - - r = link_set_ipv6_privacy_extensions(link); - if (r < 0) - return r; - - r = link_set_ipv6_accept_ra(link); - if (r < 0) - return r; - - r = link_set_ipv6_dad_transmits(link); - if (r < 0) - return r; - - r = link_set_ipv6_hop_limit(link); - if (r < 0) - return r; - - r = link_set_ipv4_accept_local(link); - if (r < 0) - return r; - r = link_set_flags(link); if (r < 0) return r; @@ -2395,7 +2113,7 @@ static int link_configure_continue(Link *link) { * we must set this here, after we've set device mtu */ r = link_set_ipv6_mtu(link); if (r < 0) - return r; + log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface, ignoring: %m"); if (link_has_carrier(link) || link->network->configure_without_carrier) { r = link_acquire_conf(link); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 43451ee2de..08cfc60c1f 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -221,17 +221,10 @@ int link_save_and_clean(Link *link); int link_carrier_reset(Link *link); bool link_has_carrier(Link *link); +bool link_ipv6_enabled(Link *link); bool link_ipv6ll_enabled(Link *link); int link_ipv6ll_gained(Link *link, const struct in6_addr *address); -bool link_ip_forward_enabled(Link *link, int family); -static inline bool link_ipv4_forward_enabled(Link *link) { - return link_ip_forward_enabled(link, AF_INET); -} -static inline bool link_ipv6_forward_enabled(Link *link) { - return link_ip_forward_enabled(link, AF_INET6); -} - int link_set_mtu(Link *link, uint32_t mtu); bool link_ipv4ll_enabled(Link *link, AddressFamily mask); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 89f2b0475b..0e42e768da 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -14,6 +14,7 @@ #include "networkd-dhcp6.h" #include "networkd-manager.h" #include "networkd-ndisc.h" +#include "networkd-sysctl.h" #include "string-table.h" #include "string-util.h" #include "strv.h" @@ -57,7 +58,7 @@ bool link_ipv6_accept_ra_enabled(Link *link) { */ if (link->network->ipv6_accept_ra < 0) /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */ - return !link_ipv6_forward_enabled(link); + return !link_ip_forward_enabled(link, AF_INET6); else if (link->network->ipv6_accept_ra > 0) /* accept RA even if ip_forward is enabled */ return true; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index e02b7e9586..78b888582b 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -991,50 +991,6 @@ int config_parse_ipv6token( return 0; } -static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = { - [IPV6_PRIVACY_EXTENSIONS_NO] = "no", - [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", - [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions, - IPV6_PRIVACY_EXTENSIONS_YES); - -int config_parse_ipv6_privacy_extensions( - 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) { - - IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(ipv6_privacy_extensions); - - s = ipv6_privacy_extensions_from_string(rvalue); - if (s < 0) { - if (streq(rvalue, "kernel")) - s = _IPV6_PRIVACY_EXTENSIONS_INVALID; - else { - log_syntax(unit, LOG_WARNING, filename, line, 0, - "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue); - return 0; - } - } - - *ipv6_privacy_extensions = s; - - return 0; -} - int config_parse_hostname( const char *unit, const char *filename, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 99cce40533..ad61995ca6 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -21,20 +21,12 @@ #include "networkd-lldp-tx.h" #include "networkd-ndisc.h" #include "networkd-radv.h" +#include "networkd-sysctl.h" #include "networkd-util.h" #include "ordered-set.h" #include "resolve-util.h" #include "socket-netlink.h" -typedef enum IPv6PrivacyExtensions { - /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ - IPV6_PRIVACY_EXTENSIONS_NO, - IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC, - IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ - _IPV6_PRIVACY_EXTENSIONS_MAX, - _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, -} IPv6PrivacyExtensions; - typedef enum KeepConfiguration { KEEP_CONFIGURATION_NO = 0, KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0, @@ -329,7 +321,6 @@ bool network_has_static_ipv6_configurations(Network *network); CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev); CONFIG_PARSER_PROTOTYPE(config_parse_tunnel); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token); -CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions); CONFIG_PARSER_PROTOTYPE(config_parse_domains); CONFIG_PARSER_PROTOTYPE(config_parse_dns); CONFIG_PARSER_PROTOTYPE(config_parse_hostname); @@ -342,9 +333,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode); const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length); -const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; -IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; - const char* keep_configuration_to_string(KeepConfiguration i) _const_; KeepConfiguration keep_configuration_from_string(const char *s) _pure_; diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c new file mode 100644 index 0000000000..c8facbf831 --- /dev/null +++ b/src/network/networkd-sysctl.c @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "missing_network.h" +#include "networkd-link.h" +#include "networkd-network.h" +#include "networkd-sysctl.h" +#include "socket-util.h" +#include "string-table.h" +#include "sysctl-util.h" + +static int link_update_ipv6_sysctl(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link_ipv6_enabled(link)) + return 0; + + return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false); +} + +static int link_set_proxy_arp(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->proxy_arp < 0) + return 0; + + return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0); +} + +bool link_ip_forward_enabled(Link *link, int family) { + assert(link); + assert(IN_SET(family, AF_INET, AF_INET6)); + + if (family == AF_INET6 && !socket_ipv6_is_supported()) + return false; + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + return link->network->ip_forward & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6); +} + +static int link_set_ipv4_forward(Link *link) { + assert(link); + + if (!link_ip_forward_enabled(link, AF_INET)) + return 0; + + /* We propagate the forwarding flag from one interface to the + * global setting one way. This means: as long as at least one + * interface was configured at any time that had IP forwarding + * enabled the setting will stay on for good. We do this + * primarily to keep IPv4 and IPv6 packet forwarding behaviour + * somewhat in sync (see below). */ + + return sysctl_write_ip_property(AF_INET, NULL, "ip_forward", "1"); +} + +static int link_set_ipv6_forward(Link *link) { + assert(link); + + if (!link_ip_forward_enabled(link, AF_INET6)) + return 0; + + /* On Linux, the IPv6 stack does not know a per-interface + * packet forwarding setting: either packet forwarding is on + * for all, or off for all. We hence don't bother with a + * per-interface setting, but simply propagate the interface + * flag, if it is set, to the global flag, one-way. Note that + * while IPv4 would allow a per-interface flag, we expose the + * same behaviour there and also propagate the setting from + * one to all, to keep things simple (see above). */ + + return sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1"); +} + +static int link_set_ipv6_privacy_extensions(Link *link) { + assert(link); + + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions); +} + +static int link_set_ipv6_accept_ra(Link *link) { + assert(link); + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + return sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0"); +} + +static int link_set_ipv6_dad_transmits(Link *link) { + assert(link); + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->ipv6_dad_transmits < 0) + return 0; + + return sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits); +} + +static int link_set_ipv6_hop_limit(Link *link) { + assert(link); + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->ipv6_hop_limit < 0) + return 0; + + return sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit); +} + +static int link_set_ipv4_accept_local(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (link->network->ipv4_accept_local < 0) + return 0; + + return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local > 0); +} + +int link_set_sysctl(Link *link) { + int r; + + assert(link); + + /* If IPv6 configured that is static IPv6 address and IPv6LL autoconfiguration is enabled + * for this interface, then enable IPv6 */ + r = link_update_ipv6_sysctl(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot enable IPv6, ignoring: %m"); + + r = link_set_proxy_arp(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface, ignoring: %m"); + + r = link_set_ipv4_forward(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m"); + + r = link_set_ipv6_forward(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");; + + r = link_set_ipv6_privacy_extensions(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface, ignorign: %m"); + + r = link_set_ipv6_accept_ra(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface, ignoring: %m"); + + r = link_set_ipv6_dad_transmits(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface, ignoring: %m"); + + r = link_set_ipv6_hop_limit(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface, ignoring: %m"); + + r = link_set_ipv4_accept_local(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv4 accept_local flag for interface, ignoring: %m"); + + return 0; +} + +int link_set_ipv6_mtu(Link *link) { + int r; + + assert(link); + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (link->network->ipv6_mtu == 0) + return 0; + + r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", link->network->ipv6_mtu); + if (r < 0) + return r; + + link->ipv6_mtu_set = true; + + return 0; +} + +static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = { + [IPV6_PRIVACY_EXTENSIONS_NO] = "no", + [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", + [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions, + IPV6_PRIVACY_EXTENSIONS_YES); + +int config_parse_ipv6_privacy_extensions( + 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) { + + IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(ipv6_privacy_extensions); + + s = ipv6_privacy_extensions_from_string(rvalue); + if (s < 0) { + if (streq(rvalue, "kernel")) + s = _IPV6_PRIVACY_EXTENSIONS_INVALID; + else { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue); + return 0; + } + } + + *ipv6_privacy_extensions = s; + + return 0; +} diff --git a/src/network/networkd-sysctl.h b/src/network/networkd-sysctl.h new file mode 100644 index 0000000000..a409d8f54f --- /dev/null +++ b/src/network/networkd-sysctl.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "conf-parser.h" + +typedef struct Link Link; + +typedef enum IPv6PrivacyExtensions { + /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ + IPV6_PRIVACY_EXTENSIONS_NO, + IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC, + IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ + _IPV6_PRIVACY_EXTENSIONS_MAX, + _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, +} IPv6PrivacyExtensions; + +bool link_ip_forward_enabled(Link *link, int family); +int link_set_sysctl(Link *link); +int link_set_ipv6_mtu(Link *link); + +const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; +IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions); From acc9fc2f516a09dec002947c16565da6d89934a0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 06:37:12 +0900 Subject: [PATCH 121/138] network: drop unused function --- src/network/networkd-network.c | 45 ---------------------------------- src/network/networkd-network.h | 1 - 2 files changed, 46 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 78b888582b..ec4dc22757 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -946,51 +946,6 @@ int config_parse_domains( } } -int config_parse_ipv6token( - 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) { - - union in_addr_union buffer; - struct in6_addr *token = data; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(token); - - r = in_addr_from_string(AF_INET6, rvalue, &buffer); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse IPv6 token, ignoring: %s", rvalue); - return 0; - } - - if (in_addr_is_null(AF_INET6, &buffer)) { - log_syntax(unit, LOG_WARNING, filename, line, 0, - "IPv6 token cannot be the ANY address, ignoring: %s", rvalue); - return 0; - } - - if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) { - log_syntax(unit, LOG_WARNING, filename, line, 0, - "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue); - return 0; - } - - *token = buffer.in6; - - return 0; -} - int config_parse_hostname( const char *unit, const char *filename, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index ad61995ca6..cbcbb73872 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -320,7 +320,6 @@ bool network_has_static_ipv6_configurations(Network *network); CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev); CONFIG_PARSER_PROTOTYPE(config_parse_tunnel); -CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token); CONFIG_PARSER_PROTOTYPE(config_parse_domains); CONFIG_PARSER_PROTOTYPE(config_parse_dns); CONFIG_PARSER_PROTOTYPE(config_parse_hostname); From 51f5dfd8bafbbff4ceecf6e795b995b400d358fd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 06:50:55 +0900 Subject: [PATCH 122/138] network: move link_enumerate_ipv6_tentative_addresses() --- src/network/networkd-address.c | 50 ++++++++++++++++++++++++++++++++++ src/network/networkd-link.c | 50 ---------------------------------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 82be47aae2..8fc6ca6404 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -571,12 +571,62 @@ static bool link_address_is_dynamic(Link *link, Address *address) { return false; } +static int link_enumerate_ipv6_tentative_addresses(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *addr; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + + r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_GETADDR, 0, AF_INET6); + if (r < 0) + return r; + + r = sd_netlink_call(link->manager->rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (addr = reply; addr; addr = sd_netlink_message_next(addr)) { + unsigned char flags; + int ifindex; + + r = sd_rtnl_message_addr_get_ifindex(addr, &ifindex); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: invalid ifindex, ignoring: %m"); + continue; + } else if (link->ifindex != ifindex) + continue; + + r = sd_rtnl_message_addr_get_flags(addr, &flags); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m"); + continue; + } else if (!(flags & IFA_F_TENTATIVE)) + continue; + + log_link_debug(link, "Found tentative ipv6 link-local address"); + (void) manager_rtnl_process_address(link->manager->rtnl, addr, link->manager); + } + + return 0; +} + int link_drop_foreign_addresses(Link *link) { Address *address; int k, r = 0; assert(link); + /* The kernel doesn't notify us about tentative addresses; + * so if ipv6ll is disabled, we need to enumerate them now so we can drop them below */ + if (!link_ipv6ll_enabled(link)) { + r = link_enumerate_ipv6_tentative_addresses(link); + if (r < 0) + return r; + } + SET_FOREACH(address, link->addresses_foreign) { /* we consider IPv6LL addresses to be managed by the kernel */ if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0f41cae3fd..53242d8e0f 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1906,59 +1906,9 @@ static int link_enter_join_netdev(Link *link) { return 0; } -static int link_enumerate_ipv6_tentative_addresses(Link *link) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *addr; - int r; - - assert(link); - assert(link->manager); - assert(link->manager->rtnl); - - r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_GETADDR, 0, AF_INET6); - if (r < 0) - return r; - - r = sd_netlink_call(link->manager->rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (addr = reply; addr; addr = sd_netlink_message_next(addr)) { - unsigned char flags; - int ifindex; - - r = sd_rtnl_message_addr_get_ifindex(addr, &ifindex); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: invalid ifindex, ignoring: %m"); - continue; - } else if (link->ifindex != ifindex) - continue; - - r = sd_rtnl_message_addr_get_flags(addr, &flags); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m"); - continue; - } else if (!(flags & IFA_F_TENTATIVE)) - continue; - - log_link_debug(link, "Found tentative ipv6 link-local address"); - (void) manager_rtnl_process_address(link->manager->rtnl, addr, link->manager); - } - - return 0; -} - static int link_drop_foreign_config(Link *link) { int r; - /* The kernel doesn't notify us about tentative addresses; - * so if ipv6ll is disabled, we need to enumerate them now so we can drop them below */ - if (!link_ipv6ll_enabled(link)) { - r = link_enumerate_ipv6_tentative_addresses(link); - if (r < 0) - return r; - } - r = link_drop_foreign_addresses(link); if (r < 0) return r; From 2ffd6d73f946d3d1619e06301b71482f2c60b078 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 07:37:22 +0900 Subject: [PATCH 123/138] network: check feature is enabled in xxx_configure() --- src/network/networkd-dhcp4.c | 12 ++++-- src/network/networkd-dhcp4.h | 1 - src/network/networkd-dhcp6.c | 25 +++++++----- src/network/networkd-ipv4ll.c | 5 ++- src/network/networkd-link.c | 69 ++++++++++++---------------------- src/network/networkd-lldp-rx.c | 21 +++++++---- src/network/networkd-lldp-rx.h | 3 -- src/network/networkd-lldp-tx.c | 2 +- src/network/networkd-ndisc.c | 17 ++++++--- 9 files changed, 74 insertions(+), 81 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index c8f4f4bf61..a20f06d6c3 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1157,12 +1157,10 @@ static bool promote_secondaries_enabled(const char *ifname) { * the primary one expires it relies on the kernel to promote the * secondary IP. See also https://github.com/systemd/systemd/issues/7163 */ -int dhcp4_set_promote_secondaries(Link *link) { +static int dhcp4_set_promote_secondaries(Link *link) { int r; assert(link); - assert(link->network); - assert(link->network->dhcp & ADDRESS_FAMILY_IPV4); /* check if the kernel has promote_secondaries enabled for our * interface. If it is not globally enabled or enabled for the @@ -1267,7 +1265,13 @@ int dhcp4_configure(Link *link) { assert(link); assert(link->network); - assert(link->network->dhcp & ADDRESS_FAMILY_IPV4); + + if (!link_dhcp4_enabled(link)) + return 0; + + r = dhcp4_set_promote_secondaries(link); + if (r < 0) + return r; r = dhcp4_init(link); if (r < 0) diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index ee3b4f1288..8aa6ac9453 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -19,7 +19,6 @@ typedef enum DHCPClientIdentifier { int dhcp4_configure(Link *link); int dhcp4_update_mac(Link *link); -int dhcp4_set_promote_secondaries(Link *link); int link_deserialize_dhcp4(Link *link, const char *dhcp4_address); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 5724d083fc..ce9f6ac300 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -25,6 +25,15 @@ #include "radv-internal.h" #include "web-util.h" +bool link_dhcp6_pd_is_enabled(Link *link) { + assert(link); + + if (!link->network) + return false; + + return link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_DHCP6; +} + static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) { uint32_t lifetime_preferred, lifetime_valid; union in_addr_union pd_prefix; @@ -181,6 +190,9 @@ int dhcp6_pd_remove(Link *link) { assert(link); assert(link->manager); + if (!link_dhcp6_pd_is_enabled(link)) + return 0; + link->dhcp6_pd_address_configured = false; link->dhcp6_pd_route_configured = false; @@ -426,13 +438,6 @@ static int dhcp6_pd_assign_prefix(Link *link, const union in_addr_union *prefix, return 0; } -bool link_dhcp6_pd_is_enabled(Link *link) { - if (!link->network) - return false; - - return link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_DHCP6; -} - static bool link_has_preferred_subnet_id(Link *link) { if (!link->network) return false; @@ -644,9 +649,6 @@ static void dhcp6_pd_prefix_lost(Link *dhcp6_link) { if (link == dhcp6_link) continue; - if (!link_dhcp6_pd_is_enabled(link)) - continue; - r = dhcp6_pd_remove(link); if (r < 0) link_enter_failed(link); @@ -1386,6 +1388,9 @@ int dhcp6_configure(Link *link) { assert(link); assert(link->network); + if (!link_dhcp6_enabled(link) && !link_ipv6_accept_ra_enabled(link)) + return 0; + if (link->dhcp6_client) return 0; diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 706393b2f2..b0e0a97ad8 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -166,8 +166,9 @@ int ipv4ll_configure(Link *link) { int r; assert(link); - assert(link->network); - assert(link->network->link_local & (ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)); + + if (!link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) + return 0; r = ipv4ll_init(link); if (r < 0) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 53242d8e0f..b8145ea651 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -638,11 +638,9 @@ int link_stop_clients(Link *link, bool may_keep_dhcp) { r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m"); } - if (link_dhcp6_pd_is_enabled(link)) { - k = dhcp6_pd_remove(link); - if (k < 0) - r = log_link_warning_errno(link, k, "Could not remove DHCPv6 PD addresses and routes: %m"); - } + k = dhcp6_pd_remove(link); + if (k < 0) + r = log_link_warning_errno(link, k, "Could not remove DHCPv6 PD addresses and routes: %m"); if (link->ndisc) { k = sd_ndisc_stop(link->ndisc); @@ -1072,9 +1070,7 @@ static int link_acquire_ipv6_conf(Link *link) { assert(link); - if (link_ipv6_accept_ra_enabled(link)) { - assert(link->ndisc); - + if (link->ndisc) { log_link_debug(link, "Discovering IPv6 routers"); r = sd_ndisc_start(link->ndisc); @@ -1134,9 +1130,7 @@ static int link_acquire_ipv4_conf(Link *link) { return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m"); } - if (link_dhcp4_enabled(link)) { - assert(link->dhcp_client); - + if (link->dhcp_client) { log_link_debug(link, "Acquiring DHCPv4 lease"); r = sd_dhcp_client_start(link->dhcp_client); @@ -1162,11 +1156,9 @@ static int link_acquire_conf(Link *link) { return r; } - if (link_lldp_emit_enabled(link)) { - r = link_lldp_emit_start(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m"); - } + r = link_lldp_emit_start(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m"); return 0; } @@ -1974,44 +1966,29 @@ int link_configure(Link *link) { if (r < 0) return r; - if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) { - r = ipv4ll_configure(link); - if (r < 0) - return r; - } + r = ipv4ll_configure(link); + if (r < 0) + return r; - if (link_dhcp4_enabled(link)) { - r = dhcp4_set_promote_secondaries(link); - if (r < 0) - return r; + r = dhcp4_configure(link); + if (r < 0) + return r; - r = dhcp4_configure(link); - if (r < 0) - return r; - } + r = dhcp6_configure(link); + if (r < 0) + return r; - if (link_dhcp6_enabled(link) || - link_ipv6_accept_ra_enabled(link)) { - r = dhcp6_configure(link); - if (r < 0) - return r; - } - - if (link_ipv6_accept_ra_enabled(link)) { - r = ndisc_configure(link); - if (r < 0) - return r; - } + r = ndisc_configure(link); + if (r < 0) + return r; r = radv_configure(link); if (r < 0) return r; - if (link_lldp_rx_enabled(link)) { - r = link_lldp_rx_configure(link); - if (r < 0) - return r; - } + r = link_lldp_rx_configure(link); + if (r < 0) + return r; r = link_configure_mtu(link); if (r < 0) diff --git a/src/network/networkd-lldp-rx.c b/src/network/networkd-lldp-rx.c index fe88777977..a97bdeda19 100644 --- a/src/network/networkd-lldp-rx.c +++ b/src/network/networkd-lldp-rx.c @@ -25,7 +25,7 @@ static const char* const lldp_mode_table[_LLDP_MODE_MAX] = { DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES); -bool link_lldp_rx_enabled(Link *link) { +static bool link_lldp_rx_enabled(Link *link) { assert(link); if (link->flags & IFF_LOOPBACK) @@ -68,9 +68,18 @@ static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n int link_lldp_rx_configure(Link *link) { int r; - r = sd_lldp_new(&link->lldp); - if (r < 0) - return r; + if (!link_lldp_rx_enabled(link)) + return 0; + + if (!link->lldp) { + r = sd_lldp_new(&link->lldp); + if (r < 0) + return r; + + r = sd_lldp_attach_event(link->lldp, NULL, 0); + if (r < 0) + return r; + } r = sd_lldp_set_ifindex(link->lldp, link->ifindex); if (r < 0) @@ -87,10 +96,6 @@ int link_lldp_rx_configure(Link *link) { if (r < 0) return r; - r = sd_lldp_attach_event(link->lldp, NULL, 0); - if (r < 0) - return r; - r = sd_lldp_set_callback(link->lldp, lldp_handler, link); if (r < 0) return r; diff --git a/src/network/networkd-lldp-rx.h b/src/network/networkd-lldp-rx.h index 12f512f628..8e1a6a0b62 100644 --- a/src/network/networkd-lldp-rx.h +++ b/src/network/networkd-lldp-rx.h @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include - #include "conf-parser.h" typedef struct Link Link; @@ -15,7 +13,6 @@ typedef enum LLDPMode { _LLDP_MODE_INVALID = -1, } LLDPMode; -bool link_lldp_rx_enabled(Link *link); int link_lldp_rx_configure(Link *link); int link_update_lldp(Link *link); int link_lldp_save(Link *link); diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c index 2be7c27e18..c8e56a5fec 100644 --- a/src/network/networkd-lldp-tx.c +++ b/src/network/networkd-lldp-tx.c @@ -367,7 +367,7 @@ int link_lldp_emit_start(Link *link) { assert(link); - if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) { + if (!link_lldp_emit_enabled(link)) { link_lldp_emit_stop(link); return 0; } diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 0e42e768da..a60c42528b 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1226,13 +1226,18 @@ int ndisc_configure(Link *link) { assert(link); - r = sd_ndisc_new(&link->ndisc); - if (r < 0) - return r; + if (!link_ipv6_accept_ra_enabled(link)) + return 0; - r = sd_ndisc_attach_event(link->ndisc, NULL, 0); - if (r < 0) - return r; + if (!link->ndisc) { + r = sd_ndisc_new(&link->ndisc); + if (r < 0) + return r; + + r = sd_ndisc_attach_event(link->ndisc, NULL, 0); + if (r < 0) + return r; + } r = sd_ndisc_set_mac(link->ndisc, &link->mac); if (r < 0) From 4cf85000674032f27910718ec264f8a124fa3e48 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 07:43:41 +0900 Subject: [PATCH 124/138] network: use sd_event stored in Manager --- src/network/networkd-address.c | 2 +- src/network/networkd-dhcp4.c | 2 +- src/network/networkd-dhcp6.c | 2 +- src/network/networkd-lldp-rx.c | 3 ++- src/network/networkd-ndisc.c | 2 +- src/network/networkd-radv.c | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 8fc6ca6404..2f93a6ea46 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1377,7 +1377,7 @@ static int ipv4_dad_configure(Link *link, Address *address) { if (r < 0) return r; - r = sd_ipv4acd_attach_event(address->acd, NULL, 0); + r = sd_ipv4acd_attach_event(address->acd, link->manager->event, 0); if (r < 0) return r; diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index a20f06d6c3..d4a8f98570 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -623,7 +623,7 @@ static int configure_dhcpv4_duplicate_address_detection(Link *link) { if (r < 0) return r; - r = sd_ipv4acd_attach_event(link->network->dhcp_acd, NULL, 0); + r = sd_ipv4acd_attach_event(link->network->dhcp_acd, link->manager->event, 0); if (r < 0) return r; diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index ce9f6ac300..ea331c95db 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -1400,7 +1400,7 @@ int dhcp6_configure(Link *link) { if (r < 0) return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to create DHCP6 client: %m"); - r = sd_dhcp6_client_attach_event(client, NULL, 0); + r = sd_dhcp6_client_attach_event(client, link->manager->event, 0); if (r < 0) return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to attach event: %m"); diff --git a/src/network/networkd-lldp-rx.c b/src/network/networkd-lldp-rx.c index a97bdeda19..65a8a314d6 100644 --- a/src/network/networkd-lldp-rx.c +++ b/src/network/networkd-lldp-rx.c @@ -9,6 +9,7 @@ #include "networkd-link.h" #include "networkd-lldp-rx.h" #include "networkd-lldp-tx.h" +#include "networkd-manager.h" #include "networkd-network.h" #include "string-table.h" #include "string-util.h" @@ -76,7 +77,7 @@ int link_lldp_rx_configure(Link *link) { if (r < 0) return r; - r = sd_lldp_attach_event(link->lldp, NULL, 0); + r = sd_lldp_attach_event(link->lldp, link->manager->event, 0); if (r < 0) return r; } diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index a60c42528b..2599ec2232 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1234,7 +1234,7 @@ int ndisc_configure(Link *link) { if (r < 0) return r; - r = sd_ndisc_attach_event(link->ndisc, NULL, 0); + r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0); if (r < 0) return r; } diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index dbdbdef80d..bf906d517b 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -624,7 +624,7 @@ int radv_configure(Link *link) { if (r < 0) return r; - r = sd_radv_attach_event(link->radv, NULL, 0); + r = sd_radv_attach_event(link->radv, link->manager->event, 0); if (r < 0) return r; From f5ee7d74af4ab74aa9b1841af7ae40f356243d2d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 08:14:27 +0900 Subject: [PATCH 125/138] network: fix indentation --- src/network/networkd-address.c | 70 +++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 2f93a6ea46..cf83da47f4 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1489,7 +1489,8 @@ int config_parse_broadcast( return 0; } -int config_parse_address(const char *unit, +int config_parse_address( + const char *unit, const char *filename, unsigned line, const char *section, @@ -1619,16 +1620,18 @@ int config_parse_label( return 0; } -int config_parse_lifetime(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) { +int config_parse_lifetime( + 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) { + Network *network = userdata; _cleanup_(address_free_or_set_invalidp) Address *n = NULL; uint32_t k; @@ -1666,16 +1669,18 @@ int config_parse_lifetime(const char *unit, return 0; } -int config_parse_address_flags(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) { +int config_parse_address_flags( + 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) { + Network *network = userdata; _cleanup_(address_free_or_set_invalidp) Address *n = NULL; int r; @@ -1719,16 +1724,18 @@ int config_parse_address_flags(const char *unit, return 0; } -int config_parse_address_scope(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) { +int config_parse_address_scope( + 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) { + Network *network = userdata; _cleanup_(address_free_or_set_invalidp) Address *n = NULL; int r; @@ -1779,6 +1786,7 @@ int config_parse_duplicate_address_detection( const char *rvalue, void *data, void *userdata) { + Network *network = userdata; _cleanup_(address_free_or_set_invalidp) Address *n = NULL; AddressFamily a; From eaff204f099a8c23048f7f247fbc78cf86c75021 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 08:27:14 +0900 Subject: [PATCH 126/138] network: do not update Address::flags in address_configure() --- src/network/networkd-address.c | 46 +++++++----------------- src/network/networkd-address.h | 4 --- src/network/networkd-dhcp4.c | 2 +- src/network/networkd-network-gperf.gperf | 10 +++--- 4 files changed, 19 insertions(+), 43 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index cf83da47f4..78c8a3f043 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -48,7 +48,6 @@ int address_new(Address **ret) { .cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME, .cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME, .duplicate_address_detection = ADDRESS_FAMILY_IPV6, - .prefix_route = true, }; *ret = TAKE_PTR(address); @@ -754,6 +753,7 @@ static int address_acquire(Link *link, Address *original, Address **ret) { if (r < 0) return r; + na->flags = original->flags; na->family = original->family; na->prefixlen = original->prefixlen; na->scope = original->scope; @@ -787,6 +787,7 @@ int address_configure( _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; Address *acquired_address, *a; + uint32_t flags; int r; assert(address); @@ -829,29 +830,13 @@ int address_configure( if (r < 0) return log_link_error_errno(link, r, "Could not set prefixlen: %m"); - address->flags |= IFA_F_PERMANENT; - - if (address->home_address) - address->flags |= IFA_F_HOMEADDRESS; - - if (!FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6)) - address->flags |= IFA_F_NODAD; - - if (address->manage_temporary_address) - address->flags |= IFA_F_MANAGETEMPADDR; - - if (!address->prefix_route) - address->flags |= IFA_F_NOPREFIXROUTE; - - if (address->autojoin) - address->flags |= IFA_F_MCAUTOJOIN; - - r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff)); + flags = address->flags | IFA_F_PERMANENT; + r = sd_rtnl_message_addr_set_flags(req, flags & 0xff); if (r < 0) return log_link_error_errno(link, r, "Could not set flags: %m"); - if (address->flags & ~0xff) { - r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags); + if (flags & ~0xff) { + r = sd_netlink_message_append_u32(req, IFA_FLAGS, flags); if (r < 0) return log_link_error_errno(link, r, "Could not set extended flags: %m"); } @@ -1707,18 +1692,10 @@ int config_parse_address_flags( return 0; } - if (streq(lvalue, "HomeAddress")) - n->home_address = r; - else if (streq(lvalue, "ManageTemporaryAddress")) - n->manage_temporary_address = r; - else if (streq(lvalue, "PrefixRoute")) - n->prefix_route = !r; - else if (streq(lvalue, "AddPrefixRoute")) - n->prefix_route = r; - else if (streq(lvalue, "AutoJoin")) - n->autojoin = r; - else - assert_not_reached("Invalid address flag type."); + if (streq(lvalue, "AddPrefixRoute")) + r = !r; + + SET_FLAG(n->flags, ltype, r); n = NULL; return 0; @@ -1852,6 +1829,9 @@ static int address_section_verify(Address *address) { if (!address->scope_set && in_addr_is_localhost(address->family, &address->in_addr) > 0) address->scope = RT_SCOPE_HOST; + if (!FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6)) + address->flags |= IFA_F_NODAD; + return 0; } diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index ec1f51927e..e935b6ffa9 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -38,10 +38,6 @@ typedef struct Address { bool scope_set:1; bool ip_masquerade_done:1; - bool manage_temporary_address:1; - bool home_address:1; - bool prefix_route:1; - bool autojoin:1; AddressFamily duplicate_address_detection; /* Called when address become ready */ diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index d4a8f98570..ed4d7c34e4 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -815,7 +815,7 @@ static int dhcp4_update_address(Link *link, bool announce) { addr->cinfo.ifa_valid = lifetime; addr->prefixlen = prefixlen; addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr; - addr->prefix_route = link_prefixroute(link); + SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link)); /* allow reusing an existing address and simply update its lifetime * in case it already exists */ diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index a5680adc16..21d2e820e9 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -131,11 +131,11 @@ Address.Peer, config_parse_address, Address.Broadcast, config_parse_broadcast, 0, 0 Address.Label, config_parse_label, 0, 0 Address.PreferredLifetime, config_parse_lifetime, 0, 0 -Address.HomeAddress, config_parse_address_flags, 0, 0 -Address.ManageTemporaryAddress, config_parse_address_flags, 0, 0 -Address.PrefixRoute, config_parse_address_flags, 0, 0 /* deprecated */ -Address.AddPrefixRoute, config_parse_address_flags, 0, 0 -Address.AutoJoin, config_parse_address_flags, 0, 0 +Address.HomeAddress, config_parse_address_flags, IFA_F_HOMEADDRESS, 0 +Address.ManageTemporaryAddress, config_parse_address_flags, IFA_F_MANAGETEMPADDR, 0 +Address.PrefixRoute, config_parse_address_flags, IFA_F_NOPREFIXROUTE, 0 /* deprecated */ +Address.AddPrefixRoute, config_parse_address_flags, IFA_F_NOPREFIXROUTE, 0 +Address.AutoJoin, config_parse_address_flags, IFA_F_MCAUTOJOIN, 0 Address.DuplicateAddressDetection, config_parse_duplicate_address_detection, 0, 0 Address.Scope, config_parse_address_scope, 0, 0 IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0 From cde1f0e8fcf07eec2a19eae89090326dbb565707 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 08:47:42 +0900 Subject: [PATCH 127/138] network: introduce address_copy() --- src/network/networkd-address.c | 37 ++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 78c8a3f043..89b17d3147 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -215,6 +215,29 @@ bool address_equal(Address *a1, Address *a2) { return address_compare_func(a1, a2) == 0; } +static int address_copy(Address *dest, const Address *src) { + int r; + + assert(dest); + assert(src); + + r = free_and_strdup(&dest->label, src->label); + if (r < 0) + return r; + + dest->family = src->family; + dest->prefixlen = src->prefixlen; + dest->scope = src->scope; + dest->flags = src->flags; + dest->broadcast = src->broadcast; + dest->cinfo = src->cinfo; + dest->in_addr = src->in_addr; + dest->in_addr_peer = src->in_addr_peer; + dest->duplicate_address_detection = src->duplicate_address_detection; + + return 0; +} + static int address_establish(Address *address, Link *link) { bool masq; int r; @@ -753,17 +776,9 @@ static int address_acquire(Link *link, Address *original, Address **ret) { if (r < 0) return r; - na->flags = original->flags; - na->family = original->family; - na->prefixlen = original->prefixlen; - na->scope = original->scope; - na->cinfo = original->cinfo; - - if (original->label) { - na->label = strdup(original->label); - if (!na->label) - return -ENOMEM; - } + r = address_copy(na, original); + if (r < 0) + return r; na->broadcast = broadcast; na->in_addr = in_addr; From 693ec5ca835b9693a6a0354e120a084f1679fb86 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 7 Oct 2020 02:57:54 +0900 Subject: [PATCH 128/138] network: constify one argument --- src/network/networkd-address.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 89b17d3147..a79b99b35a 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -733,7 +733,7 @@ int link_drop_addresses(Link *link) { return r; } -static int address_acquire(Link *link, Address *original, Address **ret) { +static int address_acquire(Link *link, const Address *original, Address **ret) { union in_addr_union in_addr = IN_ADDR_NULL; struct in_addr broadcast = {}; _cleanup_(address_freep) Address *na = NULL; From 490ccbd5e5580c907121c39be567767f05bd91a3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 09:14:15 +0900 Subject: [PATCH 129/138] network: configure IPv4 DAD per link address Previously, IPv4 DAD is configured in each Address object stored in Network object. If a .network file matches multipe links, then it causes an assertion. To prevent it, now IPv4 DAD is configured in each Address object belogs to Link object. --- src/network/networkd-address.c | 81 +++++++++++++--------------------- src/network/networkd-address.h | 4 +- src/network/networkd-link.c | 6 +-- 3 files changed, 34 insertions(+), 57 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index a79b99b35a..0d2fa60edd 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -106,7 +106,7 @@ Address *address_free(Address *address) { ordered_hashmap_remove(address->network->addresses_by_section, address->section); } - if (address->link && !address->acd) { + if (address->link) { NDiscAddress *n; set_remove(address->link->addresses, address); @@ -793,6 +793,8 @@ static int address_acquire(Link *link, const Address *original, Address **ret) { return 1; } +static int ipv4_dad_configure(Address *address); + int address_configure( Address *address, Link *link, @@ -905,16 +907,8 @@ int address_configure( return log_link_error_errno(link, r, "Could not add address: %m"); } - if (address->acd) { - assert(address->family == AF_INET); - if (DEBUG_LOGGING) { - _cleanup_free_ char *pretty = NULL; - - (void) in_addr_to_string(address->family, &address->in_addr, &pretty); - log_link_debug(link, "Starting IPv4ACD client. Probing address %s", strna(pretty)); - } - - r = sd_ipv4acd_start(address->acd, true); + if (FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) { + r = ipv4_dad_configure(a); if (r < 0) log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m"); } @@ -1363,29 +1357,37 @@ static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { return; } -static int ipv4_dad_configure(Link *link, Address *address) { +static int ipv4_dad_configure(Address *address) { int r; - assert(link); assert(address); - assert(address->family == AF_INET); - assert(!address->link && address->network); + assert(address->link); - address->link = link; + if (address->family != AF_INET) + return 0; - r = sd_ipv4acd_new(&address->acd); + if (DEBUG_LOGGING) { + _cleanup_free_ char *pretty = NULL; + + (void) in_addr_to_string(address->family, &address->in_addr, &pretty); + log_link_debug(address->link, "Starting IPv4ACD client. Probing address %s", strna(pretty)); + } + + if (!address->acd) { + r = sd_ipv4acd_new(&address->acd); + if (r < 0) + return r; + + r = sd_ipv4acd_attach_event(address->acd, address->link->manager->event, 0); + if (r < 0) + return r; + } + + r = sd_ipv4acd_set_ifindex(address->acd, address->link->ifindex); if (r < 0) return r; - r = sd_ipv4acd_attach_event(address->acd, link->manager->event, 0); - if (r < 0) - return r; - - r = sd_ipv4acd_set_ifindex(address->acd, link->ifindex); - if (r < 0) - return r; - - r = sd_ipv4acd_set_mac(address->acd, &link->mac); + r = sd_ipv4acd_set_mac(address->acd, &address->link->mac); if (r < 0) return r; @@ -1397,37 +1399,16 @@ static int ipv4_dad_configure(Link *link, Address *address) { if (r < 0) return r; - return 0; + return sd_ipv4acd_start(address->acd, true); } -int link_configure_ipv4_dad(Link *link) { - Address *address; - int r; - - assert(link); - assert(link->network); - - ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section) - if (address->family == AF_INET && - FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) { - r = ipv4_dad_configure(link, address); - if (r < 0) - return log_link_error_errno(link, r, "Failed to configure IPv4ACD: %m"); - } - - return 0; -} - -int link_stop_ipv4_dad(Link *link) { +int ipv4_dad_stop(Link *link) { Address *address; int k, r = 0; assert(link); - if (!link->network) - return 0; - - ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section) { + SET_FOREACH(address, link->addresses) { if (!address->acd) continue; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index e935b6ffa9..816e84550b 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -64,8 +64,8 @@ int link_drop_addresses(Link *link); int link_drop_foreign_addresses(Link *link); int link_serialize_addresses(Link *link, FILE *f); int link_deserialize_addresses(Link *link, const char *addresses); -int link_configure_ipv4_dad(Link *link); -int link_stop_ipv4_dad(Link *link); + +int ipv4_dad_stop(Link *link); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index b8145ea651..ce708edabb 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -628,7 +628,7 @@ int link_stop_clients(Link *link, bool may_keep_dhcp) { r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m"); } - k = link_stop_ipv4_dad(link); + k = ipv4_dad_stop(link); if (k < 0) r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client: %m"); @@ -1998,10 +1998,6 @@ int link_configure(Link *link) { if (r < 0) return r; - r = link_configure_ipv4_dad(link); - if (r < 0) - return r; - return link_configure_continue(link); } From d93d655c406554f53e2c80e1aceee1440adfd4d6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 09:27:42 +0900 Subject: [PATCH 130/138] network: update MAC address in IPv4 ACD clients When the MAC address of a link is updated, an address on the link may be under checking address duplication. Or, (currently such code is not implemented yet, but) address duplication check may be restarted later. For that case, the IPv4 ACD clients must use the new updated MAC address. --- src/network/networkd-address.c | 45 ++++++++++++++++++++++++++++++++++ src/network/networkd-address.h | 1 + src/network/networkd-link.c | 4 +++ 3 files changed, 50 insertions(+) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 0d2fa60edd..000f8cfa93 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1402,6 +1402,51 @@ static int ipv4_dad_configure(Address *address) { return sd_ipv4acd_start(address->acd, true); } +static int ipv4_dad_update_mac_one(Address *address) { + bool running; + int r; + + assert(address); + + if (!address->acd) + return 0; + + running = sd_ipv4acd_is_running(address->acd); + + if (running) { + r = sd_ipv4acd_stop(address->acd); + if (r < 0) + return r; + } + + r = sd_ipv4acd_set_mac(address->acd, &address->link->mac); + if (r < 0) + return r; + + if (running) { + r = sd_ipv4acd_start(address->acd, true); + if (r < 0) + return r; + } + + return 0; +} + +int ipv4_dad_update_mac(Link *link) { + Address *address; + int k, r = 0; + + assert(link); + + SET_FOREACH(address, link->addresses) { + k = ipv4_dad_update_mac_one(address); + if (k < 0 && r >= 0) + r = k; + } + + return r; +} + int ipv4_dad_stop(Link *link) { Address *address; int k, r = 0; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 816e84550b..88dbefc126 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -66,6 +66,7 @@ int link_serialize_addresses(Link *link, FILE *f); int link_deserialize_addresses(Link *link, const char *addresses); int ipv4_dad_stop(Link *link); +int ipv4_dad_update_mac(Link *link); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index ce708edabb..b32a436be5 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2697,6 +2697,10 @@ int link_update(Link *link, sd_netlink_message *m) { if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC for NDisc: %m"); } + + r = ipv4_dad_update_mac(link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in IPv4 ACD client: %m"); } old_master = link->master_ifindex; From cd1caf30c0bd0d0c6e8df7610c614f52a7345c40 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 10:57:03 +0900 Subject: [PATCH 131/138] network: always use RT_SCOPE_HOST for IPv4 loopback addresses For IPv6 case, use RT_SCOPE_HOST only when scope is not explicitly specified. --- src/network/networkd-address.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 000f8cfa93..58d2ffe3f2 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1867,8 +1867,19 @@ static int address_section_verify(Address *address) { address->section->filename, address->section->line); } - if (!address->scope_set && in_addr_is_localhost(address->family, &address->in_addr) > 0) + if (in_addr_is_localhost(address->family, &address->in_addr) > 0 && + (address->family == AF_INET || !address->scope_set)) { + /* For IPv4, scope must be always RT_SCOPE_HOST. + * For IPv6, use RT_SCOPE_HOST only when it is not explicitly specified. */ + + if (address->scope_set && address->scope != RT_SCOPE_HOST) + log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: non-host scope is set in the [Address] section from line %u. " + "Ignoring Scope= setting.", + address->section->filename, address->section->line); + address->scope = RT_SCOPE_HOST; + } if (!FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6)) address->flags |= IFA_F_NODAD; From 494b6b43cb232aeb49ea977154fe5d4fb17b8e88 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 11:06:23 +0900 Subject: [PATCH 132/138] network: fix masquerade setting logic Previously, address_establish() took Address object stored in Network object. And address_release() took Address object stored in Link object. Thus, address_release() always did nothing. --- src/network/networkd-address.c | 85 ++++++++++++++-------------------- 1 file changed, 36 insertions(+), 49 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 58d2ffe3f2..6e58ac9782 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -238,29 +238,38 @@ static int address_copy(Address *dest, const Address *src) { return 0; } -static int address_establish(Address *address, Link *link) { - bool masq; +static int address_set_masquerade(Address *address, bool add) { + union in_addr_union masked; int r; assert(address); - assert(link); + assert(address->link); - masq = link->network && - link->network->ip_masquerade && - address->family == AF_INET && - address->scope < RT_SCOPE_LINK; + if (!address->link->network) + return 0; - /* Add firewall entry if this is requested */ - if (address->ip_masquerade_done != masq) { - union in_addr_union masked = address->in_addr; - in_addr_mask(address->family, &masked, address->prefixlen); + if (!address->link->network->ip_masquerade) + return 0; - r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); - if (r < 0) - return r; + if (address->family != AF_INET) + return 0; - address->ip_masquerade_done = masq; - } + if (address->scope >= RT_SCOPE_LINK) + return 0; + + if (address->ip_masquerade_done == add) + return 0; + + masked = address->in_addr; + r = in_addr_mask(address->family, &masked, address->prefixlen); + if (r < 0) + return r; + + r = fw_add_masquerade(add, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); + if (r < 0) + return r; + + address->ip_masquerade_done = add; return 0; } @@ -334,27 +343,6 @@ static int address_add(Link *link, int family, const union in_addr_union *in_add return 0; } -static int address_release(Address *address) { - int r; - - assert(address); - assert(address->link); - - /* Remove masquerading firewall entry if it was added */ - if (address->ip_masquerade_done) { - union in_addr_union masked = address->in_addr; - in_addr_mask(address->family, &masked, address->prefixlen); - - r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); - if (r < 0) - return r; - - address->ip_masquerade_done = false; - } - - return 0; -} - static int address_update( Address *address, unsigned char flags, @@ -410,7 +398,7 @@ static int address_drop(Address *address) { ready = address_is_ready(address); link = address->link; - r = address_release(address); + r = address_set_masquerade(address, false); if (r < 0) log_link_warning_errno(link, r, "Failed to disable IP masquerading, ignoring: %m"); @@ -886,27 +874,26 @@ int address_configure( if (r < 0) return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m"); - r = address_establish(address, link); + if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer)) + r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, &a); + else + r = address_add(link, address->family, &address->in_addr, address->prefixlen, &a); + if (r < 0) + return log_link_error_errno(link, r, "Could not add address: %m"); + + a->scope = address->scope; + r = address_set_masquerade(a, true); if (r < 0) log_link_warning_errno(link, r, "Could not enable IP masquerading, ignoring: %m"); r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link); if (r < 0) { - address_release(address); + (void) address_set_masquerade(a, false); return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); } link_ref(link); - if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer)) - r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, &a); - else - r = address_add(link, address->family, &address->in_addr, address->prefixlen, &a); - if (r < 0) { - address_release(address); - return log_link_error_errno(link, r, "Could not add address: %m"); - } - if (FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) { r = ipv4_dad_configure(a); if (r < 0) From 13ffa39f8ee30edae557875e710d136bdd6e1fca Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 7 Oct 2020 03:21:59 +0900 Subject: [PATCH 133/138] network: rename network_verify_xxx() -> network_drop_invalid_xxx() As 'verify' implies a boolean result. --- src/network/networkd-address-label.c | 2 +- src/network/networkd-address-label.h | 2 +- src/network/networkd-address.c | 2 +- src/network/networkd-address.h | 2 +- src/network/networkd-fdb.c | 2 +- src/network/networkd-fdb.h | 2 +- src/network/networkd-mdb.c | 2 +- src/network/networkd-mdb.h | 2 +- src/network/networkd-neighbor.c | 2 +- src/network/networkd-neighbor.h | 2 +- src/network/networkd-network.c | 24 +++++++++++----------- src/network/networkd-nexthop.c | 2 +- src/network/networkd-nexthop.h | 2 +- src/network/networkd-radv.c | 4 ++-- src/network/networkd-radv.h | 4 ++-- src/network/networkd-route.c | 2 +- src/network/networkd-route.h | 2 +- src/network/networkd-routing-policy-rule.c | 2 +- src/network/networkd-routing-policy-rule.h | 2 +- src/network/networkd-sriov.c | 2 +- src/network/networkd-sriov.h | 2 +- src/network/tc/tc.c | 2 +- src/network/tc/tc.h | 2 +- 23 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index e83665bfda..66b192256e 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -151,7 +151,7 @@ int link_set_address_labels(Link *link) { return 0; } -void network_verify_address_labels(Network *network) { +void network_drop_invalid_address_labels(Network *network) { AddressLabel *label; assert(network); diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index aacab867e7..b92828c72e 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -21,7 +21,7 @@ typedef struct AddressLabel { AddressLabel *address_label_free(AddressLabel *label); -void network_verify_address_labels(Network *network); +void network_drop_invalid_address_labels(Network *network); int link_set_address_labels(Link *link); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 6e58ac9782..7407eeec9b 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1874,7 +1874,7 @@ static int address_section_verify(Address *address) { return 0; } -void network_verify_addresses(Network *network) { +void network_drop_invalid_addresses(Network *network) { Address *address; assert(network); diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 88dbefc126..431e507851 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -70,7 +70,7 @@ int ipv4_dad_update_mac(Link *link); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); -void network_verify_addresses(Network *network); +void network_drop_invalid_addresses(Network *network); void address_hash_func(const Address *a, struct siphash *state); int address_compare_func(const Address *a1, const Address *a2); diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 47db929187..2e35f7d1bf 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -185,7 +185,7 @@ int link_set_bridge_fdb(Link *link) { return 0; } -void network_verify_fdb_entries(Network *network) { +void network_drop_invalid_fdb_entries(Network *network) { FdbEntry *fdb_entry; assert(network); diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h index 4aeb8be9ce..935406e022 100644 --- a/src/network/networkd-fdb.h +++ b/src/network/networkd-fdb.h @@ -41,7 +41,7 @@ typedef struct FdbEntry { FdbEntry *fdb_entry_free(FdbEntry *fdb_entry); -void network_verify_fdb_entries(Network *network); +void network_drop_invalid_fdb_entries(Network *network); int link_set_bridge_fdb(Link *link); diff --git a/src/network/networkd-mdb.c b/src/network/networkd-mdb.c index 169cc6eb00..bca3e620dd 100644 --- a/src/network/networkd-mdb.c +++ b/src/network/networkd-mdb.c @@ -278,7 +278,7 @@ static int mdb_entry_verify(MdbEntry *mdb_entry) { return 0; } -void network_verify_mdb_entries(Network *network) { +void network_drop_invalid_mdb_entries(Network *network) { MdbEntry *mdb_entry; assert(network); diff --git a/src/network/networkd-mdb.h b/src/network/networkd-mdb.h index e0d9052497..563a9e6d99 100644 --- a/src/network/networkd-mdb.h +++ b/src/network/networkd-mdb.h @@ -21,7 +21,7 @@ typedef struct MdbEntry { MdbEntry *mdb_entry_free(MdbEntry *mdb_entry); -void network_verify_mdb_entries(Network *network); +void network_drop_invalid_mdb_entries(Network *network); int link_set_bridge_mdb(Link *link); diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index c14c8f7e06..b553f1707e 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -591,7 +591,7 @@ static int neighbor_section_verify(Neighbor *neighbor) { return 0; } -void network_verify_neighbors(Network *network) { +void network_drop_invalid_neighbors(Network *network) { Neighbor *neighbor; assert(network); diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index f40fdccc48..bb403ef2da 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -32,7 +32,7 @@ typedef struct Neighbor { Neighbor *neighbor_free(Neighbor *neighbor); -void network_verify_neighbors(Network *network); +void network_drop_invalid_neighbors(Network *network); int link_set_neighbors(Link *link); int link_drop_neighbors(Link *link); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index ec4dc22757..1ef3a6a6d8 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -287,18 +287,18 @@ int network_verify(Network *network) { network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses); } - network_verify_addresses(network); - network_verify_routes(network); - network_verify_nexthops(network); - network_verify_fdb_entries(network); - network_verify_mdb_entries(network); - network_verify_neighbors(network); - network_verify_address_labels(network); - network_verify_prefixes(network); - network_verify_route_prefixes(network); - network_verify_routing_policy_rules(network); - network_verify_traffic_control(network); - network_verify_sr_iov(network); + network_drop_invalid_addresses(network); + network_drop_invalid_routes(network); + network_drop_invalid_nexthops(network); + network_drop_invalid_fdb_entries(network); + network_drop_invalid_mdb_entries(network); + network_drop_invalid_neighbors(network); + network_drop_invalid_address_labels(network); + network_drop_invalid_prefixes(network); + network_drop_invalid_route_prefixes(network); + network_drop_invalid_routing_policy_rules(network); + network_drop_invalid_traffic_control(network); + network_drop_invalid_sr_iov(network); return 0; } diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 1f03cbfe07..6edeaabf88 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -449,7 +449,7 @@ static int nexthop_section_verify(NextHop *nh) { return 0; } -void network_verify_nexthops(Network *network) { +void network_drop_invalid_nexthops(Network *network) { NextHop *nh; assert(network); diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index f286f0e61e..3cdb068efd 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -31,7 +31,7 @@ typedef struct NextHop { NextHop *nexthop_free(NextHop *nexthop); -void network_verify_nexthops(Network *network); +void network_drop_invalid_nexthops(Network *network); int link_set_nexthop(Link *link); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index bf906d517b..1167f2865f 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -160,7 +160,7 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig return 0; } -void network_verify_prefixes(Network *network) { +void network_drop_invalid_prefixes(Network *network) { Prefix *prefix; assert(network); @@ -170,7 +170,7 @@ void network_verify_prefixes(Network *network) { prefix_free(prefix); } -void network_verify_route_prefixes(Network *network) { +void network_drop_invalid_route_prefixes(Network *network) { RoutePrefix *prefix; assert(network); diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 52ea2f2a37..fbb93a9acc 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -45,8 +45,8 @@ typedef struct RoutePrefix { Prefix *prefix_free(Prefix *prefix); RoutePrefix *route_prefix_free(RoutePrefix *prefix); -void network_verify_prefixes(Network *network); -void network_verify_route_prefixes(Network *network); +void network_drop_invalid_prefixes(Network *network); +void network_drop_invalid_route_prefixes(Network *network); int radv_emit_dns(Link *link); int radv_configure(Link *link); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index c8ae8d5bce..659fecbf2e 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -2212,7 +2212,7 @@ static int route_section_verify(Route *route, Network *network) { return 0; } -void network_verify_routes(Network *network) { +void network_drop_invalid_routes(Network *network) { Route *route; assert(network); diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index ada1059aad..3347c7c57b 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -89,7 +89,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma int network_add_ipv4ll_route(Network *network); int network_add_default_route_on_device(Network *network); -void network_verify_routes(Network *network); +void network_drop_invalid_routes(Network *network); CONFIG_PARSER_PROTOTYPE(config_parse_gateway); CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 588c36f306..de60bd9555 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -1473,7 +1473,7 @@ static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { return 0; } -void network_verify_routing_policy_rules(Network *network) { +void network_drop_invalid_routing_policy_rules(Network *network) { RoutingPolicyRule *rule; assert(network); diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index ac5cbbed0e..bc1193a111 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -50,7 +50,7 @@ typedef struct RoutingPolicyRule { RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule); -void network_verify_routing_policy_rules(Network *network); +void network_drop_invalid_routing_policy_rules(Network *network); int link_set_routing_policy_rules(Link *link); diff --git a/src/network/networkd-sriov.c b/src/network/networkd-sriov.c index d2a389d95d..61382a8993 100644 --- a/src/network/networkd-sriov.c +++ b/src/network/networkd-sriov.c @@ -262,7 +262,7 @@ static int sr_iov_section_verify(SRIOV *sr_iov) { return 0; } -void network_verify_sr_iov(Network *network) { +void network_drop_invalid_sr_iov(Network *network) { SRIOV *sr_iov; assert(network); diff --git a/src/network/networkd-sriov.h b/src/network/networkd-sriov.h index acd9f9b753..8a48545d64 100644 --- a/src/network/networkd-sriov.h +++ b/src/network/networkd-sriov.h @@ -35,7 +35,7 @@ typedef struct SRIOV { SRIOV *sr_iov_free(SRIOV *sr_iov); int link_configure_sr_iov(Link *link); -void network_verify_sr_iov(Network *network); +void network_drop_invalid_sr_iov(Network *network); DEFINE_NETWORK_SECTION_FUNCTIONS(SRIOV, sr_iov_free); diff --git a/src/network/tc/tc.c b/src/network/tc/tc.c index 2bb9c8f07f..974bb8c822 100644 --- a/src/network/tc/tc.c +++ b/src/network/tc/tc.c @@ -69,7 +69,7 @@ static int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_ro } } -void network_verify_traffic_control(Network *network) { +void network_drop_invalid_traffic_control(Network *network) { bool has_root = false, has_clsact = false; TrafficControl *tc; diff --git a/src/network/tc/tc.h b/src/network/tc/tc.h index 7e277f6323..916ad3300a 100644 --- a/src/network/tc/tc.h +++ b/src/network/tc/tc.h @@ -29,4 +29,4 @@ typedef struct TrafficControl { void traffic_control_free(TrafficControl *tc); int link_configure_traffic_control(Link *link); -void network_verify_traffic_control(Network *network); +void network_drop_invalid_traffic_control(Network *network); From 6dcc6375745416ee7ed1d30dd4d6e2523d452996 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 4 Oct 2020 19:54:56 +0900 Subject: [PATCH 134/138] test-network: drop duplicated address --- test/test-network/conf/25-address-static.network | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test-network/conf/25-address-static.network b/test/test-network/conf/25-address-static.network index f8119d13ee..506cdd2264 100644 --- a/test/test-network/conf/25-address-static.network +++ b/test/test-network/conf/25-address-static.network @@ -155,7 +155,6 @@ Address=10.3.3.98/16 Address=10.3.3.99/16 Address=10.3.3.100/16 Address=10.3.3.101/16 -Address=10.3.3.101/16 Address=10.3.3.102/16 Address=10.3.3.103/16 Address=10.3.3.104/16 From 5cf52d90a97fe930eefb3c5431218b0f9bd539cf Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 5 Oct 2020 21:47:44 +0200 Subject: [PATCH 135/138] test-network: add missing file in the list --- test/test-network/systemd-networkd-tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 3e57b335ce..67c0cce230 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -870,6 +870,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-sit-tunnel.netdev', '25-tap.netdev', '25-tun.netdev', + '25-tunnel-any-any.network', '25-tunnel-local-any.network', '25-tunnel-remote-any.network', '25-tunnel.network', From 47f8411249f31d47877186427a70d5e217c87622 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 5 Oct 2020 21:51:29 +0200 Subject: [PATCH 136/138] test-network: disable RA in test_sriov We usually disable IPv6AcceptRA= if the test does not require any dynamic address configuration, as it makes slightly slow down the test. C.f. 491b79aeac323909e8cef60ba6e91e27fd731679. --- test/test-network/conf/25-sriov.network | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test-network/conf/25-sriov.network b/test/test-network/conf/25-sriov.network index c962c3d845..099331db50 100644 --- a/test/test-network/conf/25-sriov.network +++ b/test/test-network/conf/25-sriov.network @@ -3,6 +3,7 @@ Name=eni99np1 [Network] Address=192.168.100.100/24 +IPv6AcceptRA=no [SR-IOV] VirtualFunction=0 From 713bfdaa6c0484674b398284f7ca225005f42574 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 5 Oct 2020 21:53:35 +0200 Subject: [PATCH 137/138] test-network: add a missing netdev in the list --- test/test-network/systemd-networkd-tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 67c0cce230..f2231d6701 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -745,6 +745,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): links = [ '6rdtun99', 'bareudp99', + 'bond98', 'bond99', 'bridge99', 'dropin-test', From 66493453b3f542286b58c6b2d356c9175019b424 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 5 Oct 2020 22:25:01 +0200 Subject: [PATCH 138/138] test-network: also remove IPv6 rules --- test/test-network/systemd-networkd-tests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index f2231d6701..8058122e46 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -382,6 +382,9 @@ def remove_routing_policy_rule_tables(tables): rc = 0 while rc == 0: rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + rc = 0 + while rc == 0: + rc = call('ip -6 rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) def remove_routes(routes): for route_type, addr in routes: