networkctl.c revision 1d050e1e0a7082e23ee9b31fa0b819cb332b3444
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering This file is part of systemd.
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering Copyright 2014 Lennart 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 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 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/>.
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic bool arg_no_pager = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic bool arg_legend = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic bool arg_all = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic void pager_open_if_enabled(void) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int link_get_type_string(int iftype, struct udev_device *d, char **ret) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const char *t;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* WLANs have iftype ARPHRD_ETHER, but we want
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * to show a more useful type string for
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poetteringtypedef struct LinkInfo {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poetteringstatic int link_info_compare(const void *a, const void *b) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering const LinkInfo *x = a, *y = b;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poetteringstatic int decode_and_sort_links(sd_rtnl_message *m, LinkInfo **ret) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering for (i = m; i; i = sd_rtnl_message_next(i)) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering r = sd_rtnl_message_read_string(i, IFLA_IFNAME, &name);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering r = sd_rtnl_message_link_get_type(i, &iftype);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return (int) c;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic void operational_state_to_color(const char *state, const char **on, const char **off) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering } else if (streq_ptr(state, "degraded")) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poetteringstatic void setup_state_to_color(const char *state, const char **on, const char **off) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering } else if (streq_ptr(state, "configuring")) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poetteringstatic int list_links(char **args, unsigned n) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return log_error_errno(r, "Failed to connect to netlink: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return log_error_errno(errno, "Failed to connect to udev: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return log_error_errno(r, "Failed to enumerate links: %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering printf("%3s %-16s %-18s %-11s %-10s\n", "IDX", "LINK", "TYPE", "OPERATIONAL", "SETUP");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering c = decode_and_sort_links(reply, &links);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (i = 0; i < c; i++) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering const char *on_color_operational, *off_color_operational,
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering d = udev_device_new_from_device_id(udev, devid);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering link_get_type_string(links[i].iftype, d, &t);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering links[i].ifindex, links[i].name, strna(t),
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering on_color_operational, strna(operational_state), off_color_operational,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering on_color_setup, strna(setup_state), off_color_setup);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering/* IEEE Organizationally Unique Identifier vendor string */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int ieee_oui(struct udev_hwdb *hwdb, struct ether_addr *mac, char **ret) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering char str[strlen("OUI:XXYYXXYYXXYY") + 1];
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering /* skip commonly misused 00:00:00 (Xerox) prefix */
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering snprintf(str, sizeof(str), "OUI:" ETHER_ADDR_FORMAT_STR, ETHER_ADDR_FORMAT_VAL(*mac));
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, str, 0))
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (strcmp(udev_list_entry_get_name(entry), "ID_OUI_FROM_DATABASE") == 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering description = strdup(udev_list_entry_get_value(entry));
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poetteringstatic int get_gateway_description(sd_rtnl *rtnl, struct udev_hwdb *hwdb, int ifindex, int family,
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering union in_addr_union *gateway, char **gateway_description) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(family == AF_INET || family == AF_INET6);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_GETNEIGH, ifindex, family);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (m = reply; m; m = sd_rtnl_message_next(m)) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error_errno(r, "could not get type: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_rtnl_message_neigh_get_family(m, &fam);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error_errno(r, "could not get family: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_rtnl_message_neigh_get_ifindex(m, &ifi);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error_errno(r, "could not get ifindex: %m");
90d14d2015dda79c7b465b74dd3aaf2dfc25d43cLuke Shumaker r = sd_rtnl_message_read_in_addr(m, NDA_DST, &gw.in);
eaf73b061604c028aa28f960870a9b46aab2f76aLuke Shumaker r = sd_rtnl_message_read_in6_addr(m, NDA_DST, &gw.in6);
90d14d2015dda79c7b465b74dd3aaf2dfc25d43cLuke Shumaker r = sd_rtnl_message_read_ether_addr(m, NDA_LLADDR, &mac);
90d14d2015dda79c7b465b74dd3aaf2dfc25d43cLuke Shumaker r = ieee_oui(hwdb, &mac, gateway_description);
90d14d2015dda79c7b465b74dd3aaf2dfc25d43cLuke Shumakerstatic int dump_gateways(sd_rtnl *rtnl, struct udev_hwdb *hwdb, const char *prefix, int ifindex) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
int family;
r = sd_rtnl_message_get_errno(m);
switch (family) {
case AF_INET:
case AF_INET6:
if (gateway_description)
gateway);
first = false;
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 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();