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