Re: snmpd(8): clean up variable printing

2022-06-29 Thread Martijn van Duren
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 -  1.30
+++ smi.c   29 Jun 2022 11:44:26 -
@@ -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 longv;
+   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;
+

Re: snmpd(8): clean up variable printing

2022-01-28 Thread Martijn van Duren
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 -  1.30
+++ smi.c   29 Jan 2022 07:28:15 -
@@ -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 longv;
+   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)"