2 * snmpbulkwalk.c - send SNMPv2 Bulk requests to a network entity, walking a
6 /*********************************************************************
7 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
11 Permission to use, copy, modify, and distribute this software and its
12 documentation for any purpose and without fee is hereby granted,
13 provided that the above copyright notice appear in all copies and that
14 both that copyright notice and this permission notice appear in
15 supporting documentation, and that the name of CMU not be
16 used in advertising or publicity pertaining to distribution of the
17 software without specific, written prior permission.
19 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
20 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
21 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
22 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 **********************************************************************/
27 #include <net-snmp/net-snmp-config.h>
40 #include <sys/types.h>
42 #include <netinet/in.h>
44 #if TIME_WITH_SYS_TIME
46 # include <sys/timeb.h>
48 # include <sys/time.h>
53 # include <sys/time.h>
59 #include <sys/select.h>
70 #include <arpa/inet.h>
73 #include <net-snmp/net-snmp-includes.h>
75 #define NETSNMP_DS_WALK_INCLUDE_REQUESTED 1
76 #define NETSNMP_DS_WALK_PRINT_STATISTICS 2
77 #define NETSNMP_DS_WALK_DONT_CHECK_LEXICOGRAPHIC 3
79 oid objid_mib
[] = { 1, 3, 6, 1, 2, 1 };
81 int reps
= 10, non_reps
= 0;
86 fprintf(stderr
, "USAGE: snmpbulkwalk ");
87 snmp_parse_args_usage(stderr
);
88 fprintf(stderr
, " [OID]\n\n");
89 snmp_parse_args_descriptions(stderr
);
91 " -C APPOPTS\t\tSet various application specific behaviours:\n");
93 "\t\t\t c: do not check returned OIDs are increasing\n");
95 "\t\t\t i: include given OIDs in the search range\n");
96 fprintf(stderr
, "\t\t\t n<NUM>: set non-repeaters to <NUM>\n");
98 "\t\t\t p: print the number of variables found\n");
99 fprintf(stderr
, "\t\t\t r<NUM>: set max-repeaters to <NUM>\n");
103 snmp_get_and_print(netsnmp_session
* ss
, oid
* theoid
, size_t theoid_len
)
105 netsnmp_pdu
*pdu
, *response
;
106 netsnmp_variable_list
*vars
;
109 pdu
= snmp_pdu_create(SNMP_MSG_GET
);
110 snmp_add_null_var(pdu
, theoid
, theoid_len
);
112 status
= snmp_synch_response(ss
, pdu
, &response
);
113 if (status
== STAT_SUCCESS
&& response
->errstat
== SNMP_ERR_NOERROR
) {
114 for (vars
= response
->variables
; vars
; vars
= vars
->next_variable
) {
116 print_variable(vars
->name
, vars
->name_length
, vars
);
120 snmp_free_pdu(response
);
126 optProc(int argc
, char *const *argv
, int opt
)
135 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID
,
136 NETSNMP_DS_WALK_DONT_CHECK_LEXICOGRAPHIC
);
140 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID
,
141 NETSNMP_DS_WALK_INCLUDE_REQUESTED
);
146 if (*(optarg
- 1) == 'r') {
147 reps
= strtol(optarg
, &endptr
, 0);
149 non_reps
= strtol(optarg
, &endptr
, 0);
152 if (endptr
== optarg
) {
154 * No number given -- error.
160 if (isspace(*optarg
)) {
167 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID
,
168 NETSNMP_DS_WALK_PRINT_STATISTICS
);
172 fprintf(stderr
, "Unknown flag passed to -C: %c\n",
182 main(int argc
, char *argv
[])
184 netsnmp_session session
, *ss
;
185 netsnmp_pdu
*pdu
, *response
;
186 netsnmp_variable_list
*vars
;
188 oid name
[MAX_OID_LEN
];
190 oid root
[MAX_OID_LEN
];
198 netsnmp_ds_register_config(ASN_BOOLEAN
, "snmpwalk", "includeRequested",
199 NETSNMP_DS_APPLICATION_ID
,
200 NETSNMP_DS_WALK_INCLUDE_REQUESTED
);
201 netsnmp_ds_register_config(ASN_BOOLEAN
, "snmpwalk", "printStatistics",
202 NETSNMP_DS_APPLICATION_ID
,
203 NETSNMP_DS_WALK_PRINT_STATISTICS
);
204 netsnmp_ds_register_config(ASN_BOOLEAN
, "snmpwalk", "dontCheckOrdering",
205 NETSNMP_DS_APPLICATION_ID
,
206 NETSNMP_DS_WALK_DONT_CHECK_LEXICOGRAPHIC
);
209 * get the common command line arguments
211 switch (arg
= snmp_parse_args(argc
, argv
, &session
, "C:", optProc
)) {
222 * get the initial object and subtree
226 * specified on the command line
228 rootlen
= MAX_OID_LEN
;
229 if (snmp_parse_oid(argv
[arg
], root
, &rootlen
) == NULL
) {
230 snmp_perror(argv
[arg
]);
237 memmove(root
, objid_mib
, sizeof(objid_mib
));
238 rootlen
= sizeof(objid_mib
) / sizeof(oid
);
244 * open an SNMP session
246 ss
= snmp_open(&session
);
249 * diagnose snmp_open errors with the input netsnmp_session pointer
251 snmp_sess_perror("snmpbulkwalk", &session
);
257 * setup initial object name
259 memmove(name
, root
, rootlen
* sizeof(oid
));
260 name_length
= rootlen
;
264 check
= !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID
,
265 NETSNMP_DS_WALK_DONT_CHECK_LEXICOGRAPHIC
);
266 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID
,
267 NETSNMP_DS_WALK_INCLUDE_REQUESTED
)) {
268 snmp_get_and_print(ss
, root
, rootlen
);
273 * create PDU for GETBULK request and add object name to request
275 pdu
= snmp_pdu_create(SNMP_MSG_GETBULK
);
276 pdu
->non_repeaters
= non_reps
;
277 pdu
->max_repetitions
= reps
; /* fill the packet */
278 snmp_add_null_var(pdu
, name
, name_length
);
283 status
= snmp_synch_response(ss
, pdu
, &response
);
284 if (status
== STAT_SUCCESS
) {
285 if (response
->errstat
== SNMP_ERR_NOERROR
) {
287 * check resulting variables
289 for (vars
= response
->variables
; vars
;
290 vars
= vars
->next_variable
) {
291 if ((vars
->name_length
< rootlen
)
292 || (memcmp(root
, vars
->name
, rootlen
* sizeof(oid
))
295 * not part of this subtree
301 print_variable(vars
->name
, vars
->name_length
, vars
);
302 if ((vars
->type
!= SNMP_ENDOFMIBVIEW
) &&
303 (vars
->type
!= SNMP_NOSUCHOBJECT
) &&
304 (vars
->type
!= SNMP_NOSUCHINSTANCE
)) {
306 * not an exception value
309 && snmp_oid_compare(name
, name_length
,
311 vars
->name_length
) >= 0) {
312 fprintf(stderr
, "Error: OID not increasing: ");
313 fprint_objid(stderr
, name
, name_length
);
314 fprintf(stderr
, " >= ");
315 fprint_objid(stderr
, vars
->name
,
317 fprintf(stderr
, "\n");
322 * Check if last variable, and if so, save for next request.
324 if (vars
->next_variable
== NULL
) {
325 memmove(name
, vars
->name
,
326 vars
->name_length
* sizeof(oid
));
327 name_length
= vars
->name_length
;
331 * an exception value, so stop
338 * error in response, print it
341 if (response
->errstat
== SNMP_ERR_NOSUCHNAME
) {
342 printf("End of MIB\n");
344 fprintf(stderr
, "Error in packet.\nReason: %s\n",
345 snmp_errstring(response
->errstat
));
346 if (response
->errindex
!= 0) {
347 fprintf(stderr
, "Failed object: ");
348 for (count
= 1, vars
= response
->variables
;
349 vars
&& count
!= response
->errindex
;
350 vars
= vars
->next_variable
, count
++)
353 fprint_objid(stderr
, vars
->name
,
355 fprintf(stderr
, "\n");
360 } else if (status
== STAT_TIMEOUT
) {
361 fprintf(stderr
, "Timeout: No Response from %s\n",
365 } else { /* status == STAT_ERROR */
366 snmp_sess_perror("snmpbulkwalk", ss
);
371 snmp_free_pdu(response
);
374 if (numprinted
== 0 && status
== STAT_SUCCESS
) {
376 * no printed successful results, which may mean we were
377 * pointed at an only existing instance. Attempt a GET, just
380 snmp_get_and_print(ss
, root
, rootlen
);
384 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID
,
385 NETSNMP_DS_WALK_PRINT_STATISTICS
)) {
386 printf("Variables found: %d\n", numprinted
);