X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-address.c;h=9cfc0955d31a7d615c7d74fab38d2552b8681b69;hp=75a9bae20197a411e735371b43aa6778d15bc641;hb=26fefda707e6511733f48da03b281a004dba6abf;hpb=8cd11a0f0f4ca05199e1166f6a07472b296f7455 diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 75a9bae20..9cfc0955d 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -28,9 +28,20 @@ #include "conf-parser.h" #include "net-util.h" -int address_new(Network *network, Address **ret) { +int address_new(Network *network, unsigned section, Address **ret) { _cleanup_address_free_ Address *address = NULL; + if (section) { + uint64_t key = section; + address = hashmap_get(network->addresses_by_section, &key); + if (address) { + *ret = address; + address = NULL; + + return 0; + } + } + address = new0(Address, 1); if (!address) return -ENOMEM; @@ -39,6 +50,11 @@ int address_new(Network *network, Address **ret) { LIST_PREPEND(addresses, network->addresses, address); + if (section) { + address->section = section; + hashmap_put(network->addresses_by_section, &address->section, address); + } + *ret = address; address = NULL; @@ -51,14 +67,20 @@ void address_free(Address *address) { LIST_REMOVE(addresses, address->network->addresses, address); - free(address->label); + if (address->section) + hashmap_remove(address->network->addresses_by_section, + &address->section); + free(address); } -int address_configure(Manager *manager, Address *address, Link *link) { +int address_configure(Address *address, Link *link, + sd_rtnl_message_handler_t callback) { _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL; int r; + assert(link->manager); + r = sd_rtnl_message_addr_new(RTM_NEWADDR, link->ifindex, address->family, address->prefixlen, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE, &req); @@ -97,13 +119,13 @@ int address_configure(Manager *manager, Address *address, Link *link) { } } - r = sd_rtnl_call(manager->rtnl, req, 0, NULL); + r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL); if (r < 0) { - log_error("Could not configure address: %s", strerror(-r)); - return r != -EEXIST ? r : 0; + log_error("Could not send rtnetlink message: %s", strerror(-r)); + return r; } - log_info("Configured interface address"); + link->rtnl_messages ++; return 0; } @@ -112,22 +134,25 @@ int config_parse_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_address_free_ Address *n = NULL; _cleanup_free_ char *address = NULL; const char *e; int r; assert(filename); + assert(section); assert(lvalue); assert(rvalue); assert(data); - r = address_new(userdata, &n); + r = address_new(network, section_line, &n); if (r < 0) return r; @@ -168,3 +193,53 @@ int config_parse_address(const char *unit, return 0; } + +int config_parse_label(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_ Address *n = NULL; + char *label; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_new(network, section_line, &n); + if (r < 0) + return r; + + label = strdup(rvalue); + if (!label) + return log_oom(); + + if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Interface label is not ASCII clean or is too" + " long, ignoring assignment: %s", rvalue); + free(label); + return 0; + } + + free(n->label); + if (*label) + n->label = label; + else { + free(label); + n->label = NULL; + } + + n = NULL; + + return 0; +}