bedbe7fb8a9f9e00cdad1dcff3a05ddae42725e1
[bcm963xx.git] / userapps / opensource / net-snmp / apps / snmpbulkwalk.c
1 /*
2  * snmpbulkwalk.c - send SNMPv2 Bulk requests to a network entity, walking a
3  * subtree.
4  *
5  */
6 /*********************************************************************
7         Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
8
9                       All Rights Reserved
10
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.  
18
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>
28
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
72
73 #include <net-snmp/net-snmp-includes.h>
74
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
78
79 oid             objid_mib[] = { 1, 3, 6, 1, 2, 1 };
80 int             numprinted = 0;
81 int             reps = 10, non_reps = 0;
82
83 void
84 usage(void)
85 {
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");
100 }
101
102 static void
103 snmp_get_and_print(netsnmp_session * ss, oid * theoid, size_t theoid_len)
104 {
105     netsnmp_pdu    *pdu, *response;
106     netsnmp_variable_list *vars;
107     int             status;
108
109     pdu = snmp_pdu_create(SNMP_MSG_GET);
110     snmp_add_null_var(pdu, theoid, theoid_len);
111
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);
117         }
118     }
119     if (response) {
120         snmp_free_pdu(response);
121     }
122 }
123
124 static
125     void
126 optProc(int argc, char *const *argv, int opt)
127 {
128     char           *endptr = NULL;
129
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;
138
139             case 'i':
140                 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
141                                           NETSNMP_DS_WALK_INCLUDE_REQUESTED);
142                 break;
143
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);
150                 }
151
152                 if (endptr == optarg) {
153                     /*
154                      * No number given -- error.  
155                      */
156                     usage();
157                     exit(1);
158                 } else {
159                     optarg = endptr;
160                     if (isspace(*optarg)) {
161                         return;
162                     }
163                 }
164                 break;
165
166             case 'p':
167                 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
168                                           NETSNMP_DS_WALK_PRINT_STATISTICS);
169                 break;
170
171             default:
172                 fprintf(stderr, "Unknown flag passed to -C: %c\n",
173                         optarg[-1]);
174                 exit(1);
175             }
176         }
177         break;
178     }
179 }
180
181 int
182 main(int argc, char *argv[])
183 {
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;
197
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);
207
208     /*
209      * get the common command line arguments 
210      */
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;
219     }
220
221     /*
222      * get the initial object and subtree 
223      */
224     if (arg < argc) {
225         /*
226          * specified on the command line 
227          */
228         rootlen = MAX_OID_LEN;
229         if (snmp_parse_oid(argv[arg], root, &rootlen) == NULL) {
230             snmp_perror(argv[arg]);
231             exit(1);
232         }
233     } else {
234         /*
235          * use default value 
236          */
237         memmove(root, objid_mib, sizeof(objid_mib));
238         rootlen = sizeof(objid_mib) / sizeof(oid);
239     }
240
241     SOCK_STARTUP;
242
243     /*
244      * open an SNMP session 
245      */
246     ss = snmp_open(&session);
247     if (ss == NULL) {
248         /*
249          * diagnose snmp_open errors with the input netsnmp_session pointer 
250          */
251         snmp_sess_perror("snmpbulkwalk", &session);
252         SOCK_CLEANUP;
253         exit(1);
254     }
255
256     /*
257      * setup initial object name 
258      */
259     memmove(name, root, rootlen * sizeof(oid));
260     name_length = rootlen;
261
262     running = 1;
263
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);
269     }
270
271     while (running) {
272         /*
273          * create PDU for GETBULK request and add object name to request 
274          */
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);
279
280         /*
281          * do the request 
282          */
283         status = snmp_synch_response(ss, pdu, &response);
284         if (status == STAT_SUCCESS) {
285             if (response->errstat == SNMP_ERR_NOERROR) {
286                 /*
287                  * check resulting variables 
288                  */
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)) {
294                         /*
295                          * not part of this subtree 
296                          */
297                         running = 0;
298                         continue;
299                     }
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)) {
305                         /*
306                          * not an exception value 
307                          */
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;
320                         }
321                         /*
322                          * Check if last variable, and if so, save for next request.  
323                          */
324                         if (vars->next_variable == NULL) {
325                             memmove(name, vars->name,
326                                     vars->name_length * sizeof(oid));
327                             name_length = vars->name_length;
328                         }
329                     } else {
330                         /*
331                          * an exception value, so stop 
332                          */
333                         running = 0;
334                     }
335                 }
336             } else {
337                 /*
338                  * error in response, print it 
339                  */
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");
356                     }
357                     exitval = 2;
358                 }
359             }
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;
369         }
370         if (response)
371             snmp_free_pdu(response);
372     }
373
374     if (numprinted == 0 && status == STAT_SUCCESS) {
375         /*
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. 
379          */
380         snmp_get_and_print(ss, root, rootlen);
381     }
382     snmp_close(ss);
383
384     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
385                                NETSNMP_DS_WALK_PRINT_STATISTICS)) {
386         printf("Variables found: %d\n", numprinted);
387     }
388
389     SOCK_CLEANUP;
390     return exitval;
391 }