diff --git a/src/network/generator/network-generator.c b/src/network/generator/network-generator.c index 1c3d9a7e05..ab3d2d8860 100644 --- a/src/network/generator/network-generator.c +++ b/src/network/generator/network-generator.c @@ -209,6 +209,11 @@ static Network* network_free(Network *network) { DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free); +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + network_hash_ops, + char, string_hash_func, string_compare_func, + Network, network_free); + static int network_new(Context *context, const char *name, Network **ret) { _cleanup_(network_freep) Network *network = NULL; _cleanup_free_ char *ifname = NULL; @@ -234,7 +239,7 @@ static int network_new(Context *context, const char *name, Network **ret) { .dhcp_use_dns = -1, }; - r = hashmap_ensure_put(&context->networks_by_name, &string_hash_ops, network->ifname, network); + r = hashmap_ensure_put(&context->networks_by_name, &network_hash_ops, network->ifname, network); if (r < 0) return r; @@ -277,6 +282,11 @@ static NetDev* netdev_free(NetDev *netdev) { DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_free); +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + netdev_hash_ops, + char, string_hash_func, string_compare_func, + NetDev, netdev_free); + static int netdev_new(Context *context, const char *_kind, const char *_ifname, NetDev **ret) { _cleanup_(netdev_freep) NetDev *netdev = NULL; _cleanup_free_ char *kind = NULL, *ifname = NULL; @@ -306,7 +316,7 @@ static int netdev_new(Context *context, const char *_kind, const char *_ifname, .ifname = TAKE_PTR(ifname), }; - r = hashmap_ensure_put(&context->netdevs_by_name, &string_hash_ops, netdev->ifname, netdev); + r = hashmap_ensure_put(&context->netdevs_by_name, &netdev_hash_ops, netdev->ifname, netdev); if (r < 0) return r; @@ -355,6 +365,11 @@ static Link* link_free(Link *link) { DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + link_hash_ops, + char, string_hash_func, string_compare_func, + Link, link_free); + static int link_new( Context *context, const char *name, @@ -398,7 +413,7 @@ static int link_new( .mac = *mac, }; - r = hashmap_ensure_put(&context->links_by_filename, &string_hash_ops, link->filename, link); + r = hashmap_ensure_put(&context->links_by_filename, &link_hash_ops, link->filename, link); if (r < 0) return r; @@ -1272,9 +1287,9 @@ void context_clear(Context *context) { if (!context) return; - hashmap_free_with_destructor(context->networks_by_name, network_free); - hashmap_free_with_destructor(context->netdevs_by_name, netdev_free); - hashmap_free_with_destructor(context->links_by_filename, link_free); + hashmap_free(context->networks_by_name); + hashmap_free(context->netdevs_by_name); + hashmap_free(context->links_by_filename); } static int address_dump(Address *address, FILE *f) { diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c index 032c2e75dc..a3dc42a9ea 100644 --- a/src/network/test-networkd-conf.c +++ b/src/network/test-networkd-conf.c @@ -58,7 +58,7 @@ static void test_config_parse_ether_addr_one(const char *rvalue, const struct et } static void test_config_parse_ether_addrs_one(const char *rvalue, const struct ether_addr* list, size_t n) { - _cleanup_set_free_free_ Set *s = NULL; + _cleanup_set_free_ Set *s = NULL; ASSERT_OK(config_parse_ether_addrs("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &s, NULL)); ASSERT_EQ(set_size(s), n); diff --git a/src/network/wait-online/link.c b/src/network/wait-online/link.c index a4a64462ff..7515579edb 100644 --- a/src/network/wait-online/link.c +++ b/src/network/wait-online/link.c @@ -11,7 +11,35 @@ #include "string-util.h" #include "strv.h" -int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { +static Link* link_free(Link *l) { + + if (!l) + return NULL; + + if (l->manager) { + hashmap_remove(l->manager->links_by_index, INT_TO_PTR(l->ifindex)); + hashmap_remove(l->manager->links_by_name, l->ifname); + + STRV_FOREACH(n, l->altnames) + hashmap_remove(l->manager->links_by_name, *n); + } + + dns_configuration_free(l->dns_configuration); + + free(l->state); + free(l->ifname); + strv_free(l->altnames); + return mfree(l); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + link_hash_ops_by_index, + void, trivial_hash_func, trivial_compare_func, + Link, link_free); + +static int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { _cleanup_(link_freep) Link *l = NULL; _cleanup_free_ char *n = NULL; int r; @@ -36,7 +64,7 @@ int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { .dns_configuration = hashmap_remove(m->dns_configuration_by_link_index, INT_TO_PTR(ifindex)), }; - r = hashmap_ensure_put(&m->links_by_index, NULL, INT_TO_PTR(ifindex), l); + r = hashmap_ensure_put(&m->links_by_index, &link_hash_ops_by_index, INT_TO_PTR(ifindex), l); if (r < 0) return r; @@ -51,27 +79,6 @@ int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { return 0; } -Link *link_free(Link *l) { - - if (!l) - return NULL; - - if (l->manager) { - hashmap_remove(l->manager->links_by_index, INT_TO_PTR(l->ifindex)); - hashmap_remove(l->manager->links_by_name, l->ifname); - - STRV_FOREACH(n, l->altnames) - hashmap_remove(l->manager->links_by_name, *n); - } - - dns_configuration_free(l->dns_configuration); - - free(l->state); - free(l->ifname); - strv_free(l->altnames); - return mfree(l); -} - static int link_update_name(Link *l, sd_netlink_message *m) { char ifname_from_index[IF_NAMESIZE]; const char *ifname; @@ -149,7 +156,7 @@ static int link_update_altnames(Link *l, sd_netlink_message *m) { return 0; } -int link_update_rtnl(Link *l, sd_netlink_message *m) { +static int link_update_rtnl(Link *l, sd_netlink_message *m) { int r; assert(l); @@ -171,6 +178,75 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) { return 0; } +int rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { + Manager *m = ASSERT_PTR(userdata); + uint16_t type; + Link *l; + const char *ifname; + int ifindex, r; + + assert(rtnl); + assert(mm); + + r = sd_netlink_message_get_type(mm, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_link_get_ifindex(mm, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: Could not get ifindex from link, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received link message with invalid ifindex %d, ignoring", ifindex); + return 0; + } + + r = sd_netlink_message_read_string(mm, IFLA_IFNAME, &ifname); + if (r < 0) { + log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m"); + return 0; + } + + l = hashmap_get(m->links_by_index, INT_TO_PTR(ifindex)); + + switch (type) { + + case RTM_NEWLINK: + if (!l) { + log_debug("Found link %s(%i)", ifname, ifindex); + + r = link_new(m, &l, ifindex, ifname); + if (r < 0) { + log_warning_errno(r, "Failed to create link object for %s(%i), ignoring: %m", ifname, ifindex); + return 0; + } + } + + r = link_update_rtnl(l, mm); + if (r < 0) + log_link_warning_errno(l, r, "Failed to process RTNL link message, ignoring: %m"); + + r = link_update_monitor(l); + if (r < 0) + log_link_full_errno(l, IN_SET(r, -ENODATA, -ENOENT) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to update link state, ignoring: %m"); + + break; + + case RTM_DELLINK: + if (l) { + log_link_debug(l, "Removing link"); + link_free(l); + } + + break; + } + + return 0; +} + int link_update_monitor(Link *l) { _cleanup_free_ char *required_operstate = NULL, *required_family = NULL, *ipv4_address_state = NULL, *ipv6_address_state = NULL, *state = NULL; diff --git a/src/network/wait-online/link.h b/src/network/wait-online/link.h index ec352c4113..33d0a85e8d 100644 --- a/src/network/wait-online/link.h +++ b/src/network/wait-online/link.h @@ -28,9 +28,5 @@ struct Link { DNSConfiguration *dns_configuration; }; -int link_new(Manager *m, Link **ret, int ifindex, const char *ifname); -Link *link_free(Link *l); -int link_update_rtnl(Link *l, sd_netlink_message *m); +int rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata); int link_update_monitor(Link *l); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); diff --git a/src/network/wait-online/manager.c b/src/network/wait-online/manager.c index 4bad0f97e2..597598abc6 100644 --- a/src/network/wait-online/manager.c +++ b/src/network/wait-online/manager.c @@ -234,80 +234,11 @@ bool manager_configured(Manager *m) { return !m->any && has_online; } -static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { - Manager *m = ASSERT_PTR(userdata); - uint16_t type; - Link *l; - const char *ifname; - int ifindex, r; - - assert(rtnl); - assert(mm); - - r = sd_netlink_message_get_type(mm, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_link_get_ifindex(mm, &ifindex); - if (r < 0) { - log_warning_errno(r, "rtnl: Could not get ifindex from link, ignoring: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received link message with invalid ifindex %d, ignoring", ifindex); - return 0; - } - - r = sd_netlink_message_read_string(mm, IFLA_IFNAME, &ifname); - if (r < 0) { - log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m"); - return 0; - } - - l = hashmap_get(m->links_by_index, INT_TO_PTR(ifindex)); - - switch (type) { - - case RTM_NEWLINK: - if (!l) { - log_debug("Found link %s(%i)", ifname, ifindex); - - r = link_new(m, &l, ifindex, ifname); - if (r < 0) { - log_warning_errno(r, "Failed to create link object for %s(%i), ignoring: %m", ifname, ifindex); - return 0; - } - } - - r = link_update_rtnl(l, mm); - if (r < 0) - log_link_warning_errno(l, r, "Failed to process RTNL link message, ignoring: %m"); - - r = link_update_monitor(l); - if (r < 0) - log_link_full_errno(l, IN_SET(r, -ENODATA, -ENOENT) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to update link state, ignoring: %m"); - - break; - - case RTM_DELLINK: - if (l) { - log_link_debug(l, "Removing link"); - link_free(l); - } - - break; - } - - return 0; -} - static int on_rtnl_event(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { Manager *m = userdata; int r; - r = manager_process_link(rtnl, mm, m); + r = rtnl_process_link(rtnl, mm, m); if (r < 0) return r; @@ -354,7 +285,7 @@ static int manager_rtnl_listen(Manager *m) { return r; for (sd_netlink_message *i = reply; i; i = sd_netlink_message_next(i)) { - r = manager_process_link(m->rtnl, i, m); + r = rtnl_process_link(m->rtnl, i, m); if (r < 0) return r; } @@ -572,7 +503,8 @@ Manager* manager_free(Manager *m) { if (!m) return NULL; - hashmap_free_with_destructor(m->links_by_index, link_free); + /* free links_by_index at first, as it has ownership of links. */ + hashmap_free(m->links_by_index); hashmap_free(m->links_by_name); sd_event_source_unref(m->network_monitor_event_source);