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) {

Reply via email to