Re: snmpctl walk don't show neighbours
Disregard for now. I found an infinite recursion. On 12/11/18 2:05 PM, Martijn van Duren wrote: > 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 - 1.18 > +++ snmpclient.c 11 Dec 2018 13:02:06 - > @@ -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_root_oid, >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_root_oid, >sc_oid) != 2 || > + bercmp = ber_oid_cmp(>sc_root_oid, >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) { >
Re: snmpctl walk don't show neighbours
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.c25 Nov 2018 14:58:28 - 1.18 +++ snmpclient.c11 Dec 2018 13:02:06 - @@ -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_root_oid, >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_root_oid, >sc_oid) != 2 || + bercmp = ber_oid_cmp(>sc_root_oid, >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) {
snmpctl walk don't show neighbours
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.c25 Nov 2018 14:58:28 - 1.18 +++ snmpclient.c11 Dec 2018 12:05:46 - @@ -56,7 +56,6 @@ struct snmpc { int sc_retry_max; const char *sc_community; int sc_version; - int sc_nresp; }; #defineSNMPC_RETRY_MAX 3 @@ -180,8 +179,6 @@ snmpc_run(struct snmpc *sc, enum actions if (sc->sc_oid.bo_n > 2) sc->sc_root_len = sc->sc_oid.bo_n - 1; - sc->sc_nresp = 0; - if (action == GET) snmpc_request(sc, SNMP_C_GETREQ); else if (action == BULKWALK) @@ -235,7 +232,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,10 +247,10 @@ 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_root_oid, >sc_oid) != 2 || + bercmp = ber_oid_cmp(>sc_root_oid, >sc_oid); + if ((bercmp != 0 && bercmp != 2) || e->be_class == BER_CLASS_CONTEXT || - e->be_type == BER_TYPE_NULL)) { + e->be_type == BER_TYPE_NULL) { ret = 1; break; } @@ -271,8 +268,6 @@ snmpc_response(struct snmpc *sc) } bcopy(>sc_oid, >sc_last_oid, sizeof(sc->sc_last_oid)); } - - sc->sc_nresp++; ber_free_elements(resp); return (ret);