1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "sd-network.h"
29 #include "sd-device.h"
36 #include "rtnl-util.h"
37 #include "device-util.h"
38 #include "hwdb-util.h"
39 #include "arphrd-list.h"
40 #include "local-addresses.h"
41 #include "socket-util.h"
42 #include "ether-addr-util.h"
45 static bool arg_no_pager = false;
46 static bool arg_legend = true;
47 static bool arg_all = false;
49 static void pager_open_if_enabled(void) {
57 static int link_get_type_string(int iftype, sd_device *d, char **ret) {
63 if (iftype == ARPHRD_ETHER && d) {
64 const char *devtype, *id = NULL;
65 /* WLANs have iftype ARPHRD_ETHER, but we want
66 * to show a more useful type string for
69 (void)sd_device_get_devtype(d, &devtype);
71 if (streq_ptr(devtype, "wlan"))
73 else if (streq_ptr(devtype, "wwan"))
86 t = arphrd_to_name(iftype);
102 typedef struct LinkInfo {
108 static int link_info_compare(const void *a, const void *b) {
109 const LinkInfo *x = a, *y = b;
111 return x->ifindex - y->ifindex;
114 static int decode_and_sort_links(sd_rtnl_message *m, LinkInfo **ret) {
115 _cleanup_free_ LinkInfo *links = NULL;
116 size_t size = 0, c = 0;
120 for (i = m; i; i = sd_rtnl_message_next(i)) {
126 r = sd_rtnl_message_get_type(i, &type);
130 if (type != RTM_NEWLINK)
133 r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
137 r = sd_rtnl_message_read_string(i, IFLA_IFNAME, &name);
141 r = sd_rtnl_message_link_get_type(i, &iftype);
145 if (!GREEDY_REALLOC(links, size, c+1))
148 links[c].name = name;
149 links[c].ifindex = ifindex;
150 links[c].iftype = iftype;
154 qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
162 static void operational_state_to_color(const char *state, const char **on, const char **off) {
166 if (streq_ptr(state, "routable")) {
167 *on = ansi_highlight_green();
168 *off = ansi_highlight_off();
169 } else if (streq_ptr(state, "degraded")) {
170 *on = ansi_highlight_yellow();
171 *off = ansi_highlight_off();
176 static void setup_state_to_color(const char *state, const char **on, const char **off) {
180 if (streq_ptr(state, "configured")) {
181 *on = ansi_highlight_green();
182 *off = ansi_highlight_off();
183 } else if (streq_ptr(state, "configuring")) {
184 *on = ansi_highlight_yellow();
185 *off = ansi_highlight_off();
186 } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
187 *on = ansi_highlight_red();
188 *off = ansi_highlight_off();
193 static int list_links(int argc, char *argv[], void *userdata) {
194 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
195 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
196 _cleanup_free_ LinkInfo *links = NULL;
199 pager_open_if_enabled();
201 r = sd_rtnl_open(&rtnl, 0);
203 return log_error_errno(r, "Failed to connect to netlink: %m");
205 r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
207 return rtnl_log_create_error(r);
209 r = sd_rtnl_message_request_dump(req, true);
211 return rtnl_log_create_error(r);
213 r = sd_rtnl_call(rtnl, req, 0, &reply);
215 return log_error_errno(r, "Failed to enumerate links: %m");
218 printf("%3s %-16s %-18s %-11s %-10s\n", "IDX", "LINK", "TYPE", "OPERATIONAL", "SETUP");
220 c = decode_and_sort_links(reply, &links);
222 return rtnl_log_parse_error(c);
224 for (i = 0; i < c; i++) {
225 _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
226 _cleanup_device_unref_ sd_device *d = NULL;
227 const char *on_color_operational, *off_color_operational,
228 *on_color_setup, *off_color_setup;
229 char devid[2 + DECIMAL_STR_MAX(int)];
230 _cleanup_free_ char *t = NULL;
232 sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
233 operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
235 sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
236 setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
238 sprintf(devid, "n%i", links[i].ifindex);
239 (void)sd_device_new_from_device_id(&d, devid);
241 link_get_type_string(links[i].iftype, d, &t);
243 printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n",
244 links[i].ifindex, links[i].name, strna(t),
245 on_color_operational, strna(operational_state), off_color_operational,
246 on_color_setup, strna(setup_state), off_color_setup);
250 printf("\n%i links listed.\n", c);
255 /* IEEE Organizationally Unique Identifier vendor string */
256 static int ieee_oui(sd_hwdb *hwdb, struct ether_addr *mac, char **ret) {
257 const char *description;
258 char modalias[strlen("OUI:XXYYXXYYXXYY") + 1], *desc;
269 /* skip commonly misused 00:00:00 (Xerox) prefix */
270 if (memcmp(mac, "\0\0\0", 3) == 0)
273 snprintf(modalias, sizeof(modalias), "OUI:" ETHER_ADDR_FORMAT_STR, ETHER_ADDR_FORMAT_VAL(*mac));
275 r = sd_hwdb_get(hwdb, modalias, "ID_OUI_FROM_DATABASE", &description);
279 desc = strdup(description);
288 static int get_gateway_description(
293 union in_addr_union *gateway,
294 char **gateway_description) {
295 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
300 assert(ifindex >= 0);
301 assert(family == AF_INET || family == AF_INET6);
303 assert(gateway_description);
305 r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_GETNEIGH, ifindex, family);
309 r = sd_rtnl_message_request_dump(req, true);
313 r = sd_rtnl_call(rtnl, req, 0, &reply);
317 for (m = reply; m; m = sd_rtnl_message_next(m)) {
318 union in_addr_union gw = {};
319 struct ether_addr mac = {};
323 r = sd_rtnl_message_get_errno(m);
325 log_error_errno(r, "got error: %m");
329 r = sd_rtnl_message_get_type(m, &type);
331 log_error_errno(r, "could not get type: %m");
335 if (type != RTM_NEWNEIGH) {
336 log_error("type is not RTM_NEWNEIGH");
340 r = sd_rtnl_message_neigh_get_family(m, &fam);
342 log_error_errno(r, "could not get family: %m");
347 log_error("family is not correct");
351 r = sd_rtnl_message_neigh_get_ifindex(m, &ifi);
353 log_error_errno(r, "could not get ifindex: %m");
357 if (ifindex > 0 && ifi != ifindex)
362 r = sd_rtnl_message_read_in_addr(m, NDA_DST, &gw.in);
368 r = sd_rtnl_message_read_in6_addr(m, NDA_DST, &gw.in6);
377 if (!in_addr_equal(fam, &gw, gateway))
380 r = sd_rtnl_message_read_ether_addr(m, NDA_LLADDR, &mac);
384 r = ieee_oui(hwdb, &mac, gateway_description);
394 static int dump_gateways(
399 _cleanup_free_ struct local_address *local = NULL;
402 n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local);
406 for (i = 0; i < n; i++) {
407 _cleanup_free_ char *gateway = NULL, *description = NULL;
409 r = in_addr_to_string(local[i].family, &local[i].address, &gateway);
413 r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description);
415 log_debug_errno(r, "Could not get description of gateway: %m");
418 (int) strlen(prefix),
419 i == 0 ? prefix : "",
423 printf(" (%s)", description);
425 /* Show interface name for the entry if we show
426 * entries for all interfaces */
428 char name[IF_NAMESIZE+1];
430 if (if_indextoname(local[i].ifindex, name)) {
431 fputs(" on ", stdout);
434 printf(" on %%%i", local[i].ifindex);
443 static int dump_addresses(
448 _cleanup_free_ struct local_address *local = NULL;
451 n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local);
455 for (i = 0; i < n; i++) {
456 _cleanup_free_ char *pretty = NULL;
458 r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
463 (int) strlen(prefix),
464 i == 0 ? prefix : "",
468 char name[IF_NAMESIZE+1];
470 if (if_indextoname(local[i].ifindex, name)) {
471 fputs(" on ", stdout);
474 printf(" on %%%i", local[i].ifindex);
483 static void dump_list(const char *prefix, char **l) {
488 (int) strlen(prefix),
489 i == l ? prefix : "",
494 static int link_status_one(
498 _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
499 _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
500 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
501 _cleanup_device_unref_ sd_device *d = NULL;
502 char devid[2 + DECIMAL_STR_MAX(int)];
503 _cleanup_free_ char *t = NULL, *network = NULL;
504 const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
505 const char *on_color_operational, *off_color_operational,
506 *on_color_setup, *off_color_setup;
507 _cleanup_strv_free_ char **carrier_bound_to = NULL;
508 _cleanup_strv_free_ char **carrier_bound_by = NULL;
518 if (safe_atoi(name, &ifindex) >= 0 && ifindex > 0)
519 r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
521 r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
523 return rtnl_log_create_error(r);
525 r = sd_rtnl_message_append_string(req, IFLA_IFNAME, name);
529 return rtnl_log_create_error(r);
531 r = sd_rtnl_call(rtnl, req, 0, &reply);
533 return log_error_errno(r, "Failed to query link: %m");
535 r = sd_rtnl_message_link_get_ifindex(reply, &ifindex);
537 return rtnl_log_parse_error(r);
539 r = sd_rtnl_message_read_string(reply, IFLA_IFNAME, &name);
541 return rtnl_log_parse_error(r);
543 r = sd_rtnl_message_link_get_type(reply, &iftype);
545 return rtnl_log_parse_error(r);
547 have_mac = sd_rtnl_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
551 bool all_zeroes = true;
553 for (p = (uint8_t*) &e; p < (uint8_t*) &e + sizeof(e); p++)
563 sd_rtnl_message_read_u32(reply, IFLA_MTU, &mtu);
565 sd_network_link_get_operational_state(ifindex, &operational_state);
566 operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
568 sd_network_link_get_setup_state(ifindex, &setup_state);
569 setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
571 sd_network_link_get_dns(ifindex, &dns);
572 sd_network_link_get_ntp(ifindex, &ntp);
573 sd_network_link_get_domains(ifindex, &domains);
574 r = sd_network_link_get_wildcard_domain(ifindex);
578 wildcard = strdup("*");
582 if (strv_consume(&domains, wildcard) < 0)
586 sprintf(devid, "n%i", ifindex);
588 (void)sd_device_new_from_device_id(&d, devid);
591 (void)sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
592 (void)sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
593 (void)sd_device_get_property_value(d, "ID_PATH", &path);
595 r = sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor);
597 (void)sd_device_get_property_value(d, "ID_VENDOR", &vendor);
599 r = sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model);
601 (void)sd_device_get_property_value(d, "ID_MODEL", &model);
604 link_get_type_string(iftype, d, &t);
606 sd_network_link_get_network_file(ifindex, &network);
608 sd_network_link_get_carrier_bound_to(ifindex, &carrier_bound_to);
609 sd_network_link_get_carrier_bound_by(ifindex, &carrier_bound_by);
611 printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, name);
613 printf(" Link File: %s\n"
614 " Network File: %s\n"
616 " State: %s%s%s (%s%s%s)\n",
620 on_color_operational, strna(operational_state), off_color_operational,
621 on_color_setup, strna(setup_state), off_color_setup);
624 printf(" Path: %s\n", path);
626 printf(" Driver: %s\n", driver);
628 printf(" Vendor: %s\n", vendor);
630 printf(" Model: %s\n", model);
633 _cleanup_free_ char *description = NULL;
634 char ea[ETHER_ADDR_TO_STRING_MAX];
636 ieee_oui(hwdb, &e, &description);
639 printf(" HW Address: %s (%s)\n", ether_addr_to_string(&e, ea), description);
641 printf(" HW Address: %s\n", ether_addr_to_string(&e, ea));
645 printf(" MTU: %u\n", mtu);
647 dump_addresses(rtnl, " Address: ", ifindex);
648 dump_gateways(rtnl, hwdb, " Gateway: ", ifindex);
650 if (!strv_isempty(dns))
651 dump_list(" DNS: ", dns);
652 if (!strv_isempty(domains))
653 dump_list(" Domain: ", domains);
654 if (!strv_isempty(ntp))
655 dump_list(" NTP: ", ntp);
657 if (!strv_isempty(carrier_bound_to))
658 dump_list("Carrier Bound To: ", carrier_bound_to);
660 if (!strv_isempty(carrier_bound_by))
661 dump_list("Carrier Bound By: ", carrier_bound_by);
666 static int link_status(int argc, char *argv[], void *userdata) {
667 _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
668 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
672 r = sd_rtnl_open(&rtnl, 0);
674 return log_error_errno(r, "Failed to connect to netlink: %m");
676 r = sd_hwdb_new(&hwdb);
678 log_debug_errno(r, "Failed to open hardware database: %m");
680 if (argc <= 1 && !arg_all) {
681 _cleanup_free_ char *operational_state = NULL;
682 _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
683 const char *on_color_operational, *off_color_operational;
685 sd_network_get_operational_state(&operational_state);
686 operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
688 printf("%s%s%s State: %s%s%s\n",
689 on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational,
690 on_color_operational, strna(operational_state), off_color_operational);
692 dump_addresses(rtnl, " Address: ", 0);
693 dump_gateways(rtnl, hwdb, " Gateway: ", 0);
695 sd_network_get_dns(&dns);
696 if (!strv_isempty(dns))
697 dump_list(" DNS: ", dns);
699 sd_network_get_domains(&domains);
700 if (!strv_isempty(domains))
701 dump_list(" Domain: ", domains);
703 sd_network_get_ntp(&ntp);
704 if (!strv_isempty(ntp))
705 dump_list(" NTP: ", ntp);
710 pager_open_if_enabled();
713 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
714 _cleanup_free_ LinkInfo *links = NULL;
717 r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
719 return rtnl_log_create_error(r);
721 r = sd_rtnl_message_request_dump(req, true);
723 return rtnl_log_create_error(r);
725 r = sd_rtnl_call(rtnl, req, 0, &reply);
727 return log_error_errno(r, "Failed to enumerate links: %m");
729 c = decode_and_sort_links(reply, &links);
731 return rtnl_log_parse_error(c);
733 for (i = 0; i < c; i++) {
737 link_status_one(rtnl, hwdb, links[i].name);
740 STRV_FOREACH(name, argv + 1) {
741 if (name != argv + 1)
744 link_status_one(rtnl, hwdb, *name);
751 const char *lldp_system_capability_to_string(LLDPSystemCapabilities d) _const_;
752 LLDPSystemCapabilities lldp_system_capability_from_string(const char *d) _pure_;
754 static const char* const lldp_system_capability_table[_LLDP_SYSTEM_CAPABILITIES_MAX + 1] = {
755 [LLDP_SYSTEM_CAPABILITIES_OTHER] = "O",
756 [LLDP_SYSTEM_CAPABILITIES_REPEATER] = "P",
757 [LLDP_SYSTEM_CAPABILITIES_BRIDGE] = "B",
758 [LLDP_SYSTEM_CAPABILITIES_WLAN_AP] = "W",
759 [LLDP_SYSTEM_CAPABILITIES_ROUTER] = "R",
760 [LLDP_SYSTEM_CAPABILITIES_PHONE] = "T",
761 [LLDP_SYSTEM_CAPABILITIES_DOCSIS] = "D",
762 [LLDP_SYSTEM_CAPABILITIES_STATION] = "A",
763 [LLDP_SYSTEM_CAPABILITIES_CVLAN] = "C",
764 [LLDP_SYSTEM_CAPABILITIES_SVLAN] = "S",
765 [LLDP_SYSTEM_CAPABILITIES_TPMR] = "M",
766 [_LLDP_SYSTEM_CAPABILITIES_MAX] = "N/A",
769 DEFINE_STRING_TABLE_LOOKUP(lldp_system_capability, LLDPSystemCapabilities);
771 static char *lldp_system_caps(uint16_t cap) {
772 _cleanup_free_ char *s = NULL, *t = NULL;
779 if (cap & LLDP_SYSTEM_CAPABILITIES_OTHER) {
780 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_OTHER), " ", NULL);
788 if (cap & LLDP_SYSTEM_CAPABILITIES_REPEATER) {
789 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_REPEATER), " ", NULL);
797 if (cap & LLDP_SYSTEM_CAPABILITIES_BRIDGE) {
798 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_BRIDGE), " ", NULL);
806 if (cap & LLDP_SYSTEM_CAPABILITIES_WLAN_AP) {
807 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_WLAN_AP), " ", NULL);
815 if (cap & LLDP_SYSTEM_CAPABILITIES_ROUTER) {
816 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_ROUTER), " ", NULL);
824 if (cap & LLDP_SYSTEM_CAPABILITIES_PHONE) {
825 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_PHONE), " ", NULL);
833 if (cap & LLDP_SYSTEM_CAPABILITIES_DOCSIS) {
834 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_DOCSIS), " ", NULL);
842 if (cap & LLDP_SYSTEM_CAPABILITIES_STATION) {
843 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_STATION), " ", NULL);
851 if (cap & LLDP_SYSTEM_CAPABILITIES_CVLAN) {
852 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_CVLAN), " ", NULL);
860 if (cap & LLDP_SYSTEM_CAPABILITIES_SVLAN) {
861 s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_SVLAN), " ", NULL);
869 if (cap & LLDP_SYSTEM_CAPABILITIES_TPMR) {
870 s = strappend(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_TPMR));
878 s = strappend(t, lldp_system_capability_to_string(_LLDP_SYSTEM_CAPABILITIES_MAX));
885 t = strappend(s, "]");
898 static int link_lldp_status(int argc, char *argv[], void *userdata) {
899 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
900 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
901 _cleanup_free_ LinkInfo *links = NULL;
902 const char *state, *word;
910 pager_open_if_enabled();
912 r = sd_rtnl_open(&rtnl, 0);
914 return log_error_errno(r, "Failed to connect to netlink: %m");
916 r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
918 return rtnl_log_create_error(r);
920 r = sd_rtnl_message_request_dump(req, true);
922 return rtnl_log_create_error(r);
924 r = sd_rtnl_call(rtnl, req, 0, &reply);
926 return log_error_errno(r, "Failed to enumerate links: %m");
928 c = decode_and_sort_links(reply, &links);
930 return rtnl_log_parse_error(c);
933 printf("%s %16s %24s %16s %16s\n", "Local Intf", "Device ID", "Port ID", "TTL", "Capability");
935 for (i = j = 0; i < c; i++) {
936 _cleanup_free_ char *chassis = NULL, *port = NULL, *cap = NULL, *lldp = NULL;
937 _cleanup_strv_free_ char **l = NULL;
939 r = sd_network_link_get_lldp(links[i].ifindex, &lldp);
943 l = strv_split_newlines(lldp);
948 FOREACH_WORD_QUOTED(word, ll, *s, state) {
949 _cleanup_free_ char *t = NULL, *a = NULL, *b = NULL;
951 t = strndup(word, ll);
955 r = split_pair(t, "=", &a, &b);
959 if (streq(a, "_Chassis")) {
960 r = free_and_strdup(&chassis, b);
964 } else if (streq(a, "_Port")) {
965 r = free_and_strdup(&port, b);
969 } else if (streq(a, "_TTL")) {
970 long long unsigned x = 0;
973 r = safe_atollu(b, &x);
974 if (r < 0 || (usec_t) x != x)
975 return log_warning_errno(r < 0 ? r : ERANGE,
976 "Failed to parse TTL \"%s\": %m", b);
978 time = now(CLOCK_BOOTTIME);
982 ttl = (double) (x - time) / USEC_PER_SEC;
984 } else if (streq(a, "_CAP")) {
985 sscanf(b, "%x", &capability);
987 cap = lldp_system_caps(capability);
993 printf("%10s %24s %16s %16f %16s\n",
995 strna(chassis), strna(port),
1003 printf("\nCapability Codes:\n"
1004 "(O) - Other, (P) - Repeater, (B) - Bridge , (W) - WLAN Access Point, (R) = Router,\n"
1005 "(T) - Telephone, (D) - Data Over Cable Service Interface Specifications, (A) - Station,\n"
1006 "(C) - Customer VLAN, (S) - Service VLAN, (M) - Two-port MAC Relay (TPMR)\n\n");
1008 printf("Total entries displayed: %d\n", j);
1014 static void help(void) {
1015 printf("%s [OPTIONS...]\n\n"
1016 "Query and control the networking subsystem.\n\n"
1017 " -h --help Show this help\n"
1018 " --version Show package version\n"
1019 " --no-pager Do not pipe output into a pager\n"
1020 " --no-legend Do not show the headers and footers\n"
1021 " -a --all Show status for all links\n\n"
1023 " list List links\n"
1024 " status [LINK...] Show link status\n"
1025 " lldp Show lldp information\n"
1026 , program_invocation_short_name);
1029 static int parse_argv(int argc, char *argv[]) {
1032 ARG_VERSION = 0x100,
1037 static const struct option options[] = {
1038 { "help", no_argument, NULL, 'h' },
1039 { "version", no_argument, NULL, ARG_VERSION },
1040 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1041 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1042 { "all", no_argument, NULL, 'a' },
1051 while ((c = getopt_long(argc, argv, "ha", options, NULL)) >= 0) {
1060 puts(PACKAGE_STRING);
1061 puts(SYSTEMD_FEATURES);
1065 arg_no_pager = true;
1080 assert_not_reached("Unhandled option");
1087 static int networkctl_main(int argc, char *argv[]) {
1088 const Verb verbs[] = {
1089 { "list", VERB_ANY, 1, VERB_DEFAULT, list_links },
1090 { "status", 1, VERB_ANY, 0, link_status },
1091 { "lldp", VERB_ANY, 1, VERB_DEFAULT, link_lldp_status },
1095 return dispatch_verb(argc, argv, verbs, NULL);
1098 int main(int argc, char* argv[]) {
1101 log_parse_environment();
1104 r = parse_argv(argc, argv);
1108 r = networkctl_main(argc, argv);
1113 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;