Re: snmpctl walk don't show neighbours

2018-12-12 Thread Martijn van Duren
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

2018-12-11 Thread Martijn van Duren
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

2018-12-11 Thread Martijn van Duren
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);