Moving post from misc@.

On 2015-10-07, Denis Fondras <open...@ledeuns.net> wrote:
> Hello,
>
> I'm using snmpd from base on 5.8 and while playing with snmpbulkget (from
> net-snmp), I noticed a weirdness.
>
> * 'snmpbulkget -v2c -c public 10.100.200.19 iso.3.6.1.2.1.1' is ok
> * 'snmpbulkget -v2c -c public 10.100.200.19 iso.3.6.1.2.1.31.1.1' is ok
>
> By "ok", I mean it returns the correct MIB results. However,
>
> * 'snmpbulkget -v2c -c public 10.100.200.19 iso.3.6.1.2.1.31.1.1
>  iso.3.6.1.2.1.1' is not ok :
> -----8<-----
>  iso.3.6.1.2.1.31.1.1.1.1.1 = STRING: "em0"
>  iso.3.6.1.2.1.1.1.0 = STRING: "OpenBSD test.my.domain 5.8 GENERIC#3 i386"
>  iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.30155.23.1
>  iso.3.6.1.2.1.1.3.0 = Timeticks: (217) 0:00:02.17
>  iso.3.6.1.2.1.1.4.0 = STRING: "r...@test.my.domain"
>  iso.3.6.1.2.1.1.5.0 = STRING: "test.my.domain"
>  iso.3.6.1.2.1.1.6.0 = ""
>  iso.3.6.1.2.1.1.7.0 = INTEGER: 74
>  iso.3.6.1.2.1.1.8.0 = Timeticks: (0) 0:00:00.00
>  iso.3.6.1.2.1.1.9.1.1.1 = INTEGER: 1
>  iso.3.6.1.2.1.1.9.1.1.2 = INTEGER: 2
> -----8<-----
>
> As you can see, only the first sub-OID of iso.3.6.1.2.1.31.1.1 is returned.

To make it clear, that last command is meant to return 10x results starting
from iso.3.6.1.2.1.1 and 10x results starting from iso.3.6.1.2.1.31.1.1.

There are two parameters involved in GetBulkReq, "non-repeaters"
(snmpbulkget -Cn# which defaults to 0) and "max-repetitions"
(-Cr# defaulting to 10).

The response should be single results for the first "non-repeaters"
requests (allowing you to fetch e.g. the uptime and maybe some other
individual values of interest without a bunch of unwanted extras),
followed by "maxrep" number of values for any subsequent requests.

$ snmpbulkget -Cn2 -Cr4 -v2c -c public 127.0.0.1 SNMPv2-MIB::sysDescr 
IP-MIB::ipForwarding IF-MIB::ifName IF-MIB::ifInOctets
SNMPv2-MIB::sysDescr.0 = STRING: some host description
IP-MIB::ipForwarding.0 = INTEGER: notForwarding(2)
IF-MIB::ifName.1 = STRING: em0
IF-MIB::ifName.2 = STRING: em1
IF-MIB::ifName.3 = STRING: enc0
IF-MIB::ifName.4 = STRING: lo0
IF-MIB::ifInOctets.1 = Counter32: 4019922211
IF-MIB::ifInOctets.2 = Counter32: 0
IF-MIB::ifInOctets.3 = Counter32: 0
IF-MIB::ifInOctets.4 = Counter32: 1433448428

(the answers don't have to be in the same order as the query, I have
just formatted them that way for the example to make it clearer).

> It seems that the loop surrounding mps_getbulkreq() in snmpe.c is breaking
> the return of multiple OIDs but I can't find where exactly lies the bug.
>
> Can anyone help ?

One bug is that there's no support for non-repeaters yet;
msg->sm_nonrepeaters is filled in correctly from the request but
it isn't handled at all.

The getBulk request is processed within the outer loop in
snmpe_parsevarbinds(). There is one run of the inner loop for each
requested variable in the request which calls mps_getbulkreq() each
time.

I think something like the diff below (*NOT FOR COMMIT*) might be
part of the answer, there are problems though:

- "tooBig" error return when nonreps is set to anything other
than 0 (I can't even figure out where this is sent from..)

- still doesn't fix your problem where repetitions are broken
for all but the last requested variable. I've been looking at it and
trying things but haven't figured it out yet.

- not new, but the len counting in mps_getbulkreq only relates to
the individual call of that function, but in reality the response is
being built up from multiple calls to that function. so I think len
needs to be passed in as a pointer so that it can totalled up and
stop adding vars when the whole response packet is too full.

Anyway perhaps this gives some more ideas..

Index: snmpe.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v
retrieving revision 1.40
diff -u -p -r1.40 snmpe.c
--- snmpe.c     16 Jan 2015 00:05:13 -0000      1.40
+++ snmpe.c     7 Oct 2015 22:28:05 -0000
@@ -335,7 +335,7 @@ snmpe_parsevarbinds(struct snmp_message 
        struct snmp_stats       *stats = &env->sc_stats;
        char                     buf[BUFSIZ];
        struct ber_oid           o;
-       int                      ret = 0;
+       int                      bulk_oid = 0, ret = 0, nreps;
 
        msg->sm_errstr = "invalid varbind element";
 
@@ -408,8 +408,12 @@ snmpe_parsevarbinds(struct snmp_message 
                                        goto varfail;
 
                                case SNMP_C_GETBULKREQ:
+                                       nreps = bulk_oid <
+                                           msg->sm_nonrepeaters ?
+                                           1 : msg->sm_maxrepetitions;
+                                       bulk_oid++;
                                        ret = mps_getbulkreq(msg, &msg->sm_c,
-                                           &o, msg->sm_maxrepetitions);
+                                           &o, nreps);
                                        if (ret == 0 || ret == 1)
                                                break;
                                        msg->sm_error = SNMP_ERROR_NOSUCHNAME;



Reply via email to