networkctl.c revision 3f6fd1ba65f962702753c4ad284b588e59689a23
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
430e0468d2abb3424e7ba39f2c3929a3007293afJonathan von Schroeder This file is part of systemd.
430e0468d2abb3424e7ba39f2c3929a3007293afJonathan von Schroeder Copyright 2014 Lennart Poettering
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder systemd is free software; you can redistribute it and/or modify it
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder under the terms of the GNU Lesser General Public License as published by
430e0468d2abb3424e7ba39f2c3929a3007293afJonathan von Schroeder the Free Software Foundation; either version 2.1 of the License, or
430e0468d2abb3424e7ba39f2c3929a3007293afJonathan von Schroeder (at your option) any later version.
430e0468d2abb3424e7ba39f2c3929a3007293afJonathan von Schroeder systemd is distributed in the hope that it will be useful, but
430e0468d2abb3424e7ba39f2c3929a3007293afJonathan von Schroeder WITHOUT ANY WARRANTY; without even the implied warranty of
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder Lesser General Public License for more details.
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder You should have received a copy of the GNU Lesser General Public License
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder along with systemd; If not, see <http://www.gnu.org/licenses/>.
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic bool arg_no_pager = false;
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic bool arg_legend = true;
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic bool arg_all = false;
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic void pager_open_if_enabled(void) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic int link_get_type_string(int iftype, sd_device *d, char **ret) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder const char *devtype = NULL, *id = NULL;
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder /* WLANs have iftype ARPHRD_ETHER, but we want
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder * to show a more useful type string for
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder (void)sd_device_get_devtype(d, &devtype);
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic int link_info_compare(const void *a, const void *b) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder const LinkInfo *x = a, *y = b;
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic int decode_and_sort_links(sd_netlink_message *m, LinkInfo **ret) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder for (i = m; i; i = sd_netlink_message_next(i)) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder r = sd_netlink_message_get_type(i, &type);
f0cb315452faea6fee8144489629e63e9bd7b303Christian Maeder r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
f0cb315452faea6fee8144489629e63e9bd7b303Christian Maeder r = sd_netlink_message_read_string(i, IFLA_IFNAME, &name);
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder r = sd_rtnl_message_link_get_type(i, &iftype);
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder if (!GREEDY_REALLOC(links, size, c+1))
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder return (int) c;
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic void operational_state_to_color(const char *state, const char **on, const char **off) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder } else if (streq_ptr(state, "degraded")) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic void setup_state_to_color(const char *state, const char **on, const char **off) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder if (streq_ptr(state, "configured")) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder } else if (streq_ptr(state, "configuring")) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroederstatic int list_links(int argc, char *argv[], void *userdata) {
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder _cleanup_free_ LinkInfo *links = NULL;
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder return log_error_errno(r, "Failed to connect to netlink: %m");
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
c56a356d3fcc5e123efa790aab320781d94df3c7Jonathan von Schroeder r = sd_netlink_message_request_dump(req, true);
return rtnl_log_create_error(r);
if (arg_legend)
return rtnl_log_parse_error(c);
if (arg_legend)
const char *description;
if (!hwdb)
return -EINVAL;
if (!mac)
return -EINVAL;
return -EINVAL;
if (!desc)
return -ENOMEM;
static int get_gateway_description(
int ifindex,
int family,
char **gateway_description) {
r = sd_netlink_message_get_errno(m);
switch (fam) {
case AF_INET:
case AF_INET6:
return -ENODATA;
static int dump_gateways(
const char *prefix,
int ifindex) {
r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description);
gateway);
if (description)
if (ifindex <= 0) {
static int dump_addresses(
const char *prefix,
int ifindex) {
pretty);
if (ifindex <= 0) {
STRV_FOREACH(i, l) {
static int link_status_one(
const char *name) {
struct ether_addr e;
unsigned iftype;
int r, ifindex;
bool have_mac;
return rtnl_log_create_error(r);
return rtnl_log_create_error(r);
return rtnl_log_parse_error(r);
return rtnl_log_parse_error(r);
return rtnl_log_parse_error(r);
if (have_mac) {
const uint8_t *p;
bool all_zeroes = true;
all_zeroes = false;
if (all_zeroes)
have_mac = false;
char *wildcard;
if (!wildcard)
return log_oom();
return log_oom();
printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, name);
strna(t),
if (path)
if (driver)
if (vendor)
if (model)
if (have_mac) {
if (description)
if (mtu > 0)
if (tz)
char **name;
if (arg_all) {
return rtnl_log_create_error(r);
return rtnl_log_create_error(r);
return rtnl_log_parse_error(c);
char *capability;
return NULL;
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(t);
return NULL;
free(s);
capability = t;
s = NULL;
t = NULL;
return capability;
return rtnl_log_create_error(r);
return rtnl_log_create_error(r);
return rtnl_log_parse_error(c);
if (arg_legend)
return -ENOMEM;
STRV_FOREACH(s, l) {
return -ENOMEM;
r = safe_atollu(b, &x);
if (r < 0 || (usec_t) x != x)
if (x < time)
if (ttl >= 0) {
if (arg_legend) {
static void help(void) {
help();
case ARG_VERSION:
return version();
case ARG_NO_PAGER:
arg_no_pager = true;
case ARG_NO_LEGEND:
arg_legend = false;
arg_all = true;
return -EINVAL;
log_open();
goto finish;
pager_close();