networkctl.c revision ddb7f7fc07a31937989afad53edb87b50e2cad72
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering This file is part of systemd.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Copyright 2014 Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is free software; you can redistribute it and/or modify it
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering under the terms of the GNU Lesser General Public License as published by
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (at your option) any later version.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is distributed in the hope that it will be useful, but
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Lesser General Public License for more details.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering You should have received a copy of the GNU Lesser General Public License
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
8752c5752f3b9023f9ce96a55d70c6e5fc31118fLennart Poetteringstatic bool arg_no_pager = false;
8752c5752f3b9023f9ce96a55d70c6e5fc31118fLennart Poetteringstatic bool arg_legend = true;
3f6fd1ba65f962702753c4ad284b588e59689a23Lennart Poetteringstatic bool arg_all = false;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic void pager_open_if_enabled(void) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int link_get_type_string(int iftype, struct udev_device *d, char **ret) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *t;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* WLANs have iftype ARPHRD_ETHER, but we want
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering * to show a more useful type string for
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringtypedef struct LinkInfo {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int link_info_compare(const void *a, const void *b) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const LinkInfo *x = a, *y = b;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int decode_and_sort_links(sd_rtnl_message *m, LinkInfo **ret) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering for (i = m; i; i = sd_rtnl_message_next(i)) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = sd_rtnl_message_read_string(i, IFLA_IFNAME, &name);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = sd_rtnl_message_link_get_type(i, &iftype);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return (int) c;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringstatic void operational_state_to_color(const char *state, const char **on, const char **off) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering } else if (streq_ptr(state, "degraded")) {
a6a4f528899b1dab47408733b4a423c66ea40f7aThomas Hindoe Paaboel Andersen *on = ansi_highlight_yellow();
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringstatic void setup_state_to_color(const char *state, const char **on, const char **off) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering } else if (streq_ptr(state, "configuring")) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poetteringstatic int list_links(char **args, unsigned n) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
1fc464f6fbecfc5d8ba9f7b98d19e21fb324bfb9Lennart Poettering log_error("Failed to connect to netlink: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to enumerate links: %s", strerror(-r));
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen printf("%3s %-16s %-18s %-11s %-10s\n", "IDX", "LINK", "TYPE", "OPERATIONAL", "SETUP");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering for (i = 0; i < c; i++) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering const char *on_color_operational, *off_color_operational,
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering d = udev_device_new_from_device_id(udev, devid);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering link_get_type_string(links[i].iftype, d, &t);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering on_color_operational, strna(operational_state), off_color_operational,
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering on_color_setup, strna(setup_state), off_color_setup);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringstatic int dump_addresses(sd_rtnl *rtnl, const char *prefix, int ifindex) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ struct local_address *local = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering n = local_addresses(rtnl, ifindex, &local);
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen for (i = 0; i < n; i++) {
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersenstatic void dump_list(const char *prefix, char **l) {
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersenstatic int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen _cleanup_udev_device_unref_ struct udev_device *d = NULL;
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL;
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering const char *on_color_operational, *off_color_operational,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (safe_atoi(name, &ifindex) >= 0 && ifindex > 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_rtnl_message_append_string(req, IFLA_IFNAME, name);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("Failed to query link: %s", strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_rtnl_message_link_get_ifindex(reply, &ifindex);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_rtnl_message_read_string(reply, IFLA_IFNAME, &name);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_rtnl_message_link_get_type(reply, &iftype);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen have_mac = sd_rtnl_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen for (p = (uint8_t*) &e; p < (uint8_t*) &e + sizeof(e); p++)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (*p != 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen sd_rtnl_message_read_u32(reply, IFLA_MTU, &mtu);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen sd_network_link_get_operational_state(ifindex, &operational_state);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen sd_network_link_get_setup_state(ifindex, &setup_state);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen sd_network_link_get_domains(ifindex, &domains);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_network_link_get_wildcard_domain(ifindex);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen d = udev_device_new_from_device_id(udev, devid);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen driver = udev_device_get_property_value(d, "ID_NET_DRIVER");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen path = udev_device_get_property_value(d, "ID_PATH");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen vendor = udev_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen vendor = udev_device_get_property_value(d, "ID_VENDOR");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen model = udev_device_get_property_value(d, "ID_MODEL_FROM_DATABASE");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen model = udev_device_get_property_value(d, "ID_MODEL");
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, name);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering " State: %s%s%s (%s%s%s)\n",
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen on_color_operational, strna(operational_state), off_color_operational,
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen on_color_setup, strna(setup_state), off_color_setup);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering printf(" HW Address: %s\n", ether_addr_to_string(&e, ea));
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering dump_addresses(rtnl, " Address: ", ifindex);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poetteringstatic int link_status(char **args, unsigned n) {
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("Failed to connect to netlink: %s", strerror(-r));
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering log_error("Failed to connect to udev: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *operational_state = NULL;
1d050e1e0a7082e23ee9b31fa0b819cb332b3444Lennart Poettering _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *on_color_operational, *off_color_operational;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_get_operational_state(&operational_state);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf(" State: %s%s%s\n", on_color_operational, strna(operational_state), off_color_operational);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering c = local_addresses(rtnl, 0, &addresses);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering for (i = 0; i < c; i++) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = in_addr_to_string(addresses[i].family, &addresses[i].address, &pretty);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
64d6c22905e94b02e760747c6c143dc9893083d9Thomas Hindoe Paaboel Andersen r = sd_rtnl_message_request_dump(req, true);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering log_error("Failed to enumerate links: %s", strerror(-r));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering c = decode_and_sort_links(reply, &links);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering for (i = 0; i < c; i++) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_status_one(rtnl, udev, links[i].name);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenstatic void help(void) {
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt "Query and control the networking subsystem.\n\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " -h --help Show this help\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " --version Show package version\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " --no-pager Do not pipe output into a pager\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " --no-legend Do not show the headers and footers\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " -a --all Show status for all links\n\n"
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen "Commands:\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " list List links\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " status LINK Show link status\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering { "version", no_argument, NULL, ARG_VERSION },
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering { "no-pager", no_argument, NULL, ARG_NO_PAGER },
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering while ((c = getopt_long(argc, argv, "ha", options, NULL)) >= 0) {
b1acce80cd60fe95f16df2f1ad23ff2ad82d08e5Lennart Poetteringstatic int networkctl_main(int argc, char *argv[]) {
373d9f173f910d547159917401c4b1f84af85736Tom Gundersen static const struct {
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta const enum {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering /* Special rule: no arguments means "list" */
db73295accbec0c6513817f0a64a92018592bb26Lennart Poettering log_error("Unknown operation %s", argv[optind]);
64d6c22905e94b02e760747c6c143dc9893083d9Thomas Hindoe Paaboel Andersen log_error("Too many arguments.");
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen assert_not_reached("Unknown comparison operator.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return verbs[i].dispatch(argv + optind, left);