added files
[bcm963xx.git] / userapps / opensource / net-snmp / apps / snmpwalk.c
1 /*
2  * snmpwalk.c - send snmp GETNEXT 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 #if HAVE_WINSOCK_H
63 #include <winsock.h>
64 #endif
65 #if HAVE_NETDB_H
66 #include <netdb.h>
67 #endif
68 #if HAVE_ARPA_INET_H
69 #include <arpa/inet.h>
70 #endif
71
72 #include <net-snmp/net-snmp-includes.h>
73
74 #define NETSNMP_DS_WALK_INCLUDE_REQUESTED       1
75 #define NETSNMP_DS_WALK_PRINT_STATISTICS        2
76 #define NETSNMP_DS_WALK_DONT_CHECK_LEXICOGRAPHIC        3
77
78 oid             objid_mib[] = { 1, 3, 6, 1, 2, 1 };
79 int             numprinted = 0;
80
81 void
82 usage(void)
83 {
84     fprintf(stderr, "USAGE: snmpwalk ");
85     snmp_parse_args_usage(stderr);
86     fprintf(stderr, " [OID]\n\n");
87     snmp_parse_args_descriptions(stderr);
88     fprintf(stderr,
89             "  -C APPOPTS\t\tSet various application specific behaviours:\n");
90     fprintf(stderr, "\t\t\t  p:  print the number of variables found\n");
91     fprintf(stderr, "\t\t\t  i:  include given OID in the search range\n");
92     fprintf(stderr,
93             "\t\t\t  c:  do not check returned OIDs are increasing\n");
94 }
95
96 void
97 snmp_get_and_print(netsnmp_session * ss, oid * theoid, size_t theoid_len)
98 {
99     netsnmp_pdu    *pdu, *response;
100     netsnmp_variable_list *vars;
101     int             status;
102
103     pdu = snmp_pdu_create(SNMP_MSG_GET);
104     snmp_add_null_var(pdu, theoid, theoid_len);
105
106     status = snmp_synch_response(ss, pdu, &response);
107     if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
108         for (vars = response->variables; vars; vars = vars->next_variable) {
109             numprinted++;
110             print_variable(vars->name, vars->name_length, vars);
111         }
112     }
113     if (response) {
114         snmp_free_pdu(response);
115     }
116 }
117
118 static void
119 optProc(int argc, char *const *argv, int opt)
120 {
121     switch (opt) {
122     case 'C':
123         while (*optarg) {
124             switch (*optarg++) {
125             case 'i':
126                 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
127                                           NETSNMP_DS_WALK_INCLUDE_REQUESTED);
128                 break;
129
130             case 'p':
131                 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
132                                           NETSNMP_DS_WALK_PRINT_STATISTICS);
133                 break;
134
135             case 'c':
136                 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
137                                     NETSNMP_DS_WALK_DONT_CHECK_LEXICOGRAPHIC);
138                 break;
139             default:
140                 fprintf(stderr, "Unknown flag passed to -C: %c\n",
141                         optarg[-1]);
142                 exit(1);
143             }
144         }
145         break;
146     }
147 }
148
149 int
150 main(int argc, char *argv[])
151 {
152     netsnmp_session session, *ss;
153     netsnmp_pdu    *pdu, *response;
154     netsnmp_variable_list *vars;
155     int             arg;
156     oid             name[MAX_OID_LEN];
157     size_t          name_length;
158     oid             root[MAX_OID_LEN];
159     size_t          rootlen;
160     int             count;
161     int             running;
162     int             status;
163     int             check;
164     int             exitval = 0;
165
166     netsnmp_ds_register_config(ASN_BOOLEAN, "snmpwalk", "includeRequested",
167                                NETSNMP_DS_APPLICATION_ID, 
168                                NETSNMP_DS_WALK_INCLUDE_REQUESTED);
169
170     netsnmp_ds_register_config(ASN_BOOLEAN, "snmpwalk", "printStatistics",
171                                NETSNMP_DS_APPLICATION_ID, 
172                                NETSNMP_DS_WALK_PRINT_STATISTICS);
173
174     netsnmp_ds_register_config(ASN_BOOLEAN, "snmpwalk", "dontCheckOrdering",
175                                NETSNMP_DS_APPLICATION_ID,
176                                NETSNMP_DS_WALK_DONT_CHECK_LEXICOGRAPHIC);
177
178     /*
179      * get the common command line arguments 
180      */
181     switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) {
182     case -2:
183         exit(0);
184     case -1:
185         usage();
186         exit(1);
187     default:
188         break;
189     }
190
191     /*
192      * get the initial object and subtree 
193      */
194     if (arg < argc) {
195         /*
196          * specified on the command line 
197          */
198         rootlen = MAX_OID_LEN;
199         if (snmp_parse_oid(argv[arg], root, &rootlen) == NULL) {
200             snmp_perror(argv[arg]);
201             exit(1);
202         }
203     } else {
204         /*
205          * use default value 
206          */
207         memmove(root, objid_mib, sizeof(objid_mib));
208         rootlen = sizeof(objid_mib) / sizeof(oid);
209     }
210
211     SOCK_STARTUP;
212
213     /*
214      * open an SNMP session 
215      */
216     ss = snmp_open(&session);
217     if (ss == NULL) {
218         /*
219          * diagnose snmp_open errors with the input netsnmp_session pointer 
220          */
221         snmp_sess_perror("snmpwalk", &session);
222         SOCK_CLEANUP;
223         exit(1);
224     }
225
226     /*
227      * get first object to start walk 
228      */
229     memmove(name, root, rootlen * sizeof(oid));
230     name_length = rootlen;
231
232     running = 1;
233
234     check =
235         !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
236                         NETSNMP_DS_WALK_DONT_CHECK_LEXICOGRAPHIC);
237     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_WALK_INCLUDE_REQUESTED)) {
238         snmp_get_and_print(ss, root, rootlen);
239     }
240
241     while (running) {
242         /*
243          * create PDU for GETNEXT request and add object name to request 
244          */
245         pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
246         snmp_add_null_var(pdu, name, name_length);
247
248         /*
249          * do the request 
250          */
251         status = snmp_synch_response(ss, pdu, &response);
252         if (status == STAT_SUCCESS) {
253             if (response->errstat == SNMP_ERR_NOERROR) {
254                 /*
255                  * check resulting variables 
256                  */
257                 for (vars = response->variables; vars;
258                      vars = vars->next_variable) {
259                     if ((vars->name_length < rootlen)
260                         || (memcmp(root, vars->name, rootlen * sizeof(oid))
261                             != 0)) {
262                         /*
263                          * not part of this subtree 
264                          */
265                         running = 0;
266                         continue;
267                     }
268                     numprinted++;
269                     print_variable(vars->name, vars->name_length, vars);
270                     if ((vars->type != SNMP_ENDOFMIBVIEW) &&
271                         (vars->type != SNMP_NOSUCHOBJECT) &&
272                         (vars->type != SNMP_NOSUCHINSTANCE)) {
273                         /*
274                          * not an exception value 
275                          */
276                         if (check
277                             && snmp_oid_compare(name, name_length,
278                                                 vars->name,
279                                                 vars->name_length) >= 0) {
280                             fprintf(stderr, "Error: OID not increasing: ");
281                             fprint_objid(stderr, name, name_length);
282                             fprintf(stderr, " >= ");
283                             fprint_objid(stderr, vars->name,
284                                          vars->name_length);
285                             fprintf(stderr, "\n");
286                             running = 0;
287                             exitval = 1;
288                         }
289                         memmove((char *) name, (char *) vars->name,
290                                 vars->name_length * sizeof(oid));
291                         name_length = vars->name_length;
292                     } else
293                         /*
294                          * an exception value, so stop 
295                          */
296                         running = 0;
297                 }
298             } else {
299                 /*
300                  * error in response, print it 
301                  */
302                 running = 0;
303                 if (response->errstat == SNMP_ERR_NOSUCHNAME) {
304                     printf("End of MIB\n");
305                 } else {
306                     fprintf(stderr, "Error in packet.\nReason: %s\n",
307                             snmp_errstring(response->errstat));
308                     if (response->errindex != 0) {
309                         fprintf(stderr, "Failed object: ");
310                         for (count = 1, vars = response->variables;
311                              vars && count != response->errindex;
312                              vars = vars->next_variable, count++)
313                             /*EMPTY*/;
314                         if (vars)
315                             fprint_objid(stderr, vars->name,
316                                          vars->name_length);
317                         fprintf(stderr, "\n");
318                     }
319                     exitval = 2;
320                 }
321             }
322         } else if (status == STAT_TIMEOUT) {
323             fprintf(stderr, "Timeout: No Response from %s\n",
324                     session.peername);
325             running = 0;
326             exitval = 1;
327         } else {                /* status == STAT_ERROR */
328             snmp_sess_perror("snmpwalk", ss);
329             running = 0;
330             exitval = 1;
331         }
332         if (response)
333             snmp_free_pdu(response);
334     }
335
336     if (numprinted == 0 && status == STAT_SUCCESS) {
337         /*
338          * no printed successful results, which may mean we were
339          * pointed at an only existing instance.  Attempt a GET, just
340          * for get measure. 
341          */
342         snmp_get_and_print(ss, root, rootlen);
343     }
344     snmp_close(ss);
345
346     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_WALK_PRINT_STATISTICS)) {
347         printf("Variables found: %d\n", numprinted);
348     }
349
350     SOCK_CLEANUP;
351     return exitval;
352 }