Re: Bulkget & snmpd
On Thu, Oct 08, 2015 at 08:39:40AM +0100, Stuart Henderson wrote: > > O. And now I find Gerhard Roth's post > > > > https://marc.info/?l=openbsd-tech&m=143375327425321&w=2 > > Oh! I missed this one. Thank you very much Stuart. Denis
Re: Bulkget & snmpd
On 2015/10/08 01:02, Stuart Henderson wrote: > > $ 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). > > O. And now I find Gerhard Roth's post > > https://marc.info/?l=openbsd-tech&m=143375327425321&w=2 > > In a nutshell: the mps_getbulkreq() calls subsequent to the first one > link the elements to the *first* element of the previous call, not the > last element. Gerhard's diff passes in the address of the last element > so it can be linked correctly. > > I'll look at it again tomorrow but that looks correct for the -Cr case, > nonreps and I think also len counting are still a problem but I'll look > at those again on top of Gerhard's diff. Gerhard's diff (repeated below) is correct for -Cr. Any OKs to commit it? $ snmpbulkget -Cr4 -v2c -c public 127.0.0.1 SNMPv2-MIB::sysDescr IP-MIB::ipForwarding IF-MIB::ifName IF-MIB::ifInOctets before: SNMPv2-MIB::sysDescr.0 = STRING: sym IP-MIB::ipForwarding.0 = INTEGER: 0 IF-MIB::ifName.1 = STRING: em0 IF-MIB::ifInOctets.1 = Counter32: 2305271272 IF-MIB::ifInOctets.2 = Counter32: 0 IF-MIB::ifInOctets.3 = Counter32: 0 IF-MIB::ifInOctets.4 = Counter32: 2091665909 after: SNMPv2-MIB::sysDescr.0 = STRING: sym SNMPv2-MIB::sysObjectID.0 = OID: OPENBSD-BASE-MIB::openBSDDefaultObjectID SNMPv2-MIB::sysUpTime.0 = Timeticks: (10069) 0:01:40.69 SNMPv2-MIB::sysContact.0 = STRING: r...@symphytum.spacehopper.org IP-MIB::ipForwarding.0 = INTEGER: 0 IP-MIB::ipDefaultTTL.0 = INTEGER: 64 IP-MIB::ipInReceives.0 = Counter32: 11634146 IP-MIB::ipInHdrErrors.0 = Counter32: 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: 2305182489 IF-MIB::ifInOctets.2 = Counter32: 0 IF-MIB::ifInOctets.3 = Counter32: 0 IF-MIB::ifInOctets.4 = Counter32: 2091496232 Index: mps.c === RCS file: /cvs/src/usr.sbin/snmpd/mps.c,v retrieving revision 1.21 diff -u -p -r1.21 mps.c --- mps.c 18 Jul 2015 16:54:43 - 1.21 +++ mps.c 8 Oct 2015 07:37:54 - @@ -300,7 +300,7 @@ fail: int mps_getbulkreq(struct snmp_message *msg, struct ber_element **root, -struct ber_oid *o, int max) +struct ber_element **end, struct ber_oid *o, int max) { struct ber_element *c, *d, *e; size_t len; @@ -308,14 +308,17 @@ mps_getbulkreq(struct snmp_message *msg, j = max; c = *root; + *end = NULL; for (d = NULL, len = 0; j > 0; j--) { e = ber_add_sequence(NULL); if (c == NULL) c = e; ret = mps_getnextreq(msg, e, o); - if (ret == 1) + if (ret == 1) { + *root = c; return (1); + } if (ret == -1) { ber_free_elements(e); if (d == NULL) @@ -330,6 +333,7 @@ mps_getbulkreq(struct snmp_message *msg, if (d != NULL) ber_link_elements(d, e); d = e; + *end = d; } *root = c; Index: snmpd.h === RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v retrieving revision 1.61 diff -u -p -r1.61 snmpd.h --- snmpd.h 5 Oct 2015 15:29:14 - 1.61 +++ snmpd.h 8 Oct 2015 07:37:54 - @@ -397,6 +397,7 @@ struct snmp_message { struct ber_element *sm_c; struct ber_element *sm_next; struct ber_element *sm_last; + struct ber_element *sm_end; u_int8_t sm_data[READ_BUF_SIZE]; size_t sm_datalen; @@ -639,7 +640,7 @@ int mps_getreq(struct snmp_message *, int mps_getnextreq(struct snmp_message *, struct ber_element *, struct ber_oid *); int mps_getbulkreq(struct snmp_message *, struct ber_element **, - struct ber_oid *, int); + struct ber_element **, struct ber_oid *, int); int mps_setreq(struct snmp_message *, struct ber_element *, struct ber_oid *); int mps_set(struct ber_oid *, void *, long long); Index: snmpe.c ===
Re: Bulkget & snmpd
On 2015/10/07 23:41, Stuart Henderson wrote: > Moving post from misc@. > > On 2015-10-07, Denis Fondras 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). O. And now I find Gerhard Roth's post https://marc.info/?l=openbsd-tech&m=143375327425321&w=2 In a nutshell: the mps_getbulkreq() calls subsequent to the first one link the elements to the *first* element of the previous call, not the last element. Gerhard's diff passes in the address of the last element so it can be linked correctly. I'll look at it again tomorrow but that looks correct for the -Cr case, nonreps and I think also len counting are still a problem but I'll look at those again on top of Gerhard's diff.
Re: Bulkget & snmpd
Moving post from misc@. On 2015-10-07, Denis Fondras 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 - 1.40 +++ snmpe.c 7 Oct 2015 22:28:05 - @@ -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 ==