diff options
Diffstat (limited to 'src/network/networkd-address-label.c')
-rw-r--r-- | src/network/networkd-address-label.c | 202 |
1 files changed, 173 insertions, 29 deletions
diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index e91ce3d2fa..3ac0cca72e 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -22,27 +22,49 @@ AddressLabel *address_label_free(AddressLabel *label) { hashmap_remove(label->network->address_labels_by_section, label->section); } + if (label->manager) { + assert(label->section); + hashmap_remove(label->manager->address_labels_by_section, label->section); + } + config_section_free(label->section); return mfree(label); } DEFINE_SECTION_CLEANUP_FUNCTIONS(AddressLabel, address_label_free); -static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) { +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + address_label_section_hash_ops, + ConfigSection, + config_section_hash_func, + config_section_compare_func, + AddressLabel, + address_label_free); + +static int address_label_new_static( + Manager *manager, + Network *network, + const char *filename, + unsigned section_line, + AddressLabel **ret) { + _cleanup_(config_section_freep) ConfigSection *n = NULL; _cleanup_(address_label_freep) AddressLabel *label = NULL; + Hashmap **address_labels_by_section; int r; - assert(network); + assert(!manager != !network); assert(ret); assert(filename); assert(section_line > 0); + address_labels_by_section = manager ? &manager->address_labels_by_section : &network->address_labels_by_section; + r = config_section_new(filename, section_line, &n); if (r < 0) return r; - label = hashmap_get(network->address_labels_by_section, n); + label = hashmap_get(*address_labels_by_section, n); if (label) { *ret = TAKE_PTR(label); return 0; @@ -53,12 +75,13 @@ static int address_label_new_static(Network *network, const char *filename, unsi return -ENOMEM; *label = (AddressLabel) { + .manager = manager, .network = network, .section = TAKE_PTR(n), .label = UINT32_MAX, }; - r = hashmap_ensure_put(&network->address_labels_by_section, &config_section_hash_ops, label->section, label); + r = hashmap_ensure_put(address_labels_by_section, &address_label_section_hash_ops, label->section, label); if (r < 0) return r; @@ -66,7 +89,7 @@ static int address_label_new_static(Network *network, const char *filename, unsi return 0; } -static int address_label_configure_handler( +static int link_address_label_configure_handler( sd_netlink *rtnl, sd_netlink_message *m, Request *req, @@ -86,7 +109,7 @@ static int address_label_configure_handler( } if (link->static_address_label_messages == 0) { - log_link_debug(link, "Addresses label set"); + log_link_debug(link, "Addresses label set."); link->static_address_labels_configured = true; link_check_ready(link); } @@ -94,7 +117,51 @@ static int address_label_configure_handler( return 1; } -static int address_label_configure(AddressLabel *label, Link *link, Request *req) { +static int manager_address_label_configure_handler( + sd_netlink *rtnl, + sd_netlink_message *m, + Request *req, + Link *link, + void *userdata) { + + Manager *manager = ASSERT_PTR(ASSERT_PTR(req)->manager); + int r; + + assert(m); + assert(!link); + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_message_warning_errno(m, r, "Could not set address label"); + return 1; + } + + if (manager->static_address_label_messages == 0) { + log_debug("Addresses label set."); + manager->static_address_labels_configured = true; + } + + return 1; +} + +static int address_label_fill_message(AddressLabel *label, sd_netlink_message *m) { + int r; + + assert(label); + assert(m); + + r = sd_rtnl_message_addrlabel_set_prefixlen(m, label->prefixlen); + if (r < 0) + return r; + + r = sd_netlink_message_append_u32(m, IFAL_LABEL, label->label); + if (r < 0) + return r; + + return sd_netlink_message_append_in6_addr(m, IFA_ADDRESS, &label->prefix); +} + +static int link_address_label_configure(AddressLabel *label, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -110,38 +177,69 @@ static int address_label_configure(AddressLabel *label, Link *link, Request *req if (r < 0) return r; - r = sd_rtnl_message_addrlabel_set_prefixlen(m, label->prefixlen); + r = address_label_fill_message(label, m); if (r < 0) return r; - r = sd_netlink_message_append_u32(m, IFAL_LABEL, label->label); + return request_call_netlink_async(link->manager->rtnl, m, req); +} + +static int manager_address_label_configure(AddressLabel *label, Manager *manager, Request *req) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(label); + assert(manager); + assert(manager->rtnl); + assert(req); + + r = sd_rtnl_message_new_addrlabel(manager->rtnl, &m, RTM_NEWADDRLABEL, 0, AF_INET6); if (r < 0) return r; - r = sd_netlink_message_append_in6_addr(m, IFA_ADDRESS, &label->prefix); + r = address_label_fill_message(label, m); if (r < 0) return r; - return request_call_netlink_async(link->manager->rtnl, m, req); + return request_call_netlink_async(manager->rtnl, m, req); } -static int address_label_process_request(Request *req, Link *link, void *userdata) { +static int link_address_label_process_request(Request *req, Link *link, void *userdata) { AddressLabel *label = ASSERT_PTR(userdata); int r; assert(req); assert(link); + assert(link->manager); + + if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false)) + return 0; - if (!link_is_ready_to_configure(link, false)) + if (!link->manager->static_address_labels_configured) return 0; - r = address_label_configure(label, link, req); + r = link_address_label_configure(label, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure address label: %m"); return 1; } +static int manager_address_label_process_request(Request *req, Link *link, void *userdata) { + AddressLabel *label = ASSERT_PTR(userdata); + int r; + + assert(req); + assert(req->manager); + assert(!link); + + r = manager_address_label_configure(label, req->manager, req); + if (r < 0) + return log_warning_errno(r, "Failed to configure address label: %m"); + + return 1; +} + int link_request_static_address_labels(Link *link) { AddressLabel *label; int r; @@ -154,9 +252,9 @@ int link_request_static_address_labels(Link *link) { HASHMAP_FOREACH(label, link->network->address_labels_by_section) { r = link_queue_request_full(link, REQUEST_TYPE_ADDRESS_LABEL, label, NULL, trivial_hash_func, trivial_compare_func, - address_label_process_request, + link_address_label_process_request, &link->static_address_label_messages, - address_label_configure_handler, NULL); + link_address_label_configure_handler, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request address label: %m"); } @@ -172,6 +270,32 @@ int link_request_static_address_labels(Link *link) { return 0; } +int manager_request_static_address_labels(Manager *manager) { + AddressLabel *label; + int r; + + assert(manager); + + manager->static_address_labels_configured = false; + + HASHMAP_FOREACH(label, manager->address_labels_by_section) { + r = manager_queue_request_full(manager, REQUEST_TYPE_ADDRESS_LABEL, + label, NULL, trivial_hash_func, trivial_compare_func, + manager_address_label_process_request, + &manager->static_address_label_messages, + manager_address_label_configure_handler, NULL); + if (r < 0) + return log_warning_errno(r, "Failed to request address label: %m"); + } + + if (manager->static_address_label_messages == 0) + manager->static_address_labels_configured = true; + else + log_debug("Setting address labels."); + + return 0; +} + static int address_label_section_verify(AddressLabel *label) { assert(label); assert(label->section); @@ -194,16 +318,24 @@ static int address_label_section_verify(AddressLabel *label) { return 0; } -void network_drop_invalid_address_labels(Network *network) { +static void drop_invalid_address_labels(Hashmap *address_labels_by_section) { AddressLabel *label; - assert(network); - - HASHMAP_FOREACH(label, network->address_labels_by_section) + HASHMAP_FOREACH(label, address_labels_by_section) if (address_label_section_verify(label) < 0) address_label_free(label); } +void network_drop_invalid_address_labels(Network *network) { + assert(network); + drop_invalid_address_labels(network->address_labels_by_section); +} + +void manager_drop_invalid_address_labels(Manager *manager) { + assert(manager); + drop_invalid_address_labels(manager->address_labels_by_section); +} + int config_parse_address_label_prefix( const char *unit, const char *filename, @@ -217,7 +349,8 @@ int config_parse_address_label_prefix( void *userdata) { _cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL; - Network *network = userdata; + Manager *manager = ltype ? userdata : NULL; + Network *network = ltype ? NULL : userdata; unsigned char prefixlen; union in_addr_union a; int r; @@ -226,12 +359,18 @@ int config_parse_address_label_prefix( assert(section); assert(lvalue); assert(rvalue); - assert(data); + assert(userdata); - r = address_label_new_static(network, filename, section_line, &n); + r = address_label_new_static(manager, network, filename, section_line, &n); if (r < 0) return log_oom(); + if (isempty(rvalue)) { + n->prefix_set = false; + TAKE_PTR(n); + return 0; + } + r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &prefixlen); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, @@ -249,7 +388,6 @@ int config_parse_address_label_prefix( n->prefix = a.in6; n->prefixlen = prefixlen; n->prefix_set = true; - TAKE_PTR(n); return 0; } @@ -267,7 +405,8 @@ int config_parse_address_label( void *userdata) { _cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL; - Network *network = userdata; + Manager *manager = ltype ? userdata : NULL; + Network *network = ltype ? NULL : userdata; uint32_t k; int r; @@ -275,25 +414,30 @@ int config_parse_address_label( assert(section); assert(lvalue); assert(rvalue); - assert(data); + assert(userdata); - r = address_label_new_static(network, filename, section_line, &n); + r = address_label_new_static(manager, network, filename, section_line, &n); if (r < 0) return log_oom(); + if (isempty(rvalue)) { + n->label = UINT32_MAX; + TAKE_PTR(n); + return 0; + } + r = safe_atou32(rvalue, &k); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue); return 0; } - if (k == UINT_MAX) { + if (k == UINT32_MAX) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Address label is invalid, ignoring: %s", rvalue); return 0; } n->label = k; TAKE_PTR(n); - return 0; } |