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;