networkctl.c revision f647962d64e844689f3e2acfce6102fc47e76df2
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2014 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
#include <getopt.h>
#include "sd-network.h"
#include "sd-rtnl.h"
#include "libudev.h"
#include "build.h"
#include "util.h"
#include "pager.h"
#include "rtnl-util.h"
#include "udev-util.h"
#include "arphrd-list.h"
#include "local-addresses.h"
#include "socket-util.h"
static bool arg_no_pager = false;
static bool arg_legend = true;
static bool arg_all = false;
static void pager_open_if_enabled(void) {
if (arg_no_pager)
return;
pager_open(false);
}
const char *t;
char *p;
if (iftype == ARPHRD_ETHER && d) {
/* WLANs have iftype ARPHRD_ETHER, but we want
* to show a more useful type string for
* them */
id = "wlan";
id = "wwan";
if (id) {
if (!p)
return -ENOMEM;
*ret = p;
return 1;
}
}
t = arphrd_to_name(iftype);
if (!t) {
return 0;
}
p = strdup(t);
if (!p)
return -ENOMEM;
ascii_strlower(p);
*ret = p;
return 0;
}
typedef struct LinkInfo {
const char *name;
int ifindex;
unsigned iftype;
} LinkInfo;
static int link_info_compare(const void *a, const void *b) {
const LinkInfo *x = a, *y = b;
}
sd_rtnl_message *i;
int r;
for (i = m; i; i = sd_rtnl_message_next(i)) {
const char *name;
unsigned iftype;
int ifindex;
r = sd_rtnl_message_get_type(i, &type);
if (r < 0)
return r;
if (type != RTM_NEWLINK)
continue;
r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
if (r < 0)
return r;
if (r < 0)
return r;
r = sd_rtnl_message_link_get_type(i, &iftype);
if (r < 0)
return r;
return -ENOMEM;
c++;
}
return (int) c;
}
*on = ansi_highlight_green();
*off = ansi_highlight_off();
*on = ansi_highlight_yellow();
*off = ansi_highlight_off();
} else
}
*on = ansi_highlight_green();
*off = ansi_highlight_off();
*on = ansi_highlight_yellow();
*off = ansi_highlight_off();
*on = ansi_highlight_red();
*off = ansi_highlight_off();
} else
}
static int list_links(char **args, unsigned n) {
int r, c, i;
r = sd_rtnl_open(&rtnl, 0);
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
if (!udev) {
log_error("Failed to connect to udev: %m");
return -errno;
}
if (r < 0)
return rtnl_log_create_error(r);
r = sd_rtnl_message_request_dump(req, true);
if (r < 0)
return rtnl_log_create_error(r);
if (r < 0)
return log_error_errno(r, "Failed to enumerate links: %m");
if (arg_legend)
if (c < 0)
return rtnl_log_parse_error(c);
for (i = 0; i < c; i++) {
const char *on_color_operational, *off_color_operational,
_cleanup_free_ char *t = NULL;
printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n",
}
if (arg_legend)
printf("\n%i links listed.\n", c);
return 0;
}
int r, n, i;
if (n < 0)
return n;
for (i = 0; i < n; i++) {
if (r < 0)
return r;
printf("%*s%s\n",
i == 0 ? prefix : "",
pretty);
}
return 0;
}
char **i;
STRV_FOREACH(i, l) {
printf("%*s%s\n",
i == l ? prefix : "",
*i);
}
}
const char *on_color_operational, *off_color_operational,
struct ether_addr e;
unsigned iftype;
int r, ifindex;
bool have_mac;
else {
if (r < 0)
return rtnl_log_create_error(r);
}
if (r < 0)
return rtnl_log_create_error(r);
if (r < 0)
return log_error_errno(r, "Failed to query link: %m");
if (r < 0)
return rtnl_log_parse_error(r);
if (r < 0)
return rtnl_log_parse_error(r);
if (r < 0)
return rtnl_log_parse_error(r);
if (have_mac) {
const uint8_t *p;
bool all_zeroes = true;
if (*p != 0) {
all_zeroes = false;
break;
}
if (all_zeroes)
have_mac = false;
}
if (r > 0) {
char *wildcard;
if (!wildcard)
return log_oom();
return log_oom();
}
link_get_type_string(iftype, d, &t);
if (d) {
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);
printf(" Link File: %s\n"
"Network File: %s\n"
" Type: %s\n"
" State: %s%s%s (%s%s%s)\n",
strna(t),
if (path)
if (driver)
if (vendor)
if (model)
if (have_mac) {
char ea[ETHER_ADDR_TO_STRING_MAX];
}
if (mtu > 0)
if (!strv_isempty(dns))
if (!strv_isempty(domains))
if (!strv_isempty(ntp))
return 0;
}
static int link_status(char **args, unsigned n) {
char **name;
int r;
r = sd_rtnl_open(&rtnl, 0);
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
if (!udev) {
log_error("Failed to connect to udev: %m");
return -errno;
}
if (n <= 1 && !arg_all) {
const char *on_color_operational, *off_color_operational;
int i, c;
for (i = 0; i < c; i++) {
if (r < 0)
return log_oom();
printf("%13s %s\n",
}
if (!strv_isempty(dns))
if (!strv_isempty(domains))
if (!strv_isempty(ntp))
return 0;
}
if (arg_all) {
int c, i;
if (r < 0)
return rtnl_log_create_error(r);
r = sd_rtnl_message_request_dump(req, true);
if (r < 0)
return rtnl_log_create_error(r);
if (r < 0)
return log_error_errno(r, "Failed to enumerate links: %m");
if (c < 0)
return rtnl_log_parse_error(c);
for (i = 0; i < c; i++) {
if (i > 0)
}
}
}
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"
}
enum {
ARG_VERSION = 0x100,
};
{}
};
int c;
switch (c) {
case 'h':
help();
return 0;
case ARG_VERSION:
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 const struct {
const char* verb;
const enum {
MORE,
LESS,
} argc_cmp;
const int argc;
} verbs[] = {
};
int left;
unsigned i;
if (left <= 0)
/* Special rule: no arguments means "list" */
i = 0;
else {
help();
return 0;
}
for (i = 0; i < ELEMENTSOF(verbs); i++)
break;
if (i >= ELEMENTSOF(verbs)) {
return -EINVAL;
}
}
case EQUAL:
log_error("Invalid number of arguments.");
return -EINVAL;
}
break;
case MORE:
log_error("Too few arguments.");
return -EINVAL;
}
break;
case LESS:
log_error("Too many arguments.");
return -EINVAL;
}
break;
default:
assert_not_reached("Unknown comparison operator.");
}
}
int r;
log_open();
if (r <= 0)
goto finish;
pager_close();
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}