ping
On Fri, 2021-05-28 at 08:19 +0200, Martijn van Duren wrote:
> As the original comment said:
> /*
> * This should probably go into parsevarbinds, but that's for a
> * next refactor
> */
>
> This moves the pdu parsing of traps into parsevarbinds.
> Added bonus, we can now see the packets in debugging mode:
> startup
> snmpe: listening on udp 127.0.0.1:162
> ktable_new: new ktable for rtableid 0
> snmpe_parse: 127.0.0.1:162: SNMPv2 'public' pdutype SNMPv2-Trap request
> 1329591927
> snmpe_parse: 127.0.0.1:162: SNMPv1 'public' pdutype Trap request 0
>
> OK?
>
> martijn@
>
> Index: snmpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v
> retrieving revision 1.95
> diff -u -p -r1.95 snmpd.h
> --- snmpd.h 20 May 2021 08:53:12 -0000 1.95
> +++ snmpd.h 28 May 2021 06:17:16 -0000
> @@ -776,6 +776,7 @@ int proc_flush_imsg(struct privsep *, e
>
> /* traphandler.c */
> int traphandler_parse(struct snmp_message *);
> +int traphandler_v1translate(struct snmp_message *, int);
> int traphandler_priv_recvmsg(struct privsep_proc *, struct imsg *);
> void trapcmd_free(struct trapcmd *);
> int trapcmd_add(struct trapcmd *);
> Index: snmpe.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v
> retrieving revision 1.71
> diff -u -p -r1.71 snmpe.c
> --- snmpe.c 20 May 2021 08:53:12 -0000 1.71
> +++ snmpe.c 28 May 2021 06:17:16 -0000
> @@ -368,6 +368,10 @@ snmpe_parse(struct snmp_message *msg)
> msg->sm_errstr = "trapv1 request on !SNMPv1 message";
> goto parsefail;
> }
> + /* Internally we work with SNMPv2-Traps */
> + if (traphandler_v1translate(msg, 0) == -1)
> + goto fail;
> + a = msg->sm_pdu->be_sub;
> case SNMP_C_TRAPV2:
> if (msg->sm_pdutype == SNMP_C_TRAPV2 &&
> !(msg->sm_version == SNMP_V2 ||
> @@ -390,16 +394,9 @@ snmpe_parse(struct snmp_message *msg)
> goto fail;
> }
> stats->snmp_intraps++;
> - /*
> - * This should probably go into parsevarbinds, but that's for
> a
> - * next refactor
> - */
> - if (traphandler_parse(msg) == -1)
> - goto fail;
> - /* Shortcircuit */
> - return 0;
> + break;
> default:
> - msg->sm_errstr = "invalid context";
> + msg->sm_errstr = "invalid pdutype";
> goto parsefail;
> }
>
> @@ -450,7 +447,14 @@ snmpe_parsevarbinds(struct snmp_message
> struct ber_element *pvarbind = NULL, *end;
> char buf[BUFSIZ];
> struct ber_oid o;
> - int i;
> + int i = 1;
> +
> + if (msg->sm_pdutype == SNMP_C_TRAP ||
> + msg->sm_pdutype == SNMP_C_TRAPV2) {
> + if (traphandler_parse(msg) == -1)
> + goto varfail;
> + return 0;
> + }
>
> msg->sm_errstr = "invalid varbind element";
>
> @@ -458,7 +462,7 @@ snmpe_parsevarbinds(struct snmp_message
> msg->sm_varbindresp = NULL;
> end = NULL;
>
> - for (i = 1; varbind != NULL && i < SNMPD_MAXVARBIND;
> + for (; varbind != NULL && i < SNMPD_MAXVARBIND;
> varbind = varbind->be_next, i++) {
> if (ober_scanf_elements(varbind, "{oeS$}", &o, &value) == -1)
> {
> stats->snmp_inasnparseerrs++;
> @@ -543,7 +547,7 @@ snmpe_parsevarbinds(struct snmp_message
> msg->sm_errorindex = 0;
>
> return 0;
> - varfail:
> +varfail:
> log_debug("%s: %s:%hd: %s, error index %d", __func__,
> msg->sm_host, msg->sm_port, msg->sm_errstr, i);
> if (msg->sm_error == 0)
> @@ -790,18 +794,18 @@ snmpe_recvmsg(int fd, short sig, void *a
> void
> snmpe_dispatchmsg(struct snmp_message *msg)
> {
> - if (msg->sm_pdutype == SNMP_C_TRAP ||
> - msg->sm_pdutype == SNMP_C_TRAPV2) {
> - snmp_msgfree(msg);
> - return;
> - }
> /* dispatched to subagent */
> /* XXX Do proper error handling */
> (void) snmpe_parsevarbinds(msg);
>
> - /* respond directly */
> - msg->sm_pdutype = SNMP_C_GETRESP;
> - snmpe_response(msg);
> + if (msg->sm_pdutype == SNMP_C_TRAP ||
> + msg->sm_pdutype == SNMP_C_TRAPV2)
> + snmp_msgfree(msg);
> + else {
> + /* respond directly */
> + msg->sm_pdutype = SNMP_C_GETRESP;
> + snmpe_response(msg);
> + }
> }
>
> void
> Index: traphandler.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/snmpd/traphandler.c,v
> retrieving revision 1.21
> diff -u -p -r1.21 traphandler.c
> --- traphandler.c 22 Feb 2021 11:31:09 -0000 1.21
> +++ traphandler.c 28 May 2021 06:17:16 -0000
> @@ -45,8 +45,6 @@
>
> int traphandler_priv_recvmsg(struct privsep_proc *, struct imsg *);
> int traphandler_fork_handler(struct privsep_proc *, struct imsg *);
> -struct ber_element *
> - traphandler_v1translate(struct snmp_message *, int);
> int trapcmd_cmp(struct trapcmd *, struct trapcmd *);
> void trapcmd_exec(struct trapcmd *, struct sockaddr *,
> struct ber_element *);
> @@ -76,25 +74,17 @@ traphandler_parse(struct snmp_message *m
> ssize_t buflen;
> int ret = -1;
>
> - switch (msg->sm_pdu->be_type) {
> - case SNMP_C_TRAP:
> - if ((vblist = traphandler_v1translate(msg, 0)) == NULL)
> - goto done;
> - break;
> - case SNMP_C_TRAPV2:
> - if (ober_scanf_elements(msg->sm_pdu, "{SSe}$", &elm) == -1) {
> - stats->snmp_inasnparseerrs++;
> - goto done;
> - }
> - if (elm->be_type != BER_TYPE_INTEGER) {
> - stats->snmp_inasnparseerrs++;
> - goto done;
> - }
> - vblist = ober_unlink_elements(elm);
> - break;
> - default:
> - fatalx("%s called without proper context", __func__);
> + if (ober_scanf_elements(msg->sm_pdu, "{SSe}$", &elm) == -1) {
> + stats->snmp_inasnparseerrs++;
> + msg->sm_errstr = "invalid pdu";
> + goto done;
> + }
> + if (elm->be_type != BER_TYPE_INTEGER) {
> + stats->snmp_inasnparseerrs++;
> + msg->sm_errstr = "invalid pdu";
> + goto done;
> }
> + vblist = ober_unlink_elements(elm);
>
> (void)ober_string2oid("1.3.6.1.2.1.1.3.0", &sysUpTimeOID);
> (void)ober_string2oid("1.3.6.1.6.3.1.1.4.1.0", &snmpTrapOIDOID);
> @@ -103,11 +93,13 @@ traphandler_parse(struct snmp_message *m
> ober_oid_cmp(&o1, &sysUpTimeOID) != 0 ||
> ober_oid_cmp(&o2, &snmpTrapOIDOID) != 0) {
> stats->snmp_inasnparseerrs++;
> + msg->sm_errstr = "invalid pdu";
> goto done;
> }
> (void)ober_scanf_elements(vblist, "{Se", &elm);
> for (elm = elm->be_next; elm != NULL; elm = elm->be_next) {
> if (ober_scanf_elements(elm, "{oS$}", &o1) == -1) {
> + msg->sm_errstr = "invalid pdu";
> stats->snmp_inasnparseerrs++;
> goto done;
> }
> @@ -140,7 +132,7 @@ done:
> return ret;
> }
>
> -struct ber_element *
> +int
> traphandler_v1translate(struct snmp_message *msg, int proxy)
> {
> struct snmp_stats *stats = &snmpd_env->sc_stats;
> @@ -158,7 +150,8 @@ traphandler_v1translate(struct snmp_mess
> agent_addrlen != 4 ||
> vblist->be_type != BER_TYPE_SEQUENCE) {
> stats->snmp_inasnparseerrs++;
> - return NULL;
> + msg->sm_errstr = "invalid pdu";
> + return -1;
> }
> switch (generic_trap) {
> case 0:
> @@ -184,33 +177,33 @@ traphandler_v1translate(struct snmp_mess
> /* Officially this should be 128, but BER_MAX_OID_LEN is 64 */
> if (trapoid.bo_n + 2 > BER_MAX_OID_LEN) {
> stats->snmp_inasnparseerrs++;
> - return NULL;
> + msg->sm_errstr = "enterprise too large";
> + return -1;
> }
> trapoid.bo_id[trapoid.bo_n++] = 0;
> trapoid.bo_id[trapoid.bo_n++] = specific_trap;
> break;
> default:
> stats->snmp_inasnparseerrs++;
> - return NULL;
> + msg->sm_errstr = "invalid generic-trap";
> + return -1;
> }
>
> /* work aronud net-snmp's snmptrap: It adds an EOC element in vblist
> */
> if (vblist->be_len != 0)
> vb0 = ober_unlink_elements(vblist);
> + vblist = ober_unlink_elements(msg->sm_pdu);
> + ober_free_elements(vblist);
>
> - if ((vblist = ober_add_sequence(NULL)) == NULL) {
> - msg->sm_errstr = strerror(errno);
> - if (vb0 != NULL)
> - ober_free_elements(vb0);
> - return NULL;
> - }
> - if (ober_printf_elements(vblist, "{od}{oO}e", "1.3.6.1.2.1.1.3.0",
> - time_stamp, "1.3.6.1.6.3.1.1.4.1.0", &trapoid, vb0) == NULL) {
> + if (ober_printf_elements(msg->sm_pdu, "ddd{{od}{oO}e}", 0, 0, 0,
> + "1.3.6.1.2.1.1.3.0", time_stamp, "1.3.6.1.6.3.1.1.4.1.0",
> &trapoid,
> + vb0) == NULL) {
> msg->sm_errstr = strerror(errno);
> if (vb0 != 0)
> ober_free_elements(vb0);
> ober_free_elements(vblist);
> - return NULL;
> + msg->sm_errstr = strerror(errno);
> + return -1;
> }
>
> if (proxy) {
> @@ -220,11 +213,12 @@ traphandler_v1translate(struct snmp_mess
> &snmpTrapCommunityOid);
> (void)ober_string2oid("1.3.6.1.6.3.1.1.4.3.0",
> &snmpTrapEnterpriseOid);
> - for (elm = vblist->be_sub; elm != NULL; elm = elm->be_next) {
> + ober_scanf_elements(msg->sm_pdu, "{SSS{e", &elm);
> + for (; elm != NULL; elm = elm->be_next) {
> if (ober_get_oid(elm->be_sub, &oid) == -1) {
> msg->sm_errstr = "failed to read oid";
> ober_free_elements(vblist);
> - return NULL;
> + return -1;
> }
> if (ober_oid_cmp(&oid, &snmpTrapAddressOid) == 0)
> hasaddress = 1;
> @@ -243,11 +237,11 @@ traphandler_v1translate(struct snmp_mess
> &snmpTrapEnterpriseOid, &enterprise) == NULL) {
> msg->sm_errstr = strerror(errno);
> ober_free_elements(vblist);
> - return NULL;
> + return -1;
> }
> }
> }
> - return vblist;
> + return 0;
> }
>
> int
>