summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorMartijn van Duren <martijn@cvs.openbsd.org>2020-01-17 10:03:40 +0000
committerMartijn van Duren <martijn@cvs.openbsd.org>2020-01-17 10:03:40 +0000
commit70b2f3190098c61f359d53988a369db30c7b661d (patch)
tree42d5d703a7069a23a8e925cbf583e64577928dd6 /usr.bin
parentb5f3b70fbebe77039a2ff1681ee798a3cfc2d6ed (diff)
Implement a df subcommand, this outputs disk and memory information in a
df(1) format. OK jan@ General positive sounds from the hackroom and Michael W Lucas
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/snmp/snmp.127
-rw-r--r--usr.bin/snmp/snmpc.c244
2 files changed, 266 insertions, 5 deletions
diff --git a/usr.bin/snmp/snmp.1 b/usr.bin/snmp/snmp.1
index b479fe1031c..3bba7b09ec7 100644
--- a/usr.bin/snmp/snmp.1
+++ b/usr.bin/snmp/snmp.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: snmp.1,v 1.9 2020/01/17 09:49:47 martijn Exp $
+.\" $OpenBSD: snmp.1,v 1.10 2020/01/17 10:03:39 martijn Exp $
.\"
.\" Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
.\"
@@ -43,6 +43,10 @@
.Ar agent uptime trapoid
.Oo Ar varoid type value Oc ...
.Nm
+.Cm df
+.Op Ar options
+.Ar agent
+.Nm
.Cm mibtree
.Op Fl O Ar fns
.Sh DESCRIPTION
@@ -151,6 +155,16 @@ The
is the identification OID used by the trap handler to determine its action.
This command is not available for
.Fl v Cm 1 .
+.It Xo
+.Nm
+.Cm df
+.Op Ar options
+.Ar agent
+.Xc
+An SNMP based version of the
+.Xr df 1
+command.
+If no size suffix is shown the sizes are in kilobytes.
.It Nm Cm mibtree Op Fl O Ar fnS
Dump the tree of compiled-in MIB objects.
.El
@@ -208,6 +222,12 @@ walk the tree up to but excluding
The blank before
.Ar endoid
is mandatory.
+.It Cm h
+For
+.Cm df
+print the output in
+.Dq human-readable
+format.
.It Cm I
For
.Cm walk ,
@@ -247,9 +267,10 @@ or
also show a summary of the total variables received.
.It Cm r Ns Ar maxrep
For
-.Cm bulkget
+.Cm bulkget ,
+.Cm bulkwalk
and
-.Cm bulkwalk ,
+.Cm df ,
set the max-repetitions field in the request to the positive integer
.Ar maxrep .
This determines the amount of MIBs to return for each specified OID.
diff --git a/usr.bin/snmp/snmpc.c b/usr.bin/snmp/snmpc.c
index 53d86574835..641272173b2 100644
--- a/usr.bin/snmp/snmpc.c
+++ b/usr.bin/snmp/snmpc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmpc.c,v 1.18 2020/01/17 09:49:47 martijn Exp $ */
+/* $OpenBSD: snmpc.c,v 1.19 2020/01/17 10:03:39 martijn Exp $ */
/*
* Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
@@ -37,6 +37,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <util.h>
#include "smi.h"
#include "snmp.h"
@@ -48,6 +49,7 @@ int snmpc_get(int, char *[]);
int snmpc_walk(int, char *[]);
int snmpc_set(int, char *[]);
int snmpc_trap(int, char *[]);
+int snmpc_df(int, char *[]);
int snmpc_mibtree(int, char *[]);
struct snmp_agent *snmpc_connect(char *, char *);
int snmpc_parseagent(char *, char *);
@@ -74,6 +76,7 @@ struct snmp_app snmp_apps[] = {
{ "bulkwalk", 1, "C:", "[-C cipn<nonrep>r<maxrep>] agent [oid]", snmpc_walk },
{ "set", 1, NULL, "agent oid type value [oid type value] ...", snmpc_set },
{ "trap", 1, NULL, "agent uptime oid [oid type value] ...", snmpc_trap },
+ { "df", 1, "C:", "[-Ch] agent", snmpc_df },
{ "mibtree", 0, "O:", "[-O fnS]", snmpc_mibtree }
};
struct snmp_app *snmp_app = NULL;
@@ -88,6 +91,7 @@ int print_equals = 1;
int print_varbind_only = 0;
int print_summary = 0;
int print_time = 0;
+int print_human = 0;
int walk_check_increase = 1;
int walk_fallback_oid = 1;
int walk_include_oid = 0;
@@ -275,6 +279,11 @@ main(int argc, char *argv[])
usage();
walk_check_increase = 0;
break;
+ case 'h':
+ if (strcmp(snmp_app->name, "df"))
+ usage();
+ print_human = 1;
+ break;
case 'i':
if (strcmp(snmp_app->name, "walk") &&
strcmp(snmp_app->name, "bulkwalk"))
@@ -310,7 +319,8 @@ main(int argc, char *argv[])
break;
case 'r':
if (strcmp(snmp_app->name, "bulkget") &&
- strcmp(snmp_app->name, "bulkwalk"))
+ strcmp(snmp_app->name, "bulkwalk") &&
+ strcmp(snmp_app->name, "df"))
usage();
errno = 0;
max_repetitions = strtol(&optarg[i + 1],
@@ -554,6 +564,7 @@ snmpc_get(int argc, char *argv[])
if (!snmpc_print(varbind))
err(1, "Can't print response");
}
+ sleep(10);
ober_free_elements(pdu);
snmp_free_agent(agent);
return 0;
@@ -789,6 +800,235 @@ snmpc_trap(int argc, char *argv[])
return 0;
}
+#define INCR_NEXTTAB(x) ((x + 8) & ~7)
+#define NEXTTAB(x) (8 - (x & 7))
+int
+snmpc_df(int argc, char *argv[])
+{
+ struct snmpc_df {
+ uint32_t index;
+ /* DisplayString is 255a DISPLAY-HINT */
+ char descr[256];
+ /* Theoretical maximum for 2 32 bit values multiplied */
+ char size[21];
+ char used[21];
+ char avail[21];
+ char proc[5];
+ } *df = NULL;
+ struct ber_oid descroid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 3 }, 11};
+ struct ber_oid unitsoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 4 }, 11};
+ struct ber_oid sizeoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 5 }, 11};
+ struct ber_oid usedoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 6 }, 11};
+ struct ber_oid oid, *reqoid;
+ struct ber_element *pdu, *varbind;
+ struct snmp_agent *agent;
+ int errorstatus, errorindex;
+ int class;
+ size_t i, j, rows = 0;
+ unsigned type;
+ char *string;
+ int descrlen = 0, sizelen = 0, usedlen = 0, availlen = 0, proclen = 0;
+ int len;
+ long long units, size, used;
+ int fmtret;
+
+ if (argc != 1)
+ usage();
+
+ if ((agent = snmpc_connect(argv[0], "161")) == NULL)
+ err(1, "%s", snmp_app->name);
+ agent->timeout = timeout;
+ agent->retries = retries;
+
+ if (pledge("stdio", NULL) == -1)
+ err(1, "pledge");
+
+ descrlen = sizeof("Description") - 1;
+ sizelen = sizeof("Size") - 1;
+ usedlen = sizeof("Used") - 1;
+ availlen = sizeof("Available") - 1;
+ proclen = sizeof("Used%") - 1;
+
+ bcopy(&descroid, &oid, sizeof(descroid));
+
+ i = 0;
+ while(1) {
+ if (version < SNMP_V2C) {
+ if ((pdu = snmp_getnext(agent, &oid, 1)) == NULL)
+ err(1, "df");
+ } else {
+ if ((pdu = snmp_getbulk(agent, &oid, 1, 0,
+ max_repetitions)) == NULL)
+ err(1, "df");
+ }
+
+ (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
+ &errorstatus, &errorindex, &varbind);
+ if (errorstatus != 0)
+ snmpc_printerror((enum snmp_error) errorstatus, varbind,
+ errorindex, NULL);
+
+ if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT) {
+ printf("Received report:\n");
+ for (; varbind != NULL; varbind = varbind->be_next) {
+ if (!snmpc_print(varbind))
+ err(1, "Can't print response");
+ }
+ return 1;
+ }
+ for (; varbind != NULL; varbind = varbind->be_next) {
+ (void) ober_scanf_elements(varbind, "{oS", &oid);
+ if (ober_oid_cmp(&descroid, &oid) != 2)
+ break;
+ rows++;
+ }
+ if ((df = reallocarray(df, rows, sizeof(*df))) == NULL)
+ err(1, "malloc");
+ (void) ober_scanf_elements(pdu, "{SSS{e", &varbind);
+ for (; i < rows; varbind = varbind->be_next, i++) {
+ if (ober_scanf_elements(varbind, "{os", &oid,
+ &string) == -1) {
+ i--;
+ rows--;
+ continue;
+ }
+ df[i].index = oid.bo_id[oid.bo_n - 1];
+ len = strlcpy(df[i].descr, string,
+ sizeof(df[i].descr));
+ if (len > (int) sizeof(df[i].descr))
+ len = (int) sizeof(df[i].descr) - 1;
+ if (len > descrlen)
+ descrlen = len;
+ }
+ ober_free_elements(pdu);
+ if (varbind != NULL)
+ break;
+ }
+
+ if (max_repetitions < 3)
+ max_repetitions = 3;
+ if ((reqoid = reallocarray(NULL, max_repetitions, sizeof(*reqoid))) == NULL)
+ err(1, "malloc");
+ for (i = 0; i < rows;) {
+ for (j = 0; i + j < rows && j < (size_t)max_repetitions / 3;
+ j++) {
+ bcopy(&unitsoid, &(reqoid[(j * 3) + 0]),
+ sizeof(unitsoid));
+ reqoid[(j * 3) + 0].bo_id[
+ reqoid[(j * 3) + 0].bo_n++] = df[i + j].index;
+ bcopy(&sizeoid, &(reqoid[(j * 3) + 1]),
+ sizeof(sizeoid));
+ reqoid[(j * 3) + 1].bo_id[
+ reqoid[(j * 3) + 1].bo_n++] = df[i + j].index;
+ bcopy(&usedoid, &(reqoid[(j * 3) + 2]),
+ sizeof(usedoid));
+ reqoid[(j * 3) + 2].bo_id[
+ reqoid[(j * 3) + 2].bo_n++] = df[i + j].index;
+ }
+ if ((pdu = snmp_get(agent, reqoid, j * 3)) == NULL)
+ err(1, "df");
+ (void) ober_scanf_elements(pdu, "t{Sdd{e", &class, &type,
+ &errorstatus, &errorindex, &varbind);
+ if (errorstatus != 0)
+ snmpc_printerror((enum snmp_error) errorstatus, varbind,
+ errorindex, NULL);
+ if (class == BER_CLASS_CONTEXT && type == SNMP_C_REPORT) {
+ printf("Received report:\n");
+ for (; varbind != NULL; varbind = varbind->be_next) {
+ if (!snmpc_print(varbind))
+ err(1, "Can't print response");
+ }
+ }
+ for (j = 0; varbind != NULL; i++) {
+ if (ober_scanf_elements(varbind, "{oi}{oi}{oi}",
+ &(reqoid[0]), &units, &(reqoid[1]), &size,
+ &(reqoid[2]), &used, &varbind) == -1) {
+ break;
+ }
+ varbind = varbind->be_next->be_next->be_next;
+
+ unitsoid.bo_id[unitsoid.bo_n++] = df[i].index;
+ if (ober_oid_cmp(&unitsoid, &(reqoid[0])) != 0) {
+ warnx("df: received invalid object");
+ break;
+ }
+ unitsoid.bo_n--;
+ sizeoid.bo_id[sizeoid.bo_n++] = df[i].index;
+ if (ober_oid_cmp(&sizeoid, &(reqoid[1])) != 0) {
+ warnx("df: received invalid object");
+ break;
+ }
+ sizeoid.bo_n--;
+ usedoid.bo_id[usedoid.bo_n++] = df[i].index;
+ if (ober_oid_cmp(&usedoid, &(reqoid[2])) != 0) {
+ warnx("df: received invalid object");
+ break;
+ }
+ usedoid.bo_n--;
+ if (print_human)
+ fmtret = fmt_scaled((units * size), df[i].size);
+ if (!print_human || fmtret == -1)
+ snprintf(df[i].size, sizeof(df[i].size), "%lld",
+ (units * size) / 1024);
+ len = (int) strlen(df[i].size);
+ if (len > sizelen)
+ sizelen = len;
+ if (print_human)
+ fmtret = fmt_scaled(units * used, df[i].used);
+ if (!print_human || fmtret == -1)
+ snprintf(df[i].used, sizeof(df[i].used), "%lld",
+ (units * used) / 1024);
+ len = (int) strlen(df[i].used);
+ if (len > usedlen)
+ usedlen = len;
+ if (print_human)
+ fmtret = fmt_scaled(units * (size - used),
+ df[i].avail);
+ if (!print_human || fmtret == -1)
+ snprintf(df[i].avail, sizeof(df[i].avail),
+ "%lld", (units * (size - used)) / 1024);
+ len = (int) strlen(df[i].avail);
+ if (len > usedlen)
+ availlen = len;
+ if (size == 0)
+ strlcpy(df[i].proc, "0%", sizeof(df[i].proc));
+ else {
+ snprintf(df[i].proc, sizeof(df[i].proc),
+ "%lld%%", (used * 100) / size);
+ }
+ len = (int) strlen(df[i].proc);
+ if (len > proclen)
+ proclen = len;
+ j++;
+ }
+ if (j == 0) {
+ warnx("Failed to retrieve information for %s",
+ df[i].descr);
+ memmove(df + i, df + i + 1,
+ (rows - i - 1) * sizeof(*df));
+ rows--;
+ i--;
+ }
+ }
+
+ printf("%-*s%*s%*s%*s%*s\n",
+ descrlen, "Description",
+ NEXTTAB(descrlen) + sizelen, "Size",
+ NEXTTAB(sizelen) + usedlen, "Used",
+ NEXTTAB(usedlen) + availlen, "Available",
+ NEXTTAB(availlen) + proclen, "Used%");
+ for (i = 0; i < rows; i++) {
+ printf("%-*s%*s%*s%*s%*s\n",
+ descrlen, df[i].descr,
+ NEXTTAB(descrlen) + sizelen, df[i].size,
+ NEXTTAB(sizelen) + usedlen, df[i].used,
+ NEXTTAB(usedlen) + availlen, df[i].avail,
+ NEXTTAB(availlen) + proclen, df[i].proc);
+ }
+
+ return 0;
+}
+
int
snmpc_mibtree(int argc, char *argv[])
{