networkctl.c revision 5323ead145304785121b72dcbc1c244303de7575
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder/***
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder This file is part of systemd.
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder Copyright 2014 Lennart Poettering
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder systemd is free software; you can redistribute it and/or modify it
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder under the terms of the GNU Lesser General Public License as published by
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder the Free Software Foundation; either version 2.1 of the License, or
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder (at your option) any later version.
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder systemd is distributed in the hope that it will be useful, but
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder WITHOUT ANY WARRANTY; without even the implied warranty of
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder Lesser General Public License for more details.
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder You should have received a copy of the GNU Lesser General Public License
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder along with systemd; If not, see <http://www.gnu.org/licenses/>.
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder***/
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include <stdbool.h>
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include <getopt.h>
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "sd-network.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "sd-rtnl.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "libudev.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "build.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "util.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "pager.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "rtnl-util.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "udev-util.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "arphrd-list.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder#include "local-addresses.h"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic bool arg_no_pager = false;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic bool arg_legend = true;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic bool arg_all = false;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic void pager_open_if_enabled(void) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (arg_no_pager)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder pager_open(false);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder}
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic int link_get_type_string(int iftype, struct udev_device *d, char **ret) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder const char *t;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder char *p;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (iftype == ARPHRD_ETHER && d) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder const char *devtype, *id = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder /* WLANs have iftype ARPHRD_ETHER, but we want
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder * to show a more useful type string for
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder * them */
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder devtype = udev_device_get_devtype(d);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (streq_ptr(devtype, "wlan"))
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder id = "wlan";
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder else if (streq_ptr(devtype, "wwan"))
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder id = "wwan";
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (id) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder p = strdup(id);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (!p)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return -ENOMEM;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder *ret = p;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return 1;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder t = arphrd_to_name(iftype);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (!t) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder *ret = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return 0;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder p = strdup(t);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (!p)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return -ENOMEM;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder ascii_strlower(p);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder *ret = p;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return 0;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder}
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroedertypedef struct LinkInfo {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder const char *name;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder int ifindex;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder unsigned iftype;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder} LinkInfo;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic int link_info_compare(const void *a, const void *b) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder const LinkInfo *x = a, *y = b;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return x->ifindex - y->ifindex;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder}
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic int decode_and_sort_links(sd_rtnl_message *m, LinkInfo **ret) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_free_ LinkInfo *links = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder size_t size = 0, c = 0;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sd_rtnl_message *i;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder int r;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder for (i = m; i; i = sd_rtnl_message_next(i)) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder const char *name;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder unsigned iftype;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder uint16_t type;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder int ifindex;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_get_type(i, &type);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return r;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (type != RTM_NEWLINK)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder continue;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return r;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_read_string(i, IFLA_IFNAME, &name);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return r;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_link_get_type(i, &iftype);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return r;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (!GREEDY_REALLOC(links, size, c+1))
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return -ENOMEM;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder links[c].name = name;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder links[c].ifindex = ifindex;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder links[c].iftype = iftype;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder c++;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder qsort(links, c, sizeof(LinkInfo), link_info_compare);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder *ret = links;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder links = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return (int) c;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder}
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic int list_links(char **args, unsigned n) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_udev_unref_ struct udev *udev = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_free_ LinkInfo *links = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder int r, c, i;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder pager_open_if_enabled();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_open(&rtnl, 0);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder log_error("Failed to connect to netlink: %s", strerror(-r));
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return r;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder udev = udev_new();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (!udev) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder log_error("Failed to connect to udev: %m");
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return -errno;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return rtnl_log_create_error(r);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_request_dump(req, true);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return rtnl_log_create_error(r);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_call(rtnl, req, 0, &reply);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder log_error("Failed to enumerate links: %s", strerror(-r));
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return r;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (arg_legend)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf("%3s %-16s %-10s %-11s %-10s\n", "IDX", "LINK", "TYPE", "ADMIN", "OPERATIONAL");
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder c = decode_and_sort_links(reply, &links);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (c < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return rtnl_log_parse_error(c);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder for (i = 0; i < c; i++) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_free_ char *state = NULL, *operational_state = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_udev_device_unref_ struct udev_device *d = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder const char *on_color_oper = "", *off_color_oper = "",
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder *on_color = "", *off_color = "";
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder char devid[2 + DECIMAL_STR_MAX(int)];
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_free_ char *t = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sd_network_get_link_state(links[i].ifindex, &state);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sd_network_get_link_operational_state(links[i].ifindex, &operational_state);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sprintf(devid, "n%i", links[i].ifindex);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder d = udev_device_new_from_device_id(udev, devid);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder link_get_type_string(links[i].iftype, d, &t);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (streq_ptr(operational_state, "routable")) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder on_color_oper = ansi_highlight_green();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder off_color_oper = ansi_highlight_off();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder } else if (streq_ptr(operational_state, "degraded")) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder on_color_oper = ansi_highlight_yellow();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder off_color_oper = ansi_highlight_off();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (streq_ptr(state, "configured")) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder on_color = ansi_highlight_green();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder off_color = ansi_highlight_off();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder } else if (streq_ptr(state, "configuring")) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder on_color = ansi_highlight_yellow();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder off_color = ansi_highlight_off();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder } else if (streq_ptr(state, "failed") ||
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder streq_ptr(state, "linger")) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder on_color = ansi_highlight_red();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder off_color = ansi_highlight_off();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf("%3i %-16s %-10s %s%-11s%s %s%-10s%s\n", links[i].ifindex,
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder links[i].name, strna(t), on_color, strna(state), off_color,
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder on_color_oper, strna(operational_state), off_color_oper);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (arg_legend)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf("\n%i links listed.\n", c);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return 0;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder}
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic int dump_addresses(sd_rtnl *rtnl, const char *prefix, int ifindex) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_free_ struct local_address *local = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder int r, n, i;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder n = local_addresses(rtnl, ifindex, &local);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (n < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return n;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder for (i = 0; i < n; i++) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_free_ char *pretty = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return r;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf("%*s%s\n",
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder (int) strlen(prefix),
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder i == 0 ? prefix : "",
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder pretty);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return 0;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder}
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic void dump_list(const char *prefix, char **l) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder char **i;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder STRV_FOREACH(i, l) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf("%*s%s\n",
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder (int) strlen(prefix),
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder i == l ? prefix : "",
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder *i);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder}
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroederstatic int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_strv_free_ char **dns = NULL, **ntp = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_free_ char *state = NULL, *operational_state = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_udev_device_unref_ struct udev_device *d = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder char devid[2 + DECIMAL_STR_MAX(int)];
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder _cleanup_free_ char *t = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder const char *on_color = "", *off_color = "";
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder struct ether_addr e;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder unsigned iftype;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder int r, ifindex;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder bool have_mac;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder uint32_t mtu;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder assert(rtnl);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder assert(udev);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder assert(name);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (safe_atoi(name, &ifindex) >= 0 && ifindex > 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder else {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return rtnl_log_create_error(r);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_append_string(req, IFLA_IFNAME, name);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return rtnl_log_create_error(r);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_call(rtnl, req, 0, &reply);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder log_error("Failed to query link: %s", strerror(-r));
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return r;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_link_get_ifindex(reply, &ifindex);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return rtnl_log_parse_error(r);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_read_string(reply, IFLA_IFNAME, &name);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return rtnl_log_parse_error(r);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder r = sd_rtnl_message_link_get_type(reply, &iftype);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (r < 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return rtnl_log_parse_error(r);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder have_mac = sd_rtnl_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (have_mac) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder const uint8_t *p;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder bool all_zeroes = true;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder for (p = (uint8_t*) &e; p < (uint8_t*) &e + sizeof(e); p++)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (*p != 0) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder all_zeroes = false;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder break;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (all_zeroes)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder have_mac = false;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sd_rtnl_message_read_u32(reply, IFLA_MTU, &mtu);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sd_network_get_link_state(ifindex, &state);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sd_network_get_link_operational_state(ifindex, &operational_state);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sd_network_get_link_dns(ifindex, &dns);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sd_network_get_link_ntp(ifindex, &ntp);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder sprintf(devid, "n%i", ifindex);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder d = udev_device_new_from_device_id(udev, devid);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder link_get_type_string(iftype, d, &t);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (d) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder driver = udev_device_get_property_value(d, "ID_NET_DRIVER");
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder path = udev_device_get_property_value(d, "ID_PATH");
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder vendor = udev_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE");
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (!vendor)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder vendor = udev_device_get_property_value(d, "ID_VENDOR");
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder model = udev_device_get_property_value(d, "ID_MODEL_FROM_DATABASE");
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (!model)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder model = udev_device_get_property_value(d, "ID_MODEL");
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (streq_ptr(operational_state, "routable")) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder on_color = ansi_highlight_green();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder off_color = ansi_highlight_off();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder } else if (streq_ptr(operational_state, "degraded")) {
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder on_color = ansi_highlight_yellow();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder off_color = ansi_highlight_off();
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder }
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf("%s%s%s %i: %s\n", on_color, draw_special_char(DRAW_BLACK_CIRCLE), off_color, ifindex, name);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf(" Type: %s\n"
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder " State: %s%s%s (%s)\n",
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder strna(t),
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder on_color, strna(operational_state), off_color,
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder strna(state));
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (path)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf(" Path: %s\n", path);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (driver)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf(" Driver: %s\n", driver);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (vendor)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf(" Vendor: %s\n", vendor);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (model)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf(" Model: %s\n", model);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (have_mac)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf(" HW Address: %s\n", ether_ntoa(&e));
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (mtu > 0)
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder printf(" MTU: %u\n", mtu);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder dump_addresses(rtnl, " Address: ", ifindex);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (!strv_isempty(dns))
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder dump_list(" DNS: ", dns);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder if (!strv_isempty(ntp))
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder dump_list(" NTP: ", ntp);
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder return 0;
81f49ee02aaa3bc870401f8883bf52742eb3ea7aJonathan von Schroeder}
static int link_status(char **args, unsigned n) {
_cleanup_udev_unref_ struct udev *udev = NULL;
_cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
char **name;
int r;
r = sd_rtnl_open(&rtnl, 0);
if (r < 0) {
log_error("Failed to connect to netlink: %s", strerror(-r));
return r;
}
udev = udev_new();
if (!udev) {
log_error("Failed to connect to udev: %m");
return -errno;
}
if (n <= 1 && !arg_all) {
_cleanup_free_ char *operational_state = NULL;
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL;
_cleanup_free_ struct local_address *addresses = NULL;
const char *on_color_oper = "", *off_color_oper = "";
int i, c;
sd_network_get_operational_state(&operational_state);
if (streq_ptr(operational_state, "routable")) {
on_color_oper = ansi_highlight_green();
off_color_oper = ansi_highlight_off();
} else if (streq_ptr(operational_state, "degraded")) {
on_color_oper = ansi_highlight_yellow();
off_color_oper = ansi_highlight_off();
}
printf(" State: %s%s%s\n", on_color_oper, strna(operational_state), off_color_oper);
c = local_addresses(rtnl, 0, &addresses);
for (i = 0; i < c; i++) {
_cleanup_free_ char *pretty = NULL;
r = in_addr_to_string(addresses[i].family, &addresses[i].address, &pretty);
if (r < 0)
return log_oom();
printf("%13s %s\n",
i > 0 ? "" : "Address:", pretty);
}
sd_network_get_dns(&dns);
if (!strv_isempty(dns))
dump_list(" DNS: ", dns);
sd_network_get_dns(&ntp);
if (!strv_isempty(ntp))
dump_list(" NTP: ", ntp);
return 0;
}
pager_open_if_enabled();
if (arg_all) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
_cleanup_free_ LinkInfo *links = NULL;
int c, i;
r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
if (r < 0)
return rtnl_log_create_error(r);
r = sd_rtnl_message_request_dump(req, true);
if (r < 0)
return rtnl_log_create_error(r);
r = sd_rtnl_call(rtnl, req, 0, &reply);
if (r < 0) {
log_error("Failed to enumerate links: %s", strerror(-r));
return r;
}
c = decode_and_sort_links(reply, &links);
if (c < 0)
return rtnl_log_parse_error(c);
for (i = 0; i < c; i++) {
if (i > 0)
fputc('\n', stdout);
link_status_one(rtnl, udev, links[i].name);
}
}
STRV_FOREACH(name, args + 1) {
if (name != args+1)
fputc('\n', stdout);
link_status_one(rtnl, udev, *name);
}
return 0;
}
static void help(void) {
printf("%s [OPTIONS...]\n\n"
"Query and control the networking subsystem.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" --no-legend Do not show the headers and footers\n"
" -a --all Show status for all links\n\n"
"Commands:\n"
" list List links\n"
" status LINK Show link status\n"
, program_invocation_short_name);
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_NO_LEGEND,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "all", no_argument, NULL, 'a' },
{}
};
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "ha", options, NULL)) >= 0) {
switch (c) {
case 'h':
help();
return 0;
case ARG_VERSION:
puts(PACKAGE_STRING);
puts(SYSTEMD_FEATURES);
return 0;
case ARG_NO_PAGER:
arg_no_pager = true;
break;
case ARG_NO_LEGEND:
arg_legend = false;
break;
case 'a':
arg_all = true;
break;
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
}
return 1;
}
static int networkctl_main(int argc, char *argv[]) {
static const struct {
const char* verb;
const enum {
MORE,
LESS,
EQUAL
} argc_cmp;
const int argc;
int (* const dispatch)(char **args, unsigned n);
} verbs[] = {
{ "list", LESS, 1, list_links },
{ "status", MORE, 1, link_status },
};
int left;
unsigned i;
assert(argc >= 0);
assert(argv);
left = argc - optind;
if (left <= 0)
/* Special rule: no arguments means "list" */
i = 0;
else {
if (streq(argv[optind], "help")) {
help();
return 0;
}
for (i = 0; i < ELEMENTSOF(verbs); i++)
if (streq(argv[optind], verbs[i].verb))
break;
if (i >= ELEMENTSOF(verbs)) {
log_error("Unknown operation %s", argv[optind]);
return -EINVAL;
}
}
switch (verbs[i].argc_cmp) {
case EQUAL:
if (left != verbs[i].argc) {
log_error("Invalid number of arguments.");
return -EINVAL;
}
break;
case MORE:
if (left < verbs[i].argc) {
log_error("Too few arguments.");
return -EINVAL;
}
break;
case LESS:
if (left > verbs[i].argc) {
log_error("Too many arguments.");
return -EINVAL;
}
break;
default:
assert_not_reached("Unknown comparison operator.");
}
return verbs[i].dispatch(argv + optind, left);
}
int main(int argc, char* argv[]) {
int r;
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = networkctl_main(argc, argv);
finish:
pager_close();
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}