NGINX: Upstream update to version 1.4.4
[tomato.git] / release / src / router / snmp / apps / snmpbulkwalk.c
blobbedbe7fb8a9f9e00cdad1dcff3a05ddae42725e1
1 /*
2 * snmpbulkwalk.c - send SNMPv2 Bulk requests to a network entity, walking a
3 * subtree.
5 */
6 /*********************************************************************
7 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
9 All Rights Reserved
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
25 SOFTWARE.
26 **********************************************************************/
27 #include <net-snmp/net-snmp-config.h>
29 #if HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #if HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #if HAVE_STRING_H
36 #include <string.h>
37 #else
38 #include <strings.h>
39 #endif
40 #include <sys/types.h>
41 #if HAVE_NETINET_IN_H
42 #include <netinet/in.h>
43 #endif
44 #if TIME_WITH_SYS_TIME
45 # ifdef WIN32
46 # include <sys/timeb.h>
47 # else
48 # include <sys/time.h>
49 # endif
50 # include <time.h>
51 #else
52 # if HAVE_SYS_TIME_H
53 # include <sys/time.h>
54 # else
55 # include <time.h>
56 # endif
57 #endif
58 #if HAVE_SYS_SELECT_H
59 #include <sys/select.h>
60 #endif
61 #include <stdio.h>
62 #include <ctype.h>
63 #if HAVE_WINSOCK_H
64 #include <winsock.h>
65 #endif
66 #if HAVE_NETDB_H
67 #include <netdb.h>
68 #endif
69 #if HAVE_ARPA_INET_H
70 #include <arpa/inet.h>
71 #endif
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 };
80 int numprinted = 0;
81 int reps = 10, non_reps = 0;
83 void
84 usage(void)
86 fprintf(stderr, "USAGE: snmpbulkwalk ");
87 snmp_parse_args_usage(stderr);
88 fprintf(stderr, " [OID]\n\n");
89 snmp_parse_args_descriptions(stderr);
90 fprintf(stderr,
91 " -C APPOPTS\t\tSet various application specific behaviours:\n");
92 fprintf(stderr,
93 "\t\t\t c: do not check returned OIDs are increasing\n");
94 fprintf(stderr,
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");
97 fprintf(stderr,
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");
102 static void
103 snmp_get_and_print(netsnmp_session * ss, oid * theoid, size_t theoid_len)
105 netsnmp_pdu *pdu, *response;
106 netsnmp_variable_list *vars;
107 int status;
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) {
115 numprinted++;
116 print_variable(vars->name, vars->name_length, vars);
119 if (response) {
120 snmp_free_pdu(response);
124 static
125 void
126 optProc(int argc, char *const *argv, int opt)
128 char *endptr = NULL;
130 switch (opt) {
131 case 'C':
132 while (*optarg) {
133 switch (*optarg++) {
134 case 'c':
135 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
136 NETSNMP_DS_WALK_DONT_CHECK_LEXICOGRAPHIC);
137 break;
139 case 'i':
140 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
141 NETSNMP_DS_WALK_INCLUDE_REQUESTED);
142 break;
144 case 'n':
145 case 'r':
146 if (*(optarg - 1) == 'r') {
147 reps = strtol(optarg, &endptr, 0);
148 } else {
149 non_reps = strtol(optarg, &endptr, 0);
152 if (endptr == optarg) {
154 * No number given -- error.
156 usage();
157 exit(1);
158 } else {
159 optarg = endptr;
160 if (isspace(*optarg)) {
161 return;
164 break;
166 case 'p':
167 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
168 NETSNMP_DS_WALK_PRINT_STATISTICS);
169 break;
171 default:
172 fprintf(stderr, "Unknown flag passed to -C: %c\n",
173 optarg[-1]);
174 exit(1);
177 break;
182 main(int argc, char *argv[])
184 netsnmp_session session, *ss;
185 netsnmp_pdu *pdu, *response;
186 netsnmp_variable_list *vars;
187 int arg;
188 oid name[MAX_OID_LEN];
189 size_t name_length;
190 oid root[MAX_OID_LEN];
191 size_t rootlen;
192 int count;
193 int running;
194 int status;
195 int check;
196 int exitval = 0;
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)) {
212 case -2:
213 exit(0);
214 case -1:
215 usage();
216 exit(1);
217 default:
218 break;
222 * get the initial object and subtree
224 if (arg < argc) {
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]);
231 exit(1);
233 } else {
235 * use default value
237 memmove(root, objid_mib, sizeof(objid_mib));
238 rootlen = sizeof(objid_mib) / sizeof(oid);
241 SOCK_STARTUP;
244 * open an SNMP session
246 ss = snmp_open(&session);
247 if (ss == NULL) {
249 * diagnose snmp_open errors with the input netsnmp_session pointer
251 snmp_sess_perror("snmpbulkwalk", &session);
252 SOCK_CLEANUP;
253 exit(1);
257 * setup initial object name
259 memmove(name, root, rootlen * sizeof(oid));
260 name_length = rootlen;
262 running = 1;
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);
271 while (running) {
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);
281 * do the request
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))
293 != 0)) {
295 * not part of this subtree
297 running = 0;
298 continue;
300 numprinted++;
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
308 if (check
309 && snmp_oid_compare(name, name_length,
310 vars->name,
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,
316 vars->name_length);
317 fprintf(stderr, "\n");
318 running = 0;
319 exitval = 1;
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;
329 } else {
331 * an exception value, so stop
333 running = 0;
336 } else {
338 * error in response, print it
340 running = 0;
341 if (response->errstat == SNMP_ERR_NOSUCHNAME) {
342 printf("End of MIB\n");
343 } else {
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++)
351 /*EMPTY*/;
352 if (vars)
353 fprint_objid(stderr, vars->name,
354 vars->name_length);
355 fprintf(stderr, "\n");
357 exitval = 2;
360 } else if (status == STAT_TIMEOUT) {
361 fprintf(stderr, "Timeout: No Response from %s\n",
362 session.peername);
363 running = 0;
364 exitval = 1;
365 } else { /* status == STAT_ERROR */
366 snmp_sess_perror("snmpbulkwalk", ss);
367 running = 0;
368 exitval = 1;
370 if (response)
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
378 * for get measure.
380 snmp_get_and_print(ss, root, rootlen);
382 snmp_close(ss);
384 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
385 NETSNMP_DS_WALK_PRINT_STATISTICS)) {
386 printf("Variables found: %d\n", numprinted);
389 SOCK_CLEANUP;
390 return exitval;