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.

Found a missing break after the BER_TYPE_NULL case.

OK?

martijn@

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 Jan 2022 07:28:15 -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 Jan 2022 07:28:15 -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 Jan 2022 07:28:15 -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 Jan 2022 07:28:15 -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);

Reply via email to