networkctl.c revision 5323ead145304785121b72dcbc1c244303de7575
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering This file is part of systemd.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering Copyright 2014 Lennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering systemd is free software; you can redistribute it and/or modify it
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering under the terms of the GNU Lesser General Public License as published by
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering (at your option) any later version.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering systemd is distributed in the hope that it will be useful, but
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering Lesser General Public License for more details.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering You should have received a copy of the GNU Lesser General Public License
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic bool arg_no_pager = false;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic bool arg_legend = true;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic bool arg_all = false;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic void pager_open_if_enabled(void) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int link_get_type_string(int iftype, struct udev_device *d, char **ret) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering const char *t;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering /* WLANs have iftype ARPHRD_ETHER, but we want
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * to show a more useful type string for
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringtypedef struct LinkInfo {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int link_info_compare(const void *a, const void *b) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering const LinkInfo *x = a, *y = b;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int decode_and_sort_links(sd_rtnl_message *m, LinkInfo **ret) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering for (i = m; i; i = sd_rtnl_message_next(i)) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_read_string(i, IFLA_IFNAME, &name);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_link_get_type(i, &iftype);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering qsort(links, c, sizeof(LinkInfo), link_info_compare);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return (int) c;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int list_links(char **args, unsigned n) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering log_error("Failed to connect to netlink: %s", strerror(-r));
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Failed to connect to udev: %m");
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_request_dump(req, true);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Failed to enumerate links: %s", strerror(-r));
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering printf("%3s %-16s %-10s %-11s %-10s\n", "IDX", "LINK", "TYPE", "ADMIN", "OPERATIONAL");
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering c = decode_and_sort_links(reply, &links);
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering for (i = 0; i < c; i++) {
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering _cleanup_free_ char *state = NULL, *operational_state = NULL;
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering const char *on_color_oper = "", *off_color_oper = "",
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering sd_network_get_link_state(links[i].ifindex, &state);
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering sd_network_get_link_operational_state(links[i].ifindex, &operational_state);
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering d = udev_device_new_from_device_id(udev, devid);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering link_get_type_string(links[i].iftype, d, &t);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (streq_ptr(operational_state, "routable")) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering } else if (streq_ptr(operational_state, "degraded")) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering } else if (streq_ptr(state, "configuring")) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering printf("%3i %-16s %-10s %s%-11s%s %s%-10s%s\n", links[i].ifindex,
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering links[i].name, strna(t), on_color, strna(state), off_color,
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering on_color_oper, strna(operational_state), off_color_oper);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int dump_addresses(sd_rtnl *rtnl, const char *prefix, int ifindex) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering _cleanup_free_ struct local_address *local = NULL;
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering n = local_addresses(rtnl, ifindex, &local);
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering for (i = 0; i < n; i++) {
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic void dump_list(const char *prefix, char **l) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering _cleanup_strv_free_ char **dns = NULL, **ntp = NULL;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering _cleanup_free_ char *state = NULL, *operational_state = NULL;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering const char *on_color = "", *off_color = "";
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (safe_atoi(name, &ifindex) >= 0 && ifindex > 0)
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_append_string(req, IFLA_IFNAME, name);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Failed to query link: %s", strerror(-r));
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_link_get_ifindex(reply, &ifindex);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_read_string(reply, IFLA_IFNAME, &name);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = sd_rtnl_message_link_get_type(reply, &iftype);
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering have_mac = sd_rtnl_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
all_zeroes = false;
if (all_zeroes)
have_mac = false;
if (!vendor)
if (!model)
printf("%s%s%s %i: %s\n", on_color, draw_special_char(DRAW_BLACK_CIRCLE), off_color, 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();