On Wed, 2022-01-19 at 16:23 +0100, Martijn van Duren wrote: > The new code uses smi_print_element when debugging is enabled to trace > calls. Unfortunately the current smi_print_element lacks in quite a few > departments. This diff rewrites smi_print_element to be more concise > than what we currently have, without moving into the more complex > territory that snmp(1) has. > > Unknown types are printed in a similar fashion to what tcpdump(8)'s > snmp output does. > > This change helps mostly with exceptions (NOSUCH{OBJECT,INSTANCE} and > ENDOFMIBVIEW) and distinguishing between different integer types. > > I kept the current implementation under smi_print_element_legacy, so > that we don't change the output of trap handlers. We should probably > revisit that one at some point, but I don't think to go into that > territory right now. > > OK? > > martijn@ > > p.s. I'm not particularly thrilled about the type hinting, but it's > the cleanest that I could come up with without being too much of an > eyesore or filling the screen up even further. > ping
Index: smi.c =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/smi.c,v retrieving revision 1.30 diff -u -p -r1.30 smi.c --- smi.c 21 Oct 2021 15:08:15 -0000 1.30 +++ smi.c 29 Jun 2022 11:44:26 -0000 @@ -46,6 +46,7 @@ #include "snmpd.h" #include "mib.h" +#include "application.h" #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) @@ -461,8 +462,9 @@ smi_debug_elements(struct ber_element *r } #endif +/* Keep around so trap handle scripts don't break */ char * -smi_print_element(struct ber_element *root) +smi_print_element_legacy(struct ber_element *root) { char *str = NULL, *buf, *p; size_t len, i; @@ -520,6 +522,140 @@ smi_print_element(struct ber_element *ro case BER_TYPE_SET: default: str = strdup(""); + break; + } + + return (str); + + fail: + free(str); + return (NULL); +} + +char * +smi_print_element(struct ber_element *root) +{ + char *str = NULL, *buf, *p; + long long v; + struct ber_oid o; + char strbuf[BUFSIZ]; + + switch (root->be_class) { + case BER_CLASS_UNIVERSAL: + switch (root->be_type) { + case BER_TYPE_INTEGER: + if (ober_get_integer(root, &v) == -1) + goto fail; + if (asprintf(&str, "%lld", v) == -1) + goto fail; + break; + case BER_TYPE_OBJECT: + if (ober_get_oid(root, &o) == -1) + goto fail; + if (asprintf(&str, "%s", smi_oid2string(&o, strbuf, + sizeof(strbuf), 0)) == -1) + goto fail; + break; + case BER_TYPE_OCTETSTRING: + if (ober_get_string(root, &buf) == -1) + goto fail; + p = reallocarray(NULL, 4, root->be_len + 1); + if (p == NULL) + goto fail; + strvisx(p, buf, root->be_len, VIS_NL); + if (asprintf(&str, "\"%s\"", p) == -1) { + free(p); + goto fail; + } + free(p); + break; + case BER_TYPE_NULL: + if (asprintf(&str, "null") == -1) + goto fail; + break; + default: + /* Should not happen in a valid SNMP packet */ + if (asprintf(&str, "[U/%u]", root->be_type) == -1) + goto fail; + break; + } + break; + case BER_CLASS_APPLICATION: + switch (root->be_type) { + case SNMP_T_IPADDR: + if (ober_get_string(root, &buf) == -1) + goto fail; + if (asprintf(&str, "%s", + inet_ntoa(*(struct in_addr *)buf)) == -1) + goto fail; + break; + case SNMP_T_COUNTER32: + if (ober_get_integer(root, &v) == -1) + goto fail; + if (asprintf(&str, "%lld(c32)", v) == -1) + goto fail; + break; + case SNMP_T_GAUGE32: + if (ober_get_integer(root, &v) == -1) + goto fail; + if (asprintf(&str, "%lld(g32)", v) == -1) + goto fail; + break; + case SNMP_T_TIMETICKS: + if (ober_get_integer(root, &v) == -1) + goto fail; + if (asprintf(&str, "%lld.%llds", v/100, v%100) == -1) + goto fail; + break; + case SNMP_T_OPAQUE: + if (ober_get_string(root, &buf) == -1) + goto fail; + p = reallocarray(NULL, 4, root->be_len + 1); + if (p == NULL) + goto fail; + strvisx(p, buf, root->be_len, VIS_NL); + if (asprintf(&str, "\"%s\"(opaque)", p) == -1) { + free(p); + goto fail; + } + free(p); + break; + case SNMP_T_COUNTER64: + if (ober_get_integer(root, &v) == -1) + goto fail; + if (asprintf(&str, "%lld(c64)", v) == -1) + goto fail; + break; + default: + /* Should not happen in a valid SNMP packet */ + if (asprintf(&str, "[A/%u]", root->be_type) == -1) + goto fail; + break; + } + break; + case BER_CLASS_CONTEXT: + switch (root->be_type) { + case SNMP_V_NOSUCHOBJECT: + str = strdup("noSuchObject"); + break; + case SNMP_V_NOSUCHINSTANCE: + str = strdup("noSuchInstance"); + break; + case SNMP_V_ENDOFMIBVIEW: + str = strdup("endOfMibView"); + break; + default: + /* Should not happen in a valid SNMP packet */ + if (asprintf(&str, "[C/%u]", root->be_type) == -1) + goto fail; + break; + } + break; + default: + /* Should not happen in a valid SNMP packet */ + if (asprintf(&str, "[%hhu/%u]", root->be_class, + root->be_type) == -1) + goto fail; break; } Index: smi.h =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/smi.h,v retrieving revision 1.1 diff -u -p -r1.1 smi.h --- smi.h 19 Jan 2022 10:25:04 -0000 1.1 +++ smi.h 29 Jun 2022 11:44:26 -0000 @@ -25,3 +25,4 @@ char *smi_oid2string(struct ber_oid *, char *, size_t, size_t); u_long smi_getticks(void); char *smi_print_element(struct ber_element *); +char *smi_print_element_legacy(struct ber_element *); Index: snmp.h =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/snmp.h,v retrieving revision 1.18 diff -u -p -r1.18 snmp.h --- snmp.h 21 Oct 2021 14:33:13 -0000 1.18 +++ snmp.h 29 Jun 2022 11:44:26 -0000 @@ -91,6 +91,12 @@ enum snmp_pdutype { SNMP_C_REPORT = 8 }; +enum snmp_varbindtype { + SNMP_V_NOSUCHOBJECT = 0, + SNMP_V_NOSUCHINSTANCE = 1, + SNMP_V_ENDOFMIBVIEW = 2 +}; + enum snmp_application { SNMP_T_IPADDR = 0, SNMP_T_COUNTER32 = 1, Index: traphandler.c =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/traphandler.c,v retrieving revision 1.22 diff -u -p -r1.22 traphandler.c --- traphandler.c 21 Oct 2021 08:17:34 -0000 1.22 +++ traphandler.c 29 Jun 2022 11:44:26 -0000 @@ -380,7 +380,7 @@ trapcmd_exec(struct trapcmd *cmd, struct for (; vb != NULL; vb = vb->be_next) { if (ober_scanf_elements(vb, "{oeS$}", &oid, &elm) == -1) goto out; - if ((value = smi_print_element(elm)) == NULL) + if ((value = smi_print_element_legacy(elm)) == NULL) goto out; smi_oid2string(&oid, oidbuf, sizeof(oidbuf), 0); n = dprintf(s[0], "%s %s\n", oidbuf, value);