networkctl.c revision ddb7f7fc07a31937989afad53edb87b50e2cad72
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen This file is part of systemd.
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen Copyright 2014 Lennart Poettering
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen systemd is free software; you can redistribute it and/or modify it
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen under the terms of the GNU Lesser General Public License as published by
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen the Free Software Foundation; either version 2.1 of the License, or
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen (at your option) any later version.
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen systemd is distributed in the hope that it will be useful, but
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen WITHOUT ANY WARRANTY; without even the implied warranty of
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen Lesser General Public License for more details.
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen You should have received a copy of the GNU Lesser General Public License
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen along with systemd; If not, see <http://www.gnu.org/licenses/>.
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic bool arg_no_pager = false;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic bool arg_legend = true;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic bool arg_all = false;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic void pager_open_if_enabled(void) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic int link_get_type_string(int iftype, struct udev_device *d, char **ret) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen const char *t;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen /* WLANs have iftype ARPHRD_ETHER, but we want
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen * to show a more useful type string for
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelementypedef struct LinkInfo {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic int link_info_compare(const void *a, const void *b) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen const LinkInfo *x = a, *y = b;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic int decode_and_sort_links(sd_rtnl_message *m, LinkInfo **ret) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen for (i = m; i; i = sd_rtnl_message_next(i)) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen r = sd_rtnl_message_read_string(i, IFLA_IFNAME, &name);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen r = sd_rtnl_message_link_get_type(i, &iftype);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen return (int) c;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic void operational_state_to_color(const char *state, const char **on, const char **off) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic void setup_state_to_color(const char *state, const char **on, const char **off) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic int list_links(char **args, unsigned n) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen _cleanup_udev_unref_ struct udev *udev = NULL;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen log_error("Failed to connect to netlink: %s", strerror(-r));
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen log_error("Failed to enumerate links: %s", strerror(-r));
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen printf("%3s %-16s %-18s %-11s %-10s\n", "IDX", "LINK", "TYPE", "OPERATIONAL", "SETUP");
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen for (i = 0; i < c; i++) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen _cleanup_udev_device_unref_ struct udev_device *d = NULL;
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen const char *on_color_operational, *off_color_operational,
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen d = udev_device_new_from_device_id(udev, devid);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n",
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen on_color_operational, strna(operational_state), off_color_operational,
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen on_color_setup, strna(setup_state), off_color_setup);
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemenstatic int dump_addresses(sd_rtnl *rtnl, const char *prefix, int ifindex) {
dc0c531b98e470892518019fb538aa687e2fa056Gabor Kelemen _cleanup_free_ struct local_address *local = NULL;
pretty);
STRV_FOREACH(i, l) {
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();
if (!vendor)
if (!model)
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 (mtu > 0)
char **name;
if (!udev) {
return -errno;
return log_oom();
if (arg_all) {
return rtnl_log_create_error(r);
return rtnl_log_create_error(r);
return rtnl_log_parse_error(c);
static void help(void) {
help();
case ARG_VERSION:
case ARG_NO_PAGER:
arg_no_pager = true;
case ARG_NO_LEGEND:
arg_legend = false;
arg_all = true;
return -EINVAL;
const char* verb;
MORE,
LESS,
} argc_cmp;
const int argc;
} verbs[] = {
int left;
if (left <= 0)
help();
return -EINVAL;
case EQUAL:
return -EINVAL;
case MORE:
return -EINVAL;
case LESS:
return -EINVAL;
log_open();
goto finish;
pager_close();