networkctl.c revision f7d68aa8c9430dfddee5f913f93b405a5d75723a
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/***
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering This file is part of systemd.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Copyright 2014 Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart 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
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
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/>.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering***/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <stdbool.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <getopt.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "sd-network.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "sd-rtnl.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "libudev.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "build.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "pager.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "rtnl-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "udev-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "arphrd-list.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "local-addresses.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic bool arg_no_pager = false;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic bool arg_legend = true;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringstatic bool arg_all = false;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void pager_open_if_enabled(void) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (arg_no_pager)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering pager_open(false);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int link_get_type_string(int iftype, struct udev_device *d, char **ret) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *t;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering char *p;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (iftype == ARPHRD_ETHER && d) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *devtype, *id = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* WLANs have iftype ARPHRD_ETHER, but we want
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering * to show a more useful type string for
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering * them */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering devtype = udev_device_get_devtype(d);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (streq_ptr(devtype, "wlan"))
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering id = "wlan";
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering else if (streq_ptr(devtype, "wwan"))
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering id = "wwan";
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (id) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering p = strdup(id);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!p)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -ENOMEM;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *ret = p;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 1;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = arphrd_to_name(iftype);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!t) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *ret = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering p = strdup(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!p)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -ENOMEM;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ascii_strlower(p);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *ret = p;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringtypedef struct LinkInfo {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering const char *name;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering int ifindex;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering unsigned iftype;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering} LinkInfo;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringstatic int link_info_compare(const void *a, const void *b) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering const LinkInfo *x = a, *y = b;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return x->ifindex - y->ifindex;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering}
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringstatic int decode_and_sort_links(sd_rtnl_message *m, LinkInfo **ret) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering _cleanup_free_ LinkInfo *links = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering size_t size = 0, c = 0;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering sd_rtnl_message *i;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering int r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering for (i = m; i; i = sd_rtnl_message_next(i)) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering const char *name;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering unsigned iftype;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering uint16_t type;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering int ifindex;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = sd_rtnl_message_get_type(i, &type);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (type != RTM_NEWLINK)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering continue;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = sd_rtnl_message_read_string(i, IFLA_IFNAME, &name);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = sd_rtnl_message_link_get_type(i, &iftype);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (!GREEDY_REALLOC(links, size, c+1))
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return -ENOMEM;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering links[c].name = name;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering links[c].ifindex = ifindex;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering links[c].iftype = iftype;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering c++;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering qsort(links, c, sizeof(LinkInfo), link_info_compare);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering *ret = links;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering links = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return (int) c;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering}
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int list_links(char **args, unsigned n) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering _cleanup_free_ LinkInfo *links = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering int r, c, i;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering pager_open_if_enabled();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_open(&rtnl, 0);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to connect to netlink: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering udev = udev_new();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!udev) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to connect to udev: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -errno;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return rtnl_log_create_error(r);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_request_dump(req, true);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return rtnl_log_create_error(r);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_call(rtnl, req, 0, &reply);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to enumerate links: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (arg_legend)
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering printf("%3s %-16s %-10s %-10s %-10s\n", "IDX", "LINK", "TYPE", "ADMIN", "OPERATIONAL");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering c = decode_and_sort_links(reply, &links);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (c < 0)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return rtnl_log_parse_error(c);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering for (i = 0; i < c; i++) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *state = NULL, *operational_state = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering const char *on_color = "", *off_color = "";
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering char devid[2 + DECIMAL_STR_MAX(int)];
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *t = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering sd_network_get_link_state(links[i].ifindex, &state);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering sd_network_get_link_operational_state(links[i].ifindex, &operational_state);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering sprintf(devid, "n%i", links[i].ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering d = udev_device_new_from_device_id(udev, devid);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering link_get_type_string(links[i].iftype, d, &t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering if (streq_ptr(operational_state, "routable")) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering on_color = ansi_highlight_green();
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering off_color = ansi_highlight_off();
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering } else if (streq_ptr(operational_state, "degraded")) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering on_color = ansi_highlight_yellow();
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering off_color = ansi_highlight_off();
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering }
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering printf("%3i %-16s %-10s %-10s %s%-10s%s\n", links[i].ifindex, links[i].name, strna(t), strna(state), on_color, strna(operational_state), off_color);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (arg_legend)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering printf("\n%i links listed.\n", c);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int dump_addresses(sd_rtnl *rtnl, const char *prefix, int ifindex) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ struct local_address *local = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r, n, i;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering n = local_addresses(rtnl, ifindex, &local);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (n < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return n;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering for (i = 0; i < n; i++) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *pretty = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf("%*s%s\n",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (int) strlen(prefix),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering i == 0 ? prefix : "",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering pretty);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void dump_list(const char *prefix, char **l) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering char **i;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering STRV_FOREACH(i, l) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf("%*s%s\n",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (int) strlen(prefix),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering i == l ? prefix : "",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *i);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringstatic int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_strv_free_ char **dns = NULL, **ntp = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_free_ char *state = NULL, *operational_state = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering char devid[2 + DECIMAL_STR_MAX(int)];
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_free_ char *t = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL;
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering const char *on_color = "", *off_color = "";
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering struct ether_addr e;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering unsigned iftype;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering int r, ifindex;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering bool have_mac;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering uint32_t mtu;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(rtnl);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(udev);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(name);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (safe_atoi(name, &ifindex) >= 0 && ifindex > 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering else {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return rtnl_log_create_error(r);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_rtnl_message_append_string(req, IFLA_IFNAME, name);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return rtnl_log_create_error(r);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_rtnl_call(rtnl, req, 0, &reply);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_error("Failed to query link: %s", strerror(-r));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_rtnl_message_link_get_ifindex(reply, &ifindex);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return rtnl_log_parse_error(r);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_rtnl_message_read_string(reply, IFLA_IFNAME, &name);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return rtnl_log_parse_error(r);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_rtnl_message_link_get_type(reply, &iftype);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return rtnl_log_parse_error(r);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering have_mac = sd_rtnl_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (have_mac) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering const uint8_t *p;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering bool all_zeroes = true;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering for (p = (uint8_t*) &e; p < (uint8_t*) &e + sizeof(e); p++)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (*p != 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering all_zeroes = false;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering break;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (all_zeroes)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering have_mac = false;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sd_rtnl_message_read_u32(reply, IFLA_MTU, &mtu);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sd_network_get_link_state(ifindex, &state);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sd_network_get_link_operational_state(ifindex, &operational_state);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sd_network_get_link_dns(ifindex, &dns);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sd_network_get_link_ntp(ifindex, &ntp);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sprintf(devid, "n%i", ifindex);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering d = udev_device_new_from_device_id(udev, devid);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_get_type_string(iftype, d, &t);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (d) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering driver = udev_device_get_property_value(d, "ID_NET_DRIVER");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering path = udev_device_get_property_value(d, "ID_PATH");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering vendor = udev_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (!vendor)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering vendor = udev_device_get_property_value(d, "ID_VENDOR");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering model = udev_device_get_property_value(d, "ID_MODEL_FROM_DATABASE");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (!model)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering model = udev_device_get_property_value(d, "ID_MODEL");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering if (streq_ptr(operational_state, "routable")) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering on_color = ansi_highlight_green();
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering off_color = ansi_highlight_off();
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering } else if (streq_ptr(operational_state, "degraded")) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering on_color = ansi_highlight_yellow();
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering off_color = ansi_highlight_off();
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering }
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering printf("%s%s%s %i: %s\n", on_color, draw_special_char(DRAW_BLACK_CIRCLE), off_color, ifindex, name);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" Type: %s\n"
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering " State: %s%s%s (%s)\n",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering strna(t),
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering on_color, strna(operational_state), off_color,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering strna(state));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (path)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" Path: %s\n", path);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (driver)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" Driver: %s\n", driver);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (vendor)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" Vendor: %s\n", vendor);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (model)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" Model: %s\n", model);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (have_mac)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" HW Address: %s\n", ether_ntoa(&e));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (mtu > 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" MTU: %u\n", mtu);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering dump_addresses(rtnl, " Address: ", ifindex);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (!strv_isempty(dns))
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering dump_list(" DNS: ", dns);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (!strv_isempty(ntp))
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering dump_list(" NTP: ", ntp);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return 0;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering}
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int link_status(char **args, unsigned n) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering char **name;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering r = sd_rtnl_open(&rtnl, 0);
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering if (r < 0) {
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering log_error("Failed to connect to netlink: %s", strerror(-r));
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering return r;
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering }
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering udev = udev_new();
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering if (!udev) {
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering log_error("Failed to connect to udev: %m");
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering return -errno;
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering }
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (n <= 1 && !arg_all) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *operational_state = NULL;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering _cleanup_strv_free_ char **dns = NULL, **ntp = NULL;
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering int i, c;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering sd_network_get_operational_state(&operational_state);
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering if (operational_state)
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering printf(" State: %s\n", operational_state);
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering c = local_addresses(rtnl, 0, &addresses);
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering for (i = 0; i < c; i++) {
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering _cleanup_free_ char *pretty = NULL;
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering r = in_addr_to_string(addresses[i].family, &addresses[i].address, &pretty);
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering if (r < 0)
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering return log_oom();
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering printf("%13s %s\n",
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering i > 0 ? "" : "Address:", pretty);
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering }
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering sd_network_get_dns(&dns);
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering if (!strv_isempty(dns))
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering dump_list(" DNS: ", dns);
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering sd_network_get_dns(&ntp);
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering if (!strv_isempty(ntp))
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering dump_list(" NTP: ", ntp);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering pager_open_if_enabled();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (arg_all) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering _cleanup_free_ LinkInfo *links = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering int c, i;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return rtnl_log_create_error(r);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return rtnl_log_create_error(r);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_call(rtnl, req, 0, &reply);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_error("Failed to enumerate links: %s", strerror(-r));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering c = decode_and_sort_links(reply, &links);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (c < 0)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return rtnl_log_parse_error(c);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering for (i = 0; i < c; i++) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (i > 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering fputc('\n', stdout);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering link_status_one(rtnl, udev, links[i].name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering STRV_FOREACH(name, args + 1) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (name != args+1)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering fputc('\n', stdout);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_status_one(rtnl, udev, *name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void help(void) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf("%s [OPTIONS...]\n\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "Query and control the networking subsystem.\n\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart 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"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "Commands:\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering " list List links\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering " status LINK Show link status\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering , program_invocation_short_name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering enum {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ARG_VERSION = 0x100,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ARG_NO_PAGER,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering ARG_NO_LEGEND,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering };
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering static const struct option options[] = {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering { "help", no_argument, NULL, 'h' },
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering { "version", no_argument, NULL, ARG_VERSION },
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering { "no-pager", no_argument, NULL, ARG_NO_PAGER },
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering { "all", no_argument, NULL, 'a' },
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering {}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering };
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int c;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(argc >= 0);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(argv);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering while ((c = getopt_long(argc, argv, "ha", options, NULL)) >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering switch (c) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case 'h':
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering help();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case ARG_VERSION:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering puts(PACKAGE_STRING);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering puts(SYSTEMD_FEATURES);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case ARG_NO_PAGER:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering arg_no_pager = true;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case ARG_NO_LEGEND:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering arg_legend = false;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering case 'a':
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering arg_all = true;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering break;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case '?':
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -EINVAL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering default:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert_not_reached("Unhandled option");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 1;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int networkctl_main(int argc, char *argv[]) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering static const struct {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char* verb;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const enum {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering MORE,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering LESS,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering EQUAL
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering } argc_cmp;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const int argc;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int (* const dispatch)(char **args, unsigned n);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering } verbs[] = {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering { "list", LESS, 1, list_links },
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering { "status", MORE, 1, link_status },
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering };
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int left;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering unsigned i;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(argc >= 0);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(argv);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering left = argc - optind;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (left <= 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Special rule: no arguments means "list" */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering i = 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering else {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (streq(argv[optind], "help")) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering help();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering for (i = 0; i < ELEMENTSOF(verbs); i++)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (streq(argv[optind], verbs[i].verb))
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (i >= ELEMENTSOF(verbs)) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Unknown operation %s", argv[optind]);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -EINVAL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering switch (verbs[i].argc_cmp) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case EQUAL:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (left != verbs[i].argc) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Invalid number of arguments.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -EINVAL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case MORE:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (left < verbs[i].argc) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Too few arguments.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -EINVAL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering case LESS:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (left > verbs[i].argc) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Too many arguments.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -EINVAL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering break;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering default:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert_not_reached("Unknown comparison operator.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return verbs[i].dispatch(argv + optind, left);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringint main(int argc, char* argv[]) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_parse_environment();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_open();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = parse_argv(argc, argv);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r <= 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering goto finish;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = networkctl_main(argc, argv);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringfinish:
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering pager_close();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}