Implement an option to execute SNMP walks using GETBULK requests in bsnmpwalk(1)

retrieving multiple values with a Single PDU.

Reviewed by:	philip@
Tested by:	tsanand129 (at) gmail (dot) com
This commit is contained in:
Shteryana Shopova 2012-01-10 15:29:03 +00:00
parent 756e2ef0ff
commit b9288caaf6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=229933
4 changed files with 62 additions and 26 deletions

View File

@ -33,7 +33,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd September 17, 2007
.Dd January 10, 2012
.Dt BSNMPGET 1
.Os
.Sh NAME
@ -112,7 +112,7 @@ objects whose values will be retrived, waits for a response and prints it if
received successfully.
.Pp
.Nm Bsnmpwalk
queries an agent with SMNP GetNextRequest packets,
queries an agent with ether SMNP GetNextRequest or GetBulkRequest packets,
asking for values of OID instances that are a part of the object subtree
rooted at the provided OIDs.
.Pp
@ -220,7 +220,7 @@ The path of the posix local (unix domain) socket if local
transport is used.
.It Fl M Ar max-repetitions
The value for the max-repetitions field in a GetBulk PDU.
Default is 1.
Default is 10.
.It Fl N Ar non-repeaters
The value for the non-repeaters field in a GetBulk PDU.
Default is 0.
@ -251,8 +251,17 @@ A binary localized privacy key to use when encypting/decrypting SNMPv3 PDU data.
By default plain text SNMPv3 PDUs are sent.
.It Fl p Ar [get|getnext|getbulk]
The PDU type to send by
.Nm bsmpget .
Default is get.
.Nm bsmpget
and
.Nm bsnmpwalk .
Default is get
for
.Nm bsmpget
and getnext for
.Nm bsnmpwalk .
Getbulk allows executing the so called SNMP "bulkwalks" allowing the values of
multiple columns to be retrived in a single PDU by
.Nm bsnmpwalk .
.It Fl r Ar retries
Number of resends of request packets before giving up if the agent does
not respond after the first try.

View File

@ -76,8 +76,9 @@ usage(void)
(program == BSNMPWALK) ? "[-dhnK]" :
(program == BSNMPSET) ? "[-adehnK]" :
"",
(program == BSNMPGET) ? " [-M max-repetitions] [-N non-repeaters]" : "",
(program == BSNMPGET) ? "[-p pdu] " : "",
(program == BSNMPGET || program == BSNMPWALK) ?
" [-M max-repetitions] [-N non-repeaters]" : "",
(program == BSNMPGET || program == BSNMPWALK) ? "[-p pdu] " : "",
(program == BSNMPGET) ? " OID [OID ...]" :
(program == BSNMPWALK || program == BSNMPSET) ? " [OID ...]" :
""
@ -150,7 +151,7 @@ snmptool_parse_options(struct snmp_toolinfo *snmptoolctx, int argc, char **argv)
switch (program) {
case BSNMPWALK:
opts = "dhnKA:b:C:I:i:l:o:P:r:s:t:U:v:";
opts = "dhnKA:b:C:I:i:l:M:N:o:P:p:r:s:t:U:v:";
break;
case BSNMPGET:
opts = "aDdehnKA:b:C:I:i:l:M:N:o:P:p:r:s:t:U:v:";
@ -398,7 +399,7 @@ snmptool_get(struct snmp_toolinfo *snmptoolctx)
}
if (snmp_parse_resp(&resp, &req) >= 0) {
snmp_output_resp(snmptoolctx, &resp);
snmp_output_resp(snmptoolctx, &resp, NULL);
break;
}
@ -460,8 +461,14 @@ snmptool_walk(struct snmp_toolinfo *snmptoolctx)
struct snmp_pdu req, resp;
struct asn_oid root; /* Keep the initial oid. */
int32_t outputs, rc;
uint32_t op;
snmp_pdu_create(&req, SNMP_PDU_GETNEXT);
if (GET_PDUTYPE(snmptoolctx) == SNMP_PDU_GETBULK)
op = SNMP_PDU_GETBULK;
else
op = SNMP_PDU_GETNEXT;
snmp_pdu_create(&req, op);
while ((rc = snmp_pdu_add_bindings(snmptoolctx, NULL,
snmptool_add_vbind, &req, 1)) > 0) {
@ -470,6 +477,10 @@ snmptool_walk(struct snmp_toolinfo *snmptoolctx)
memset(&root, 0, sizeof(struct asn_oid));
asn_append_oid(&root, &(req.bindings[0].var));
if (op == SNMP_PDU_GETBULK)
snmpget_fix_getbulk(&req, GET_MAXREP(snmptoolctx),
GET_NONREP(snmptoolctx));
outputs = 0;
while (snmp_dialog(&req, &resp) >= 0) {
if ((snmp_parse_resp(&resp, &req)) < 0) {
@ -479,21 +490,24 @@ snmptool_walk(struct snmp_toolinfo *snmptoolctx)
break;
}
if (!(asn_is_suboid(&root, &(resp.bindings[0].var)))) {
snmp_pdu_free(&resp);
break;
}
if (snmp_output_resp(snmptoolctx, &resp)!= 0) {
rc = snmp_output_resp(snmptoolctx, &resp, &root);
if (rc < 0) {
snmp_pdu_free(&resp);
outputs = -1;
break;
}
outputs++;
outputs += rc;
snmp_pdu_free(&resp);
snmpwalk_nextpdu_create(SNMP_PDU_GETNEXT,
&(resp.bindings[0].var), &req);
if (rc < resp.nbindings)
break;
snmpwalk_nextpdu_create(op,
&(resp.bindings[resp.nbindings - 1].var), &req);
if (op == SNMP_PDU_GETBULK)
snmpget_fix_getbulk(&req, GET_MAXREP(snmptoolctx),
GET_NONREP(snmptoolctx));
}
/* Just in case our root was a leaf. */
@ -503,7 +517,7 @@ snmptool_walk(struct snmp_toolinfo *snmptoolctx)
if (snmp_parse_resp(&resp,&req) < 0)
snmp_output_err_resp(snmptoolctx, &resp);
else
snmp_output_resp(snmptoolctx, &(resp));
snmp_output_resp(snmptoolctx, &(resp), NULL);
snmp_pdu_free(&resp);
} else
@ -515,7 +529,7 @@ snmptool_walk(struct snmp_toolinfo *snmptoolctx)
break;
}
snmp_pdu_create(&req, SNMP_PDU_GETNEXT);
snmp_pdu_create(&req, op);
}
if (rc == 0)
@ -1076,7 +1090,7 @@ snmptool_set(struct snmp_toolinfo *snmptoolctx)
if (snmp_pdu_check(&req, &resp) > 0) {
if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET)
snmp_output_resp(snmptoolctx, &resp);
snmp_output_resp(snmptoolctx, &resp, NULL);
break;
}

View File

@ -132,6 +132,7 @@ snmptool_init(struct snmp_toolinfo *snmptoolctx)
snmptoolctx->flags = SNMP_PDU_GET; /* XXX */
SLIST_INIT(&snmptoolctx->filelist);
snmp_client_init(&snmp_client);
SET_MAXREP(snmptoolctx, SNMP_MAX_REPETITIONS);
if (add_filename(snmptoolctx, bsnmpd_defs, &IsoOrgDod_OID, 0) < 0)
warnx("Error adding file %s to list", bsnmpd_defs);
@ -2039,14 +2040,20 @@ snmp_output_err_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu)
}
int32_t
snmp_output_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu)
snmp_output_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu,
struct asn_oid *root)
{
int32_t error;
char p[ASN_OIDSTRLEN];
uint32_t i;
struct snmp_object object;
for (i = 0, error = 0; i < pdu->nbindings; i++) {
i = error = 0;
while (i < pdu->nbindings) {
if (root != NULL && !(asn_is_suboid(root,
&(pdu->bindings[i].var))))
break;
if (GET_OUTPUT(snmptoolctx) != OUTPUT_QUIET) {
if (!ISSET_NUMERIC(snmptoolctx) &&
(snmp_fill_object(snmptoolctx, &object,
@ -2058,9 +2065,13 @@ snmp_output_resp(struct snmp_toolinfo *snmptoolctx, struct snmp_pdu *pdu)
}
}
error |= snmp_output_numval(snmptoolctx, &(pdu->bindings[i]), object.info);
i++;
}
return (error);
if (error)
return (-1);
return (i);
}
void

View File

@ -47,6 +47,8 @@
#define SNMP_DEFS_DIR "/usr/share/snmp/defs/"
#define SNMP_DEFAULT_LOCAL "/var/run/snmpd.sock"
#define SNMP_MAX_REPETITIONS 10
enum snmp_access {
SNMP_ACCESS_NONE = 0,
SNMP_ACCESS_GET,
@ -323,7 +325,7 @@ int32_t snmp_parse_resp(struct snmp_pdu *, struct snmp_pdu *);
int32_t snmp_output_numval(struct snmp_toolinfo *, struct snmp_value *,
struct snmp_oid2str *);
void snmp_output_val(struct snmp_value *);
int32_t snmp_output_resp(struct snmp_toolinfo *, struct snmp_pdu *);
int32_t snmp_output_resp(struct snmp_toolinfo *, struct snmp_pdu *, struct asn_oid *);
void snmp_output_err_resp(struct snmp_toolinfo *, struct snmp_pdu *);
void snmp_output_engine(void);
void snmp_output_keys(void);