diff options
author | Martijn van Duren <martijn@cvs.openbsd.org> | 2020-01-17 10:03:40 +0000 |
---|---|---|
committer | Martijn van Duren <martijn@cvs.openbsd.org> | 2020-01-17 10:03:40 +0000 |
commit | 70b2f3190098c61f359d53988a369db30c7b661d (patch) | |
tree | 42d5d703a7069a23a8e925cbf583e64577928dd6 /usr.bin | |
parent | b5f3b70fbebe77039a2ff1681ee798a3cfc2d6ed (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.1 | 27 | ||||
-rw-r--r-- | usr.bin/snmp/snmpc.c | 244 |
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[]) { |