diff --git a/src/network/networkctl-misc.c b/src/network/networkctl-misc.c index e4021ee30d..701efee078 100644 --- a/src/network/networkctl-misc.c +++ b/src/network/networkctl-misc.c @@ -14,205 +14,149 @@ #include "networkctl.h" #include "networkctl-misc.h" #include "networkctl-util.h" +#include "ordered-set.h" #include "parse-util.h" #include "polkit-agent.h" -#include "set.h" #include "string-util.h" +#include "strv.h" #include "varlink-util.h" -static int link_up_down_send_message(sd_netlink *rtnl, char *command, int index) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; +static int parse_interfaces(sd_netlink **rtnl, char *argv[], OrderedSet **ret) { + _cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL; + _cleanup_ordered_set_free_ OrderedSet *indexes = NULL; int r; - assert(rtnl); - assert(index >= 0); + assert(ret); - r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, index); - if (r < 0) - return rtnl_log_create_error(r); + if (!rtnl) + rtnl = &our_rtnl; - if (streq(command, "up")) - r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); - else - r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP); - if (r < 0) - return log_error_errno(r, "Could not set link flags: %m"); + STRV_FOREACH(s, strv_skip(argv, 1)) { + int index = rtnl_resolve_interface_or_warn(rtnl, *s); + if (index < 0) + return index; + assert(index > 0); - r = sd_netlink_call(rtnl, req, 0, NULL); - if (r < 0) - return r; + r = ordered_set_ensure_put(&indexes, /* ops= */ NULL, INT_TO_PTR(index)); + if (r < 0) + return log_oom(); + } + *ret = TAKE_PTR(indexes); return 0; } int link_up_down(int argc, char *argv[], void *userdata) { - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_set_free_ Set *indexes = NULL; - int index, r; - void *p; + int r, ret = 0; - r = sd_netlink_open(&rtnl); - if (r < 0) - return log_error_errno(r, "Failed to connect to netlink: %m"); + bool up = streq_ptr(argv[0], "up"); - indexes = set_new(NULL); - if (!indexes) - return log_oom(); - - for (int i = 1; i < argc; i++) { - index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]); - if (index < 0) - return index; - - r = set_put(indexes, INT_TO_PTR(index)); - if (r < 0) - return log_oom(); - } - - SET_FOREACH(p, indexes) { - index = PTR_TO_INT(p); - r = link_up_down_send_message(rtnl, argv[0], index); - if (r < 0) - return log_error_errno(r, "Failed to bring %s interface %s: %m", - argv[0], FORMAT_IFNAME_FULL(index, FORMAT_IFNAME_IFINDEX)); - } - - return r; -} - -static int link_delete_send_message(sd_netlink *rtnl, int index) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(rtnl); - assert(index >= 0); - - r = sd_rtnl_message_new_link(rtnl, &req, RTM_DELLINK, index); - if (r < 0) - return rtnl_log_create_error(r); - - r = sd_netlink_call(rtnl, req, 0, NULL); + _cleanup_ordered_set_free_ OrderedSet *indexes = NULL; + r = parse_interfaces(/* rtnl= */ NULL, argv, &indexes); if (r < 0) return r; - return 0; + _cleanup_(sd_varlink_flush_close_unrefp) sd_varlink *vl = NULL; + r = varlink_connect_networkd(&vl); + if (r < 0) + return r; + + (void) polkit_agent_open_if_enabled(BUS_TRANSPORT_LOCAL, arg_ask_password); + + void *p; + ORDERED_SET_FOREACH(p, indexes) + RET_GATHER(ret, varlink_callbo_and_log( + vl, + up ? "io.systemd.Network.LinkUp" : "io.systemd.Network.LinkDown", + /* reply= */ NULL, + SD_JSON_BUILD_PAIR_INTEGER("InterfaceIndex", PTR_TO_INT(p)), + SD_JSON_BUILD_PAIR_BOOLEAN("allowInteractiveAuthentication", arg_ask_password))); + + return ret; } int link_delete(int argc, char *argv[], void *userdata) { + int r, ret = 0; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_set_free_ Set *indexes = NULL; - int index, r; + _cleanup_ordered_set_free_ OrderedSet *indexes = NULL; + r = parse_interfaces(&rtnl, argv, &indexes); + if (r < 0) + return r; + void *p; + ORDERED_SET_FOREACH(p, indexes) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int index = PTR_TO_INT(p); - r = sd_netlink_open(&rtnl); - if (r < 0) - return log_error_errno(r, "Failed to connect to netlink: %m"); - - indexes = set_new(NULL); - if (!indexes) - return log_oom(); - - for (int i = 1; i < argc; i++) { - index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]); - if (index < 0) - return index; - - r = set_put(indexes, INT_TO_PTR(index)); + r = sd_rtnl_message_new_link(rtnl, &req, RTM_DELLINK, index); if (r < 0) - return log_oom(); + return rtnl_log_create_error(r); + + r = sd_netlink_call(rtnl, req, /* timeout= */ 0, /* ret= */ NULL); + if (r < 0) { + RET_GATHER(ret, r); + log_error_errno(r, "Failed to delete interface %s: %m", + FORMAT_IFNAME_FULL(index, FORMAT_IFNAME_IFINDEX)); + } } - SET_FOREACH(p, indexes) { - index = PTR_TO_INT(p); - r = link_delete_send_message(rtnl, index); - if (r < 0) - return log_error_errno(r, "Failed to delete interface %s: %m", - FORMAT_IFNAME_FULL(index, FORMAT_IFNAME_IFINDEX)); - } - - return r; + return ret; } -static int link_renew_one(sd_bus *bus, int index, const char *name) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - int r; +int link_bus_simple_method(int argc, char *argv[], void *userdata) { + int r, ret = 0; - assert(bus); - assert(index >= 0); - assert(name); + typedef struct LinkBusAction { + const char *verb; + const char *bus_method; + const char *error_message; + } LinkBusAction; - r = bus_call_method(bus, bus_network_mgr, "RenewLink", &error, NULL, "i", index); + static const LinkBusAction link_bus_action_table[] = { + { "renew", "RenewLink", "Failed to renew dynamic configuration of interface" }, + { "forcerenew", "ForceRenewLink", "Failed to forcibly renew dynamic configuration of interface" }, + { "reconfigure", "ReconfigureLink", "Failed to reconfigure network interface" }, + }; + + /* Common implementation for 'simple' method calls that just take an ifindex, and nothing else. */ + + const LinkBusAction *a = NULL; + FOREACH_ELEMENT(i, link_bus_action_table) + if (streq(argv[0], i->verb)) { + a = i; + break; + } + assert(a); + + _cleanup_ordered_set_free_ OrderedSet *indexes = NULL; + r = parse_interfaces(/* rtnl= */ NULL, argv, &indexes); if (r < 0) - return log_error_errno(r, "Failed to renew dynamic configuration of interface %s: %s", - name, bus_error_message(&error, r)); + return r; - return 0; -} - -int link_renew(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - int r; - r = acquire_bus(&bus); if (r < 0) return r; (void) polkit_agent_open_if_enabled(BUS_TRANSPORT_LOCAL, arg_ask_password); - r = 0; + void *p; + ORDERED_SET_FOREACH(p, indexes) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int index = PTR_TO_INT(p); - for (int i = 1; i < argc; i++) { - int index; - - index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]); - if (index < 0) - return index; - - RET_GATHER(r, link_renew_one(bus, index, argv[i])); + r = bus_call_method(bus, bus_network_mgr, a->bus_method, &error, /* ret_reply= */ NULL, "i", index); + if (r < 0) { + RET_GATHER(ret, r); + log_error_errno(r, "%s %s: %s", + a->error_message, + FORMAT_IFNAME_FULL(index, FORMAT_IFNAME_IFINDEX), + bus_error_message(&error, r)); + } } - return r; -} - -static int link_force_renew_one(sd_bus *bus, int index, const char *name) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - int r; - - assert(bus); - assert(index >= 0); - assert(name); - - r = bus_call_method(bus, bus_network_mgr, "ForceRenewLink", &error, NULL, "i", index); - if (r < 0) - return log_error_errno(r, "Failed to force renew dynamic configuration of interface %s: %s", - name, bus_error_message(&error, r)); - - return 0; -} - -int link_force_renew(int argc, char *argv[], void *userdata) { - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - int k = 0, r; - - r = acquire_bus(&bus); - if (r < 0) - return r; - - (void) polkit_agent_open_if_enabled(BUS_TRANSPORT_LOCAL, arg_ask_password); - - for (int i = 1; i < argc; i++) { - int index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]); - if (index < 0) - return index; - - r = link_force_renew_one(bus, index, argv[i]); - if (r < 0 && k >= 0) - k = r; - } - - return k; + return ret; } int verb_reload(int argc, char *argv[], void *userdata) { @@ -233,46 +177,6 @@ int verb_reload(int argc, char *argv[], void *userdata) { return 0; } -int verb_reconfigure(int argc, char *argv[], void *userdata) { - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_set_free_ Set *indexes = NULL; - int index, r; - void *p; - - r = acquire_bus(&bus); - if (r < 0) - return r; - - (void) polkit_agent_open_if_enabled(BUS_TRANSPORT_LOCAL, arg_ask_password); - - indexes = set_new(NULL); - if (!indexes) - return log_oom(); - - for (int i = 1; i < argc; i++) { - index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]); - if (index < 0) - return index; - - r = set_put(indexes, INT_TO_PTR(index)); - if (r < 0) - return log_oom(); - } - - SET_FOREACH(p, indexes) { - index = PTR_TO_INT(p); - r = bus_call_method(bus, bus_network_mgr, "ReconfigureLink", &error, NULL, "i", index); - if (r < 0) - return log_error_errno(r, "Failed to reconfigure network interface %s: %s", - FORMAT_IFNAME_FULL(index, FORMAT_IFNAME_IFINDEX), - bus_error_message(&error, r)); - } - - return 0; -} - int verb_persistent_storage(int argc, char *argv[], void *userdata) { _cleanup_(sd_varlink_flush_close_unrefp) sd_varlink *vl = NULL; bool ready; diff --git a/src/network/networkctl-misc.h b/src/network/networkctl-misc.h index a7cae1c43a..4860c99ce3 100644 --- a/src/network/networkctl-misc.h +++ b/src/network/networkctl-misc.h @@ -3,8 +3,6 @@ int link_up_down(int argc, char *argv[], void *userdata); int link_delete(int argc, char *argv[], void *userdata); -int link_renew(int argc, char *argv[], void *userdata); -int link_force_renew(int argc, char *argv[], void *userdata); +int link_bus_simple_method(int argc, char *argv[], void *userdata); int verb_reload(int argc, char *argv[], void *userdata); -int verb_reconfigure(int argc, char *argv[], void *userdata); int verb_persistent_storage(int argc, char *argv[], void *userdata); diff --git a/src/network/networkctl.c b/src/network/networkctl.c index f9aa40ba1b..68acdcf60a 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -230,9 +230,9 @@ static int networkctl_main(int argc, char *argv[]) { { "delete", 2, VERB_ANY, 0, link_delete }, { "up", 2, VERB_ANY, 0, link_up_down }, { "down", 2, VERB_ANY, 0, link_up_down }, - { "renew", 2, VERB_ANY, VERB_ONLINE_ONLY, link_renew }, - { "forcerenew", 2, VERB_ANY, VERB_ONLINE_ONLY, link_force_renew }, - { "reconfigure", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_reconfigure }, + { "renew", 2, VERB_ANY, VERB_ONLINE_ONLY, link_bus_simple_method }, + { "forcerenew", 2, VERB_ANY, VERB_ONLINE_ONLY, link_bus_simple_method }, + { "reconfigure", 2, VERB_ANY, VERB_ONLINE_ONLY, link_bus_simple_method }, { "reload", 1, 1, VERB_ONLINE_ONLY, verb_reload }, { "edit", 2, VERB_ANY, 0, verb_edit }, { "cat", 1, VERB_ANY, 0, verb_cat },