As requested by deraadt@, here's a diff that includes the leaf value
itself.
$ ./snmpctl snmp walk host oid 1.3.6.1.4.1.9.9.273.1.1.2.1.1
1.1=1
1.2=5
$ ./snmpctl snmp walk host oid 1.3.6.1.4.1.9.9.273.1.1.2.1.1.1
1=1
$
On 12/11/18 1:10 PM, Martijn van Duren wrote:
> So I got puzzled because of a behavioural difference between snmpwalk
> and snmpctl walk.
>
> snmp returns the next element after the requested element for a
> getNextRequest. So for a leaf-element this can be it's closest
> neighbour. e.g.
> $ make && snmpctl snmp walk host oid 1.3.6.1.4.1.9.9.273.1.1.2.1.1
> 1.1=1
> 1.2=5
> icinga2$ make && snmpctl snmp walk host oid 1.3.6.1.4.1.9.9.273.1.1.2.1.1.1
> 2=5
> icinga2$ make && snmpctl snmp walk host oid 1.3.6.1.4.1.9.9.273.1.1.2.1.1.2
> 1=0
>
> snmpwalk returns the requested leaf if no subelements can be found:
> $ snmpwalk -v2c -c public host 1.3.6.1.4.1.9.9.273.1.1.2.1.1.1
> SNMPv2-SMI::enterprises.9.9.273.1.1.2.1.1.1 = Gauge32: 1
> $ snmpwalk -v2c -c public host 1.3.6.1.4.1.9.9.273.1.1.2.1.1.2
> SNMPv2-SMI::enterprises.9.9.273.1.1.2.1.1.2 = Gauge32: 5
>
> The problem for snmpctl is that we always return the first match, even
> if even if it's not in our scope. The diff below removes that
> requirement and also makes sure we also match itself, so to keep
> "snmp get" working.
>
> Note that this diff doesn't include the value of the leaf itself, unlike
> snmpwalk, since that would require extra wiring and isn't exactly what's
> being asked. If people would like this it could probably be added.
>
> $ ./snmpctl snmp walk host oid 1.3.6.1.4.1.9.9.273.1.1.2.1.1.1
> $ ./snmpctl snmp get 10.17.11.27 oid 1.3.6.1.4.1.9.9.273.1.1.2.1.1.1
> 1=1
> $
>
> OK?
>
> martijn@
>
Index: snmpclient.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpctl/snmpclient.c,v
retrieving revision 1.18
diff -u -p -r1.18 snmpclient.c
--- snmpclient.c 25 Nov 2018 14:58:28 -0000 1.18
+++ snmpclient.c 11 Dec 2018 13:02:06 -0000
@@ -220,6 +220,11 @@ snmpc_request(struct snmpc *sc, unsigned
if ((ret = snmpc_response(sc)) != 0) {
if (ret == -1)
err(1, "response");
+ if (sc->sc_nresp == 0) {
+ bcopy(&sc->sc_root_oid, &sc->sc_oid,
+ sizeof(sc->sc_oid));
+ snmpc_request(sc, SNMP_C_GETREQ);
+ }
return;
}
@@ -235,7 +240,7 @@ snmpc_response(struct snmpc *sc)
char buf[BUFSIZ];
struct ber_element *resp = NULL, *s, *e;
char *value = NULL, *p;
- int ret = 0;
+ int ret = 0, bercmp;
/* Receive response */
if (snmpc_recvresp(sc->sc_fd, sc->sc_version,
@@ -250,12 +255,12 @@ snmpc_response(struct snmpc *sc)
goto fail;
/* Break if the returned OID is not a child of the root. */
- if (sc->sc_nresp &&
- (ber_oid_cmp(&sc->sc_root_oid, &sc->sc_oid) != 2 ||
+ bercmp = ber_oid_cmp(&sc->sc_root_oid, &sc->sc_oid);
+ if ((bercmp != 0 && bercmp != 2) ||
e->be_class == BER_CLASS_CONTEXT ||
- e->be_type == BER_TYPE_NULL)) {
- ret = 1;
- break;
+ e->be_type == BER_TYPE_NULL) {
+ ber_free_elements(resp);
+ return 1;
}
if ((value = smi_print_element(e)) != NULL) {