summaryrefslogtreecommitdiff
path: root/src/network/networkctl.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-02-19 19:50:14 +0100
committerLennart Poettering <lennart@poettering.net>2016-02-21 20:40:57 +0100
commit837f57da416be279ef5793e43b34e41247aa90a2 (patch)
tree14a4f08c47dffe341b9355968160b116c66ad8df /src/network/networkctl.c
parent691d4da98a1288d75ea62e470280684d075e9725 (diff)
networkctl: extend "networkctl status" per-interface output to include LLDP info
This adds a small and useful field to the "systemctl status" output: the router(s) the interface is connected to as reported via LLDP. Example output: ● 2: enp0s25 Link File: /usr/lib/systemd/network/99-default.link Type: ether State: degraded (configured) Path: pci-0000:00:19.0 Driver: e1000e Connected To: GS1900 on port 2 (foobar) i.e. the last line is the relevant one.
Diffstat (limited to 'src/network/networkctl.c')
-rw-r--r--src/network/networkctl.c137
1 files changed, 104 insertions, 33 deletions
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 59d5a38ff0..c5da24e75b 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -489,6 +489,9 @@ static int dump_gateways(
_cleanup_free_ struct local_address *local = NULL;
int r, n, i;
+ assert(rtnl);
+ assert(prefix);
+
n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local);
if (n < 0)
return n;
@@ -538,6 +541,9 @@ static int dump_addresses(
_cleanup_free_ struct local_address *local = NULL;
int r, n, i;
+ assert(rtnl);
+ assert(prefix);
+
n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local);
if (n < 0)
return n;
@@ -570,6 +576,92 @@ static int dump_addresses(
return 0;
}
+static int open_lldp_neighbors(int ifindex, FILE **ret) {
+ _cleanup_free_ char *p = NULL;
+ FILE *f;
+
+ if (asprintf(&p, "/run/systemd/netif/lldp/%i", ifindex) < 0)
+ return -ENOMEM;
+
+ f = fopen(p, "re");
+ if (!f)
+ return -errno;
+
+ *ret = f;
+ return 0;
+}
+
+static int next_lldp_neighbor(FILE *f, sd_lldp_neighbor **ret) {
+ _cleanup_free_ void *raw = NULL;
+ size_t l;
+ le64_t u;
+ int r;
+
+ assert(f);
+ assert(ret);
+
+ l = fread(&u, 1, sizeof(u), f);
+ if (l == 0 && feof(f))
+ return 0;
+ if (l != sizeof(u))
+ return -EBADMSG;
+
+ raw = new(uint8_t, le64toh(u));
+ if (!raw)
+ return -ENOMEM;
+
+ if (fread(raw, 1, le64toh(u), f) != le64toh(u))
+ return -EBADMSG;
+
+ r = sd_lldp_neighbor_from_raw(ret, raw, le64toh(u));
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
+static int dump_lldp_neighbors(const char *prefix, int ifindex) {
+ _cleanup_fclose_ FILE *f = NULL;
+ int r, c = 0;
+
+ assert(prefix);
+ assert(ifindex > 0);
+
+ r = open_lldp_neighbors(ifindex, &f);
+ if (r < 0)
+ return r;
+
+ for (;;) {
+ const char *system_name = NULL, *port_id = NULL, *port_description = NULL;
+ _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
+
+ r = next_lldp_neighbor(f, &n);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ printf("%*s",
+ (int) strlen(prefix),
+ c == 0 ? prefix : "");
+
+ (void) sd_lldp_neighbor_get_system_name(n, &system_name);
+ (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id);
+ (void) sd_lldp_neighbor_get_port_description(n, &port_description);
+
+ printf("%s on port %s", strna(system_name), strna(port_id));
+
+ if (!isempty(port_description))
+ printf(" (%s)", port_description);
+
+ putchar('\n');
+
+ c++;
+ }
+
+ return c;
+}
+
static void dump_list(const char *prefix, char **l) {
char **i;
@@ -692,6 +784,8 @@ static int link_status_one(
if (tz)
printf(" Time Zone: %s", tz);
+ (void) dump_lldp_neighbors(" Connected To: ", info->ifindex);
+
return 0;
}
@@ -809,50 +903,27 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
for (i = 0; i < c; i++) {
_cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *p = NULL;
-
- if (asprintf(&p, "/run/systemd/netif/lldp/%i", links[i].ifindex) < 0)
- return log_oom();
-
- f = fopen(p, "re");
- if (!f) {
- if (errno == ENOENT)
- continue;
- log_warning_errno(errno, "Failed to open %s, ignoring: %m", p);
+ r = open_lldp_neighbors(links[i].ifindex, &f);
+ if (r == -ENOENT)
+ continue;
+ if (r < 0) {
+ log_warning_errno(r, "Failed to open LLDP data for %i, ignoring: %m", links[i].ifindex);
continue;
}
for (;;) {
const char *chassis_id = NULL, *port_id = NULL, *system_name = NULL, *port_description = NULL, *capabilities = NULL;
_cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
- _cleanup_free_ void *raw = NULL;
uint16_t cc;
- le64_t u;
- size_t l;
- l = fread(&u, 1, sizeof(u), f);
- if (l == 0 && feof(f)) /* EOF */
- break;
- if (l != sizeof(u)) {
- log_warning("Premature end of file, ignoring.");
- break;
- }
-
- raw = new(uint8_t, le64toh(u));
- if (!raw)
- return log_oom();
-
- if (fread(raw, 1, le64toh(u), f) != le64toh(u)) {
- log_warning("Premature end of file, ignoring.");
- break;
- }
-
- r = sd_lldp_neighbor_from_raw(&n, raw, le64toh(u));
+ r = next_lldp_neighbor(f, &n);
if (r < 0) {
- log_warning_errno(r, "Failed to parse LLDP data, ignoring: %m");
+ log_warning_errno(r, "Failed to read neighbor data: %m");
break;
}
+ if (r == 0)
+ break;
(void) sd_lldp_neighbor_get_chassis_id_as_string(n, &chassis_id);
(void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id);
@@ -895,7 +966,7 @@ static void help(void) {
"Commands:\n"
" list [LINK...] List links\n"
" status [LINK...] Show link status\n"
- " lldp [LINK...] Show lldp neighbors\n"
+ " lldp [LINK...] Show LLDP neighbors\n"
, program_invocation_short_name);
}