When moving the traphandler to the snmpe process I overlooked the fact
that "type" is being saved inside the switch statement under the
sm_context name. RFC3411 talks about pduType, and the name context means
something completely different in the v3 world.

The diff below moves our naming closer to the RFCs, which should
hopefully prevent further confusion in the future.

While here I made the debug output print the pduType in a human readable
format.

The invalid varbind check can be simplified a simple "{}" in the
ober_scanf_elements allowing me to just drop the type variable.

OK?

martijn@

Index: snmp.h
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmp.h,v
retrieving revision 1.16
diff -u -p -r1.16 snmp.h
--- snmp.h      30 Jun 2020 17:11:49 -0000      1.16
+++ snmp.h      7 May 2021 14:17:12 -0000
@@ -77,7 +77,7 @@ enum snmp_version {
        SNMP_V3                 = 3
 };
 
-enum snmp_context {
+enum snmp_pdutype {
        SNMP_C_GETREQ           = 0,
        SNMP_C_GETNEXTREQ       = 1,
        SNMP_C_GETRESP          = 2,
Index: snmpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v
retrieving revision 1.94
diff -u -p -r1.94 snmpd.h
--- snmpd.h     5 Feb 2021 10:30:45 -0000       1.94
+++ snmpd.h     7 May 2021 14:17:12 -0000
@@ -384,7 +384,7 @@ struct snmp_message {
        socklen_t                sm_slen;
        int                      sm_sock_tcp;
        int                      sm_aflags;
-       int                      sm_type;
+       enum snmp_pdutype        sm_pdutype;
        struct event             sm_sockev;
        char                     sm_host[HOST_NAME_MAX+1];
        in_port_t                sm_port;
@@ -405,7 +405,6 @@ struct snmp_message {
 
        /* V1, V2c */
        char                     sm_community[SNMPD_MAXCOMMUNITYLEN];
-       int                      sm_context;
 
        /* V3 */
        long long                sm_msgid;
Index: snmpe.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v
retrieving revision 1.70
diff -u -p -r1.70 snmpe.c
--- snmpe.c     22 Feb 2021 11:31:09 -0000      1.70
+++ snmpe.c     7 May 2021 14:17:12 -0000
@@ -41,6 +41,7 @@
 #include "mib.h"
 
 void    snmpe_init(struct privsep *, struct privsep_proc *, void *);
+const char *snmpe_pdutype2string(enum snmp_pdutype);
 int     snmpe_parse(struct snmp_message *);
 void    snmpe_tryparse(int, struct snmp_message *);
 int     snmpe_parsevarbinds(struct snmp_message *);
@@ -194,6 +195,36 @@ snmpe_bind(struct address *addr)
        return (-1);
 }
 
+const char *
+snmpe_pdutype2string(enum snmp_pdutype pdutype)
+{
+       static char unknown[sizeof("Unknown (4294967295)")];
+
+       switch (pdutype) {
+       case SNMP_C_GETREQ:
+               return "GetRequest";
+       case SNMP_C_GETNEXTREQ:
+               return "GetNextRequest";
+       case SNMP_C_GETRESP:
+               return "Response";
+       case SNMP_C_SETREQ:
+               return "SetRequest";
+       case SNMP_C_TRAP:
+               return "Trap";
+       case SNMP_C_GETBULKREQ:
+               return "GetBulkRequest";
+       case SNMP_C_INFORMREQ:
+               return "InformRequest";
+       case SNMP_C_TRAPV2:
+               return "SNMPv2-Trap";
+       case SNMP_C_REPORT:
+               return "Report";
+       }
+
+       snprintf(unknown, sizeof(unknown), "Unknown (%u)", pdutype);
+       return unknown;
+}
+
 int
 snmpe_parse(struct snmp_message *msg)
 {
@@ -202,7 +233,6 @@ snmpe_parse(struct snmp_message *msg)
        struct ber_element      *a;
        long long                ver, req;
        long long                errval, erridx;
-       unsigned int             type;
        u_int                    class;
        char                    *comn;
        char                    *flagstr, *ctxname;
@@ -271,15 +301,15 @@ snmpe_parse(struct snmp_message *msg)
                goto fail;
        }
 
-       if (ober_scanf_elements(msg->sm_pdu, "t{e", &class, &type, &a) != 0)
+       if (ober_scanf_elements(msg->sm_pdu, "t{e", &class, &(msg->sm_pdutype),
+           &a) != 0)
                goto parsefail;
 
        /* SNMP PDU context */
        if (class != BER_CLASS_CONTEXT)
                goto parsefail;
 
-       msg->sm_type = type;
-       switch (type) {
+       switch (msg->sm_pdutype) {
        case SNMP_C_GETBULKREQ:
                if (msg->sm_version == SNMP_V1) {
                        stats->snmp_inbadversions++;
@@ -294,7 +324,7 @@ snmpe_parse(struct snmp_message *msg)
                /* FALLTHROUGH */
 
        case SNMP_C_GETNEXTREQ:
-               if (type == SNMP_C_GETNEXTREQ)
+               if (msg->sm_pdutype == SNMP_C_GETNEXTREQ)
                        stats->snmp_ingetnexts++;
                if (!(msg->sm_aflags & ADDRESS_FLAG_READ)) {
                        msg->sm_errstr = "read requests disabled";
@@ -308,7 +338,6 @@ snmpe_parse(struct snmp_message *msg)
                        msg->sm_errstr = "wrong read community";
                        goto fail;
                }
-               msg->sm_context = type;
                break;
 
        case SNMP_C_SETREQ:
@@ -327,7 +356,6 @@ snmpe_parse(struct snmp_message *msg)
                        msg->sm_errstr = "wrong write community";
                        goto fail;
                }
-               msg->sm_context = type;
                break;
 
        case SNMP_C_GETRESP:
@@ -341,7 +369,7 @@ snmpe_parse(struct snmp_message *msg)
                        goto parsefail;
                }
        case SNMP_C_TRAPV2:
-               if (type == SNMP_C_TRAPV2 &&
+               if (msg->sm_pdutype == SNMP_C_TRAPV2 &&
                    !(msg->sm_version == SNMP_V2 ||
                    msg->sm_version != SNMP_V3)) {
                        msg->sm_errstr = "trapv2 request on !SNMPv2C or "
@@ -370,25 +398,19 @@ snmpe_parse(struct snmp_message *msg)
                        goto fail;
                /* Shortcircuit */
                return 0;
-
        default:
                msg->sm_errstr = "invalid context";
                goto parsefail;
        }
 
        /* SNMP PDU */
-       if (ober_scanf_elements(a, "iiie{et}$",
+       if (ober_scanf_elements(a, "iiie{e{}}$",
            &req, &errval, &erridx, &msg->sm_pduend,
-           &msg->sm_varbind, &class, &type) != 0) {
+           &msg->sm_varbind) != 0) {
                stats->snmp_silentdrops++;
                msg->sm_errstr = "invalid PDU";
                goto fail;
        }
-       if (class != BER_CLASS_UNIVERSAL || type != BER_TYPE_SEQUENCE) {
-               stats->snmp_silentdrops++;
-               msg->sm_errstr = "invalid varbind";
-               goto fail;
-       }
 
        msg->sm_request = req;
        msg->sm_error = errval;
@@ -396,16 +418,18 @@ snmpe_parse(struct snmp_message *msg)
 
        print_host(ss, msg->sm_host, sizeof(msg->sm_host));
        if (msg->sm_version == SNMP_V3)
-               log_debug("%s: %s:%hd: SNMPv3 context %d, flags %#x, "
+               log_debug("%s: %s:%hd: SNMPv3 pdutype %s, flags %#x, "
                    "secmodel %lld, user '%s', ctx-engine %s, ctx-name '%s', "
                    "request %lld", __func__, msg->sm_host, msg->sm_port,
-                   msg->sm_context, msg->sm_flags, msg->sm_secmodel,
-                   msg->sm_username, tohexstr(msg->sm_ctxengineid,
-                   msg->sm_ctxengineid_len), msg->sm_ctxname, msg->sm_request);
+                   snmpe_pdutype2string(msg->sm_pdutype), msg->sm_flags,
+                   msg->sm_secmodel, msg->sm_username,
+                   tohexstr(msg->sm_ctxengineid, msg->sm_ctxengineid_len),
+                   msg->sm_ctxname, msg->sm_request);
        else
-               log_debug("%s: %s:%hd: SNMPv%d '%s' context %d request %lld",
+               log_debug("%s: %s:%hd: SNMPv%d '%s' pdutype %s request %lld",
                    __func__, msg->sm_host, msg->sm_port, msg->sm_version + 1,
-                   msg->sm_community, msg->sm_context, msg->sm_request);
+                   msg->sm_community, snmpe_pdutype2string(msg->sm_pdutype),
+                   msg->sm_request);
 
        return (0);
 
@@ -451,7 +475,7 @@ snmpe_parsevarbinds(struct snmp_message 
                 * XXX intotalreqvars should only be incremented after all are
                 * succeeded
                 */
-               switch (msg->sm_context) {
+               switch (msg->sm_pdutype) {
                case SNMP_C_GETNEXTREQ:
                        if ((rvarbind = ober_add_sequence(NULL)) == NULL)
                                goto varfail;
@@ -766,8 +790,8 @@ snmpe_recvmsg(int fd, short sig, void *a
 void
 snmpe_dispatchmsg(struct snmp_message *msg)
 {
-       if (msg->sm_type == SNMP_C_TRAP ||
-           msg->sm_type == SNMP_C_TRAPV2) {
+       if (msg->sm_pdutype == SNMP_C_TRAP ||
+           msg->sm_pdutype == SNMP_C_TRAPV2) {
                snmp_msgfree(msg);
                return;
        }
@@ -776,7 +800,7 @@ snmpe_dispatchmsg(struct snmp_message *m
        (void) snmpe_parsevarbinds(msg);
 
        /* respond directly */
-       msg->sm_context = SNMP_C_GETRESP;
+       msg->sm_pdutype = SNMP_C_GETRESP;
        snmpe_response(msg);
 }
 
@@ -888,7 +912,7 @@ snmpe_encode(struct snmp_message *msg)
        }
 
        if (!ober_printf_elements(epdu, "tiii{e}", BER_CLASS_CONTEXT,
-           msg->sm_context, msg->sm_request,
+           msg->sm_pdutype, msg->sm_request,
            msg->sm_error, msg->sm_errorindex,
            msg->sm_varbindresp)) {
                ober_free_elements(pdu);
Index: usm.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/usm.c,v
retrieving revision 1.18
diff -u -p -r1.18 usm.c
--- usm.c       22 Feb 2021 11:31:09 -0000      1.18
+++ usm.c       7 May 2021 14:17:14 -0000
@@ -548,7 +548,7 @@ usm_make_report(struct snmp_message *msg
 {
        struct ber_oid           usmstat = OID(MIB_usmStats, 0, 0);
 
-       msg->sm_context = SNMP_C_REPORT;
+       msg->sm_pdutype = SNMP_C_REPORT;
        usmstat.bo_id[OIDIDX_usmStats] = msg->sm_usmerr;
        usmstat.bo_n = OIDIDX_usmStats + 2;
        if (msg->sm_varbindresp != NULL)


Reply via email to