networkctl.c revision 03cc0fd1431b82e59c11ae12a274c1f2df23169d
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering This file is part of systemd.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Copyright 2014 Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is free software; you can redistribute it and/or modify it
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering under the terms of the GNU Lesser General Public License as published by
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (at your option) any later version.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is distributed in the hope that it will be useful, but
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Lesser General Public License for more details.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering You should have received a copy of the GNU Lesser General Public License
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic bool arg_no_pager = false;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic bool arg_legend = true;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void pager_open_if_enabled(void) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int link_get_type_string(int iftype, struct udev_device *d, char **ret) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *t;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* WLANs have iftype ARPHRD_ETHER, but we want
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering * to show a more useful type string for
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int list_links(char **args, unsigned n) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering unsigned c = 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to connect to netlink: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to connect to udev: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_request_dump(req, true);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to enumerate links: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf("%3s %-16s %-10s %-10s %-10s\n", "IDX", "LINK", "TYPE", "STATE", "OPERATIONAL");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *state = NULL, *operational_state = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_read_string(i, IFLA_IFNAME, &name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_link_get_type(i, &iftype);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_get_link_state(ifindex, &state);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_get_link_operational_state(ifindex, &operational_state);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering d = udev_device_new_from_device_id(udev, devid);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf("%3i %-16s %-10s %-10s %-10s\n", ifindex, name, strna(t), strna(state), strna(operational_state));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int dump_addresses(sd_rtnl *rtnl, const char *prefix, int ifindex) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ struct local_address *local = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering n = local_addresses(rtnl, ifindex, &local);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering for (i = 0; i < n; i++) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void dump_list(const char *prefix, char **l) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int link_status(char **args, unsigned n) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *operational_state = NULL;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering _cleanup_strv_free_ char **dns = NULL, **ntp = NULL;
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering sd_network_get_operational_state(&operational_state);
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering printf(" State: %s\n", operational_state);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to connect to netlink: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to connect to udev: %m");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_strv_free_ char **dns = NULL, **ntp = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_free_ char *state = NULL, *operational_state = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (safe_atoi(*name, &ifindex) >= 0 && ifindex > 0)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_append_string(req, IFLA_IFNAME, *name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Failed to query link: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_link_get_ifindex(reply, &canonical_ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_read_string(reply, IFLA_IFNAME, &canonical_name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = sd_rtnl_message_link_get_type(reply, &iftype);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering have_mac = sd_rtnl_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering for (p = (uint8_t*) &e; p < (uint8_t*) &e + sizeof(e); p++)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (*p != 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_rtnl_message_read_u32(reply, IFLA_MTU, &mtu);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_get_link_state(canonical_ifindex, &state);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_get_link_operational_state(canonical_ifindex, &operational_state);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sd_network_get_link_dns(canonical_ifindex, &dns);
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering sd_network_get_link_ntp(canonical_ifindex, &ntp);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering sprintf(devid, "n%i", canonical_ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering d = udev_device_new_from_device_id(udev, devid);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering driver = udev_device_get_property_value(d, "ID_NET_DRIVER");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering path = udev_device_get_property_value(d, "ID_PATH");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering vendor = udev_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering vendor = udev_device_get_property_value(d, "ID_VENDOR");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering model = udev_device_get_property_value(d, "ID_MODEL_FROM_DATABASE");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering model = udev_device_get_property_value(d, "ID_MODEL");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering printf("%i: %s\n", canonical_ifindex, canonical_name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering " State: %s (%s)\n",
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering h = hexmem(&e, sizeof(e));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering dump_addresses(rtnl, " Address: ", canonical_ifindex);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void help(void) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering "Query and control the networking subsystem.\n\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering " -h --help Show this help\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering " --version Show package version\n\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering " list List links\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering " status LINK Show link status\n"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering { "version", no_argument, NULL, ARG_VERSION },
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering { "no-pager", no_argument, NULL, ARG_NO_PAGER },
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int networkctl_main(int argc, char *argv[]) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering static const struct {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int (* const dispatch)(char **args, unsigned n);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Special rule: no arguments means "list" */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Unknown operation %s", argv[optind]);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Invalid number of arguments.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert_not_reached("Unknown comparison operator.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return verbs[i].dispatch(argv + optind, left);