networkctl.c revision b5efdb8af40ea759a1ea584c1bc44ecc81dd00ce
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 <getopt.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <net/if.h>
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering#include <stdbool.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "sd-device.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "sd-hwdb.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "sd-netlink.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "sd-network.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "alloc-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "arphrd-list.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "device-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "ether-addr-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "hwdb-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "lldp.h"
db73295accbec0c6513817f0a64a92018592bb26Lennart Poettering#include "local-addresses.h"
d8500c53789eafefe28d4ace088bf4b912280bf9Tom Gundersen#include "locale-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "locale-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "netlink-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "pager.h"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering#include "parse-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "socket-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "string-table.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "string-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "strv.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "terminal-util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "verbs.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic bool arg_no_pager = false;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic bool arg_legend = true;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart 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, sd_device *d, char **ret) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *t;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering char *p;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(ret);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (iftype == ARPHRD_ETHER && d) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *devtype = NULL, *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 (void)sd_device_get_devtype(d, &devtype);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
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) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering *ret = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return 0;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering p = strdup(t);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (!p)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return -ENOMEM;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering ascii_strlower(p);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering *ret = p;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return 0;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering}
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart 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_netlink_message *m, LinkInfo **ret) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering _cleanup_free_ LinkInfo *links = NULL;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering size_t size = 0, c = 0;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering sd_netlink_message *i;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering int r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering for (i = m; i; i = sd_netlink_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_netlink_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_netlink_message_read_string(i, IFLA_IFNAME, &name);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return r;
a6a4f528899b1dab47408733b4a423c66ea40f7aThomas Hindoe Paaboel Andersen
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
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering links[c].name = name;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering links[c].ifindex = ifindex;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering links[c].iftype = iftype;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering c++;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering }
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering *ret = links;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering links = NULL;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering return (int) c;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering}
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poetteringstatic void operational_state_to_color(const char *state, const char **on, const char **off) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering assert(on);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering assert(off);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering if (streq_ptr(state, "routable")) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering *on = ansi_highlight_green();
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering *off = ansi_normal();
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering } else if (streq_ptr(state, "degraded")) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering *on = ansi_highlight_yellow();
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering *off = ansi_normal();
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering } else
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering *on = *off = "";
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering}
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poetteringstatic void setup_state_to_color(const char *state, const char **on, const char **off) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering assert(on);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering assert(off);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (streq_ptr(state, "configured")) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *on = ansi_highlight_green();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *off = ansi_normal();
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering } else if (streq_ptr(state, "configuring")) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering *on = ansi_highlight_yellow();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *off = ansi_normal();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *on = ansi_highlight_red();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *off = ansi_normal();
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt } else
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt *on = *off = "";
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidtstatic int list_links(int argc, char *argv[], void *userdata) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ LinkInfo *links = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r, c, i;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering pager_open_if_enabled();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_netlink_open(&rtnl);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return log_error_errno(r, "Failed to connect to netlink: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return rtnl_log_create_error(r);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
3e3db0ee860025ad663b13b0ace4e6d627611332Lennart Poettering r = sd_netlink_message_request_dump(req, true);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return rtnl_log_create_error(r);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = sd_netlink_call(rtnl, req, 0, &reply);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return log_error_errno(r, "Failed to enumerate links: %m");
ab1525bc2d92780b4dc64bc5b9cdb52594e2df7dLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (arg_legend)
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering printf("%3s %-16s %-18s %-11s %-10s\n", "IDX", "LINK", "TYPE", "OPERATIONAL", "SETUP");
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering c = decode_and_sort_links(reply, &links);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (c < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return rtnl_log_parse_error(c);
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering for (i = 0; i < c; i++) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering _cleanup_device_unref_ sd_device *d = NULL;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering const char *on_color_operational, *off_color_operational,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *on_color_setup, *off_color_setup;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering char devid[2 + DECIMAL_STR_MAX(int)];
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *t = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
3e3db0ee860025ad663b13b0ace4e6d627611332Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sprintf(devid, "n%i", links[i].ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (void)sd_device_new_from_device_id(&d, devid);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering link_get_type_string(links[i].iftype, d, &t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering links[i].ifindex, links[i].name, strna(t),
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering on_color_operational, strna(operational_state), off_color_operational,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen on_color_setup, strna(setup_state), off_color_setup);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (arg_legend)
d8500c53789eafefe28d4ace088bf4b912280bf9Tom Gundersen printf("\n%i links listed.\n", c);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering return 0;
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering}
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen/* IEEE Organizationally Unique Identifier vendor string */
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersenstatic int ieee_oui(sd_hwdb *hwdb, struct ether_addr *mac, char **ret) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen const char *description;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen char modalias[strlen("OUI:XXYYXXYYXXYY") + 1], *desc;
d8500c53789eafefe28d4ace088bf4b912280bf9Tom Gundersen int r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(ret);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (!hwdb)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return -EINVAL;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (!mac)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return -EINVAL;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen /* skip commonly misused 00:00:00 (Xerox) prefix */
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (memcmp(mac, "\0\0\0", 3) == 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return -EINVAL;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen snprintf(modalias, sizeof(modalias), "OUI:" ETHER_ADDR_FORMAT_STR, ETHER_ADDR_FORMAT_VAL(*mac));
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering r = sd_hwdb_get(hwdb, modalias, "ID_OUI_FROM_DATABASE", &description);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (r < 0)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering return r;
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering desc = strdup(description);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (!desc)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering return -ENOMEM;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen *ret = desc;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return 0;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen}
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersenstatic int get_gateway_description(
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen sd_netlink *rtnl,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen sd_hwdb *hwdb,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen int ifindex,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen int family,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen union in_addr_union *gateway,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen char **gateway_description) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen sd_netlink_message *m;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen int r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(rtnl);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(ifindex >= 0);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(family == AF_INET || family == AF_INET6);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(gateway);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen assert(gateway_description);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_GETNEIGH, ifindex, family);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_netlink_message_request_dump(req, true);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_netlink_call(rtnl, req, 0, &reply);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return r;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen for (m = reply; m; m = sd_netlink_message_next(m)) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen union in_addr_union gw = {};
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen struct ether_addr mac = {};
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen uint16_t type;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen int ifi, fam;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_netlink_message_get_errno(m);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error_errno(r, "got error: %m");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_netlink_message_get_type(m, &type);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error_errno(r, "could not get type: %m");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (type != RTM_NEWNEIGH) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("type is not RTM_NEWNEIGH");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
144232a8e0ea77eed8c5a456832758681b5b3511Torstein Husebø r = sd_rtnl_message_neigh_get_family(m, &fam);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error_errno(r, "could not get family: %m");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (fam != family) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("family is not correct");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_rtnl_message_neigh_get_ifindex(m, &ifi);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error_errno(r, "could not get ifindex: %m");
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (ifindex > 0 && ifi != ifindex)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen switch (fam) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen case AF_INET:
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_netlink_message_read_in_addr(m, NDA_DST, &gw.in);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen break;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen case AF_INET6:
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_netlink_message_read_in6_addr(m, NDA_DST, &gw.in6);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen break;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen default:
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (!in_addr_equal(fam, &gw, gateway))
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen continue;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = sd_netlink_message_read_ether_addr(m, NDA_LLADDR, &mac);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (r < 0)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering continue;
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering r = ieee_oui(hwdb, &mac, gateway_description);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (r < 0)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering continue;
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen return 0;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen }
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen return -ENODATA;
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen}
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersenstatic int dump_gateways(
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen sd_netlink *rtnl,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen sd_hwdb *hwdb,
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen const char *prefix,
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen int ifindex) {
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen _cleanup_free_ struct local_address *local = NULL;
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen int r, n, i;
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local);
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen if (n < 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen return n;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering for (i = 0; i < n; i++) {
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering _cleanup_free_ char *gateway = NULL, *description = NULL;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering r = in_addr_to_string(local[i].family, &local[i].address, &gateway);
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen if (r < 0)
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering return r;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering if (r < 0)
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering log_debug_errno(r, "Could not get description of gateway: %m");
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering printf("%*s%s",
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering (int) strlen(prefix),
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering i == 0 ? prefix : "",
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering gateway);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering if (description)
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering printf(" (%s)", description);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering /* Show interface name for the entry if we show
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen * entries for all interfaces */
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (ifindex <= 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen char name[IF_NAMESIZE+1];
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (if_indextoname(local[i].ifindex, name)) {
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering fputs(" on ", stdout);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering fputs(name, stdout);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering } else
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering printf(" on %%%i", local[i].ifindex);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering fputc('\n', stdout);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
1d050e1e0a7082e23ee9b31fa0b819cb332b3444Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int dump_addresses(
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_netlink *rtnl,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *prefix,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int ifindex) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ struct local_address *local = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r, n, i;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (n < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return n;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering for (i = 0; i < n; i++) {
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering _cleanup_free_ char *pretty = NULL;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering if (r < 0)
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering return r;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering printf("%*s%s",
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering (int) strlen(prefix),
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering i == 0 ? prefix : "",
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering pretty);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (ifindex <= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering char name[IF_NAMESIZE+1];
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (if_indextoname(local[i].ifindex, name)) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering fputs(" on ", stdout);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering fputs(name, stdout);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering } else
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf(" on %%%i", local[i].ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering fputc('\n', stdout);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poetteringstatic void dump_list(const char *prefix, char **l) {
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering char **i;
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering STRV_FOREACH(i, l) {
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering printf("%*s%s\n",
2301cb9fdb774d0a1b3d8f5e95c5d358721ccacbLennart Poettering (int) strlen(prefix),
6c03d27d9f7e831194dbd8bd6bcdeef9273edb6eThomas Hindoe Paaboel Andersen i == l ? prefix : "",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering *i);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering}
373d9f173f910d547159917401c4b1f84af85736Tom Gundersen
af5effc4220dab6c4c87a130bae7be441f6967caTom Gundersenstatic int link_status_one(
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering sd_netlink *rtnl,
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering sd_hwdb *hwdb,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering const char *name) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_device_unref_ sd_device *d = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering char devid[2 + DECIMAL_STR_MAX(int)];
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_free_ char *t = NULL, *network = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering const char *on_color_operational, *off_color_operational,
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering *on_color_setup, *off_color_setup;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_strv_free_ char **carrier_bound_to = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_strv_free_ char **carrier_bound_by = NULL;
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(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 {
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return rtnl_log_create_error(r);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = sd_netlink_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_netlink_call(rtnl, req, 0, &reply);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return log_error_errno(r, "Failed to query link: %m");
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_netlink_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_netlink_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++)
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen if (*p != 0) {
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering all_zeroes = false;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering break;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering }
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (all_zeroes)
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen have_mac = false;
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen }
2301cb9fdb774d0a1b3d8f5e95c5d358721ccacbLennart Poettering
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen sd_network_link_get_operational_state(ifindex, &operational_state);
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering sd_network_link_get_setup_state(ifindex, &setup_state);
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering sd_network_link_get_dns(ifindex, &dns);
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering sd_network_link_get_domains(ifindex, &domains);
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen r = sd_network_link_get_wildcard_domain(ifindex);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (r > 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering char *wildcard;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering wildcard = strdup("*");
af5effc4220dab6c4c87a130bae7be441f6967caTom Gundersen if (!wildcard)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return log_oom();
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (strv_consume(&domains, wildcard) < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return log_oom();
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sprintf(devid, "n%i", ifindex);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering (void)sd_device_new_from_device_id(&d, devid);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (d) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering (void)sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
b1acce80cd60fe95f16df2f1ad23ff2ad82d08e5Lennart Poettering (void)sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
b1acce80cd60fe95f16df2f1ad23ff2ad82d08e5Lennart Poettering (void)sd_device_get_property_value(d, "ID_PATH", &path);
373d9f173f910d547159917401c4b1f84af85736Tom Gundersen
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering r = sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering if (r < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering (void)sd_device_get_property_value(d, "ID_VENDOR", &vendor);
af5effc4220dab6c4c87a130bae7be441f6967caTom Gundersen
af5effc4220dab6c4c87a130bae7be441f6967caTom Gundersen r = sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model);
373d9f173f910d547159917401c4b1f84af85736Tom Gundersen if (r < 0)
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering (void)sd_device_get_property_value(d, "ID_MODEL", &model);
af5effc4220dab6c4c87a130bae7be441f6967caTom Gundersen }
373d9f173f910d547159917401c4b1f84af85736Tom Gundersen
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_get_type_string(iftype, d, &t);
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering sd_network_link_get_network_file(ifindex, &network);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sd_network_link_get_carrier_bound_to(ifindex, &carrier_bound_to);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering sd_network_link_get_carrier_bound_by(ifindex, &carrier_bound_by);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, name);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" Link File: %s\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " Network File: %s\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " Type: %s\n"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering " State: %s%s%s (%s%s%s)\n",
db73295accbec0c6513817f0a64a92018592bb26Lennart Poettering strna(link),
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering strna(network),
db73295accbec0c6513817f0a64a92018592bb26Lennart Poettering strna(t),
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering on_color_operational, strna(operational_state), off_color_operational,
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering on_color_setup, strna(setup_state), off_color_setup);
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering if (path)
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering printf(" Path: %s\n", path);
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering if (driver)
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering printf(" Driver: %s\n", driver);
db73295accbec0c6513817f0a64a92018592bb26Lennart 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) {
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering _cleanup_free_ char *description = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering char ea[ETHER_ADDR_TO_STRING_MAX];
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering ieee_oui(hwdb, &e, &description);
2301cb9fdb774d0a1b3d8f5e95c5d358721ccacbLennart Poettering
c627729fc49d59ffcecc09555a34d9dd139927ceLennart Poettering if (description)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" HW Address: %s (%s)\n", ether_addr_to_string(&e, ea), description);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering else
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering printf(" HW Address: %s\n", ether_addr_to_string(&e, ea));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (mtu > 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf(" MTU: %u\n", mtu);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering dump_addresses(rtnl, " Address: ", ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering dump_gateways(rtnl, hwdb, " Gateway: ", ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!strv_isempty(dns))
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering dump_list(" DNS: ", dns);
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering if (!strv_isempty(domains))
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt dump_list(" Domain: ", domains);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering (void) sd_network_link_get_ntp(ifindex, &ntp);
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering if (!strv_isempty(ntp))
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt dump_list(" NTP: ", ntp);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering if (!strv_isempty(carrier_bound_to))
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering dump_list("Carrier Bound To: ", carrier_bound_to);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (!strv_isempty(carrier_bound_by))
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering dump_list("Carrier Bound By: ", carrier_bound_by);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (void) sd_network_link_get_timezone(ifindex, &tz);
c627729fc49d59ffcecc09555a34d9dd139927ceLennart Poettering if (tz)
f7d68aa8c9430dfddee5f913f93b405a5d75723aLennart Poettering printf(" Time Zone: %s", tz);
e92da1e5d0a3b38804e173af136ec7a076c7757eLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering}
e92da1e5d0a3b38804e173af136ec7a076c7757eLennart Poettering
5323ead145304785121b72dcbc1c244303de7575Daniel Buchstatic int link_status(int argc, char *argv[], void *userdata) {
b1acce80cd60fe95f16df2f1ad23ff2ad82d08e5Lennart Poettering _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
b1acce80cd60fe95f16df2f1ad23ff2ad82d08e5Lennart Poettering _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
b1acce80cd60fe95f16df2f1ad23ff2ad82d08e5Lennart Poettering char **name;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering int r;
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering r = sd_netlink_open(&rtnl);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (r < 0)
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering return log_error_errno(r, "Failed to connect to netlink: %m");
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering r = sd_hwdb_new(&hwdb);
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering if (r < 0)
c627729fc49d59ffcecc09555a34d9dd139927ceLennart Poettering log_debug_errno(r, "Failed to open hardware database: %m");
c627729fc49d59ffcecc09555a34d9dd139927ceLennart Poettering
c627729fc49d59ffcecc09555a34d9dd139927ceLennart Poettering if (argc <= 1 && !arg_all) {
c627729fc49d59ffcecc09555a34d9dd139927ceLennart Poettering _cleanup_free_ char *operational_state = NULL;
ddb7f7fc07a31937989afad53edb87b50e2cad72Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering const char *on_color_operational, *off_color_operational;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering
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
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf("%s%s%s State: %s%s%s\n",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering on_color_operational, strna(operational_state), off_color_operational);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering dump_addresses(rtnl, " Address: ", 0);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering dump_gateways(rtnl, hwdb, " Gateway: ", 0);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_get_dns(&dns);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (!strv_isempty(dns))
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering dump_list(" DNS: ", dns);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_get_domains(&domains);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (!strv_isempty(domains))
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering dump_list(" Domain: ", domains);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_get_ntp(&ntp);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!strv_isempty(ntp))
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt dump_list(" NTP: ", ntp);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering pager_open_if_enabled();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (arg_all) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering _cleanup_free_ LinkInfo *links = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int c, i;
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (r < 0)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering return rtnl_log_create_error(r);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering r = sd_netlink_message_request_dump(req, true);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering return rtnl_log_create_error(r);
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_netlink_call(rtnl, req, 0, &reply);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return log_error_errno(r, "Failed to enumerate links: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering c = decode_and_sort_links(reply, &links);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (c < 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return rtnl_log_parse_error(c);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering for (i = 0; i < c; i++) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (i > 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering fputc('\n', stdout);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering link_status_one(rtnl, hwdb, links[i].name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering } else {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering STRV_FOREACH(name, argv + 1) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (name != argv + 1)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering fputc('\n', stdout);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering link_status_one(rtnl, hwdb, *name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringconst char *lldp_system_capability_to_string(LLDPSystemCapabilities d) _const_;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart PoetteringLLDPSystemCapabilities lldp_system_capability_from_string(const char *d) _pure_;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic const char* const lldp_system_capability_table[_LLDP_SYSTEM_CAPABILITIES_MAX + 1] = {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_OTHER] = "O",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_REPEATER] = "P",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering [LLDP_SYSTEM_CAPABILITIES_BRIDGE] = "B",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_WLAN_AP] = "W",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_ROUTER] = "R",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_PHONE] = "T",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_DOCSIS] = "D",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_STATION] = "A",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_CVLAN] = "C",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_SVLAN] = "S",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering [LLDP_SYSTEM_CAPABILITIES_TPMR] = "M",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering [_LLDP_SYSTEM_CAPABILITIES_MAX] = "N/A",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering};
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(lldp_system_capability, LLDPSystemCapabilities);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic char *lldp_system_caps(uint16_t cap) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *s = NULL, *t = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering char *capability;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = strdup("[ ");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!t)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_OTHER) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_OTHER), " ", NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_REPEATER) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_REPEATER), " ", NULL);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_BRIDGE) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_BRIDGE), " ", NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_WLAN_AP) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_WLAN_AP), " ", NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_ROUTER) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_ROUTER), " ", NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_PHONE) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_PHONE), " ", NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_DOCSIS) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_DOCSIS), " ", NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_STATION) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_STATION), " ", NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_CVLAN) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_CVLAN), " ", NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_SVLAN) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_SVLAN), " ", NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (cap & LLDP_SYSTEM_CAPABILITIES_TPMR) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strappend(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_TPMR));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strappend(t, lldp_system_capability_to_string(_LLDP_SYSTEM_CAPABILITIES_MAX));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(t);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = strappend(s, "]");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!t)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(s);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering capability = t;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering t = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
return capability;
}
static int link_lldp_status(int argc, char *argv[], void *userdata) {
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
_cleanup_free_ LinkInfo *links = NULL;
const char *state, *word;
double ttl = -1;
uint32_t capability;
int i, r, c, j;
size_t ll;
char **s;
pager_open_if_enabled();
r = sd_netlink_open(&rtnl);
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
if (r < 0)
return rtnl_log_create_error(r);
r = sd_netlink_message_request_dump(req, true);
if (r < 0)
return rtnl_log_create_error(r);
r = sd_netlink_call(rtnl, req, 0, &reply);
if (r < 0)
return log_error_errno(r, "Failed to enumerate links: %m");
c = decode_and_sort_links(reply, &links);
if (c < 0)
return rtnl_log_parse_error(c);
if (arg_legend)
printf("%s %16s %24s %16s %16s\n", "Local Intf", "Device ID", "Port ID", "TTL", "Capability");
for (i = j = 0; i < c; i++) {
_cleanup_free_ char *chassis = NULL, *port = NULL, *cap = NULL, *lldp = NULL;
_cleanup_strv_free_ char **l = NULL;
r = sd_network_link_get_lldp(links[i].ifindex, &lldp);
if (r < 0)
continue;
l = strv_split_newlines(lldp);
if (!l)
return -ENOMEM;
STRV_FOREACH(s, l) {
FOREACH_WORD_QUOTED(word, ll, *s, state) {
_cleanup_free_ char *t = NULL, *a = NULL, *b = NULL;
t = strndup(word, ll);
if (!t)
return -ENOMEM;
r = split_pair(t, "=", &a, &b);
if (r < 0)
continue;
if (streq(a, "_Chassis")) {
r = free_and_strdup(&chassis, b);
if (r < 0)
return r;
} else if (streq(a, "_Port")) {
r = free_and_strdup(&port, b);
if (r < 0)
return r;
} else if (streq(a, "_TTL")) {
long long unsigned x = 0;
usec_t time;
r = safe_atollu(b, &x);
if (r < 0 || (usec_t) x != x)
return log_warning_errno(r < 0 ? r : ERANGE,
"Failed to parse TTL \"%s\": %m", b);
time = now(clock_boottime_or_monotonic());
if (x < time)
continue;
ttl = (double) (x - time) / USEC_PER_SEC;
} else if (streq(a, "_CAP")) {
sscanf(b, "%x", &capability);
cap = lldp_system_caps(capability);
}
}
if (ttl >= 0) {
printf("%10s %24s %16s %16f %16s\n",
links[i].name,
strna(chassis), strna(port),
ttl, cap);
j++;
}
}
}
if (arg_legend) {
printf("\nCapability Codes:\n"
"(O) - Other, (P) - Repeater, (B) - Bridge , (W) - WLAN Access Point, (R) = Router,\n"
"(T) - Telephone, (D) - Data Over Cable Service Interface Specifications, (A) - Station,\n"
"(C) - Customer VLAN, (S) - Service VLAN, (M) - Two-port MAC Relay (TPMR)\n\n");
printf("Total entries displayed: %d\n", j);
}
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"
" lldp Show lldp information\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:
return version();
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[]) {
const Verb verbs[] = {
{ "list", VERB_ANY, 1, VERB_DEFAULT, list_links },
{ "status", 1, VERB_ANY, 0, link_status },
{ "lldp", VERB_ANY, 1, VERB_DEFAULT, link_lldp_status },
{}
};
return dispatch_verb(argc, argv, verbs, NULL);
}
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;
}