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