diff --git a/src/network/networkctl.c b/src/network/networkctl.c index df09f75c56..d645300899 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -125,6 +125,7 @@ typedef struct VxLanInfo { typedef struct LinkInfo { char name[IFNAMSIZ+1]; char netdev_kind[NETDEV_KIND_MAX]; + sd_device *sd_device; int ifindex; unsigned short iftype; struct ether_addr mac_address; @@ -167,12 +168,23 @@ typedef struct LinkInfo { bool has_stats:1; bool has_bitrates:1; bool has_ethtool_link_info:1; + + bool needs_freeing:1; } LinkInfo; static int link_info_compare(const LinkInfo *a, const LinkInfo *b) { return CMP(a->ifindex, b->ifindex); } +static const LinkInfo* link_info_array_free(LinkInfo *array) { + for (unsigned i = 0; array && array[i].needs_freeing; i++) { + sd_device_unref(array[i].sd_device); + } + + return mfree(array); +} +DEFINE_TRIVIAL_CLEANUP_FUNC(LinkInfo*, link_info_array_free); + static int decode_netdev(sd_netlink_message *m, LinkInfo *info) { const char *received_kind; int r; @@ -360,7 +372,7 @@ static void acquire_ether_link_info(int *fd, LinkInfo *link) { static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, LinkInfo **ret) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - _cleanup_free_ LinkInfo *links = NULL; + _cleanup_(link_info_array_freep) LinkInfo *links = NULL; _cleanup_close_ int fd = -1; size_t allocated = 0, c = 0, j; sd_netlink_message *i; @@ -382,7 +394,7 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin return log_error_errno(r, "Failed to enumerate links: %m"); for (i = reply; i; i = sd_netlink_message_next(i)) { - if (!GREEDY_REALLOC0(links, allocated, c+1)) + if (!GREEDY_REALLOC0(links, allocated, c + 2)) /* We keep one trailing one as marker */ return -ENOMEM; r = decode_link(i, links + c, patterns); @@ -391,6 +403,12 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin if (r == 0) continue; + links[c].needs_freeing = true; + + char devid[2 + DECIMAL_STR_MAX(int)]; + xsprintf(devid, "n%i", links[c].ifindex); + (void) sd_device_new_from_device_id(&links[c].sd_device, devid); + acquire_ether_link_info(&fd, &links[c]); c++; @@ -409,7 +427,7 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin static int list_links(int argc, char *argv[], void *userdata) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_free_ LinkInfo *links = NULL; + _cleanup_(link_info_array_freep) LinkInfo *links = NULL; _cleanup_(table_unrefp) Table *table = NULL; TableCell *cell; int c, i, r; @@ -441,10 +459,8 @@ static int list_links(int argc, char *argv[], void *userdata) { for (i = 0; i < c; i++) { _cleanup_free_ char *setup_state = NULL, *operational_state = NULL; - _cleanup_(sd_device_unrefp) sd_device *d = NULL; const char *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup; - char devid[2 + DECIMAL_STR_MAX(int)]; _cleanup_free_ char *t = NULL; (void) sd_network_link_get_operational_state(links[i].ifindex, &operational_state); @@ -455,10 +471,7 @@ static int list_links(int argc, char *argv[], void *userdata) { setup_state = strdup("unmanaged"); setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); - xsprintf(devid, "n%i", links[i].ifindex); - (void) sd_device_new_from_device_id(&d, devid); - - t = link_get_type_string(links[i].iftype, d); + t = link_get_type_string(links[i].iftype, links[i].sd_device); r = table_add_many(table, TABLE_INT, links[i].ifindex, @@ -1004,8 +1017,6 @@ static int link_status_one( _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL; _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL; - _cleanup_(sd_device_unrefp) sd_device *d = NULL; - char devid[2 + DECIMAL_STR_MAX(int)]; _cleanup_free_ char *t = NULL, *network = NULL; const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL; const char *on_color_operational, *off_color_operational, @@ -1031,23 +1042,19 @@ static int link_status_one( (void) sd_network_link_get_route_domains(info->ifindex, &route_domains); (void) sd_network_link_get_ntp(info->ifindex, &ntp); - xsprintf(devid, "n%i", info->ifindex); + if (info->sd_device) { + (void) sd_device_get_property_value(info->sd_device, "ID_NET_LINK_FILE", &link); + (void) sd_device_get_property_value(info->sd_device, "ID_NET_DRIVER", &driver); + (void) sd_device_get_property_value(info->sd_device, "ID_PATH", &path); - (void) sd_device_new_from_device_id(&d, devid); + if (sd_device_get_property_value(info->sd_device, "ID_VENDOR_FROM_DATABASE", &vendor) < 0) + (void) sd_device_get_property_value(info->sd_device, "ID_VENDOR", &vendor); - if (d) { - (void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link); - (void) sd_device_get_property_value(d, "ID_NET_DRIVER", &driver); - (void) sd_device_get_property_value(d, "ID_PATH", &path); - - if (sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor) < 0) - (void) sd_device_get_property_value(d, "ID_VENDOR", &vendor); - - if (sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model) < 0) - (void) sd_device_get_property_value(d, "ID_MODEL", &model); + if (sd_device_get_property_value(info->sd_device, "ID_MODEL_FROM_DATABASE", &model) < 0) + (void) sd_device_get_property_value(info->sd_device, "ID_MODEL", &model); } - t = link_get_type_string(info->iftype, d); + t = link_get_type_string(info->iftype, info->sd_device); (void) sd_network_link_get_network_file(info->ifindex, &network); @@ -1430,7 +1437,7 @@ static int link_status(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; - _cleanup_free_ LinkInfo *links = NULL; + _cleanup_(link_info_array_freep) LinkInfo *links = NULL; int r, c, i; (void) pager_open(arg_pager_flags); @@ -1518,7 +1525,7 @@ static void lldp_capabilities_legend(uint16_t x) { static int link_lldp_status(int argc, char *argv[], void *userdata) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_free_ LinkInfo *links = NULL; + _cleanup_(link_info_array_freep) LinkInfo *links = NULL; _cleanup_(table_unrefp) Table *table = NULL; int i, r, c, m = 0; uint16_t all = 0;