1 /*
2  * snmptranslate.c - report or translate info about oid from mibs
3  *
4  * Update: 1998-07-17 <jhy@gsu.edu>
5  * Added support for dumping alternate oid reports (-t and -T options).
6  * Added more detailed (useful?) usage info.
7  */
8 /************************************************************************
9 	Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
10 
11                       All Rights Reserved
12 
13 Permission to use, copy, modify, and distribute this software and its
14 documentation for any purpose and without fee is hereby granted,
15 provided that the above copyright notice appear in all copies and that
16 both that copyright notice and this permission notice appear in
17 supporting documentation, and that the name of CMU not be
18 used in advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20 
21 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
22 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
23 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
24 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27 SOFTWARE.
28 ******************************************************************/
29 
30 
31 #include <net-snmp/net-snmp-config.h>
32 
33 #if HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
36 #if HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #if HAVE_STRING_H
40 #include <string.h>
41 #else
42 #include <strings.h>
43 #endif
44 #include <sys/types.h>
45 #if HAVE_SYS_SELECT_H
46 #include <sys/select.h>
47 #endif
48 #if HAVE_NETINET_IN_H
49 #include <netinet/in.h>
50 #endif
51 #include <stdio.h>
52 #include <ctype.h>
53 #include <net-snmp/utilities.h>
54 #include <net-snmp/config_api.h>
55 #include <net-snmp/output_api.h>
56 #include <net-snmp/mib_api.h>
57 
58 int             show_all_matched_objects(FILE *, const char *, oid *,
59                                          size_t *, int, int);
60 
61 void
usage(void)62 usage(void)
63 {
64     fprintf(stderr, "USAGE: snmptranslate [OPTIONS] OID [OID]...\n\n");
65     fprintf(stderr, "  Version:  %s\n", netsnmp_get_version());
66     fprintf(stderr, "  Web:      http://www.net-snmp.org/\n");
67     fprintf(stderr,
68             "  Email:    net-snmp-coders@lists.sourceforge.net\n\nOPTIONS:\n");
69 
70     fprintf(stderr, "  -h\t\t\tdisplay this help message\n");
71     fprintf(stderr, "  -V\t\t\tdisplay package version number\n");
72     fprintf(stderr,
73             "  -m MIB[" ENV_SEPARATOR "...]\t\tload given list of MIBs (ALL loads everything)\n");
74     fprintf(stderr,
75             "  -M DIR[" ENV_SEPARATOR "...]\t\tlook in given list of directories for MIBs\n");
76     fprintf(stderr,
77             "  -D[TOKEN[,...]]\tturn on debugging output for the specified TOKENs\n\t\t\t   (ALL gives extremely verbose debugging output)\n");
78     fprintf(stderr, "  -w WIDTH\t\tset width of tree and detail output\n");
79     fprintf(stderr,
80             "  -T TRANSOPTS\t\tSet various options controlling report produced:\n");
81     fprintf(stderr,
82             "\t\t\t  B:  print all matching objects for a regex search\n");
83     fprintf(stderr, "\t\t\t  d:  print full details of the given OID\n");
84     fprintf(stderr, "\t\t\t  p:  print tree format symbol table\n");
85     fprintf(stderr, "\t\t\t  a:  print ASCII format symbol table\n");
86     fprintf(stderr, "\t\t\t  l:  enable labeled OID report\n");
87     fprintf(stderr, "\t\t\t  o:  enable OID report\n");
88     fprintf(stderr, "\t\t\t  s:  enable dotted symbolic report\n");
89     fprintf(stderr, "\t\t\t  z:  enable MIB child OID report\n");
90     fprintf(stderr,
91             "\t\t\t  t:  enable alternate format symbolic suffix report\n");
92 #ifndef NETSNMP_DISABLE_MIB_LOADING
93     fprintf(stderr,
94             "  -P MIBOPTS\t\tToggle various defaults controlling mib parsing:\n");
95     snmp_mib_toggle_options_usage("\t\t\t  ", stderr);
96 #endif /* NETSNMP_DISABLE_MIB_LOADING */
97     fprintf(stderr,
98             "  -O OUTOPTS\t\tToggle various defaults controlling output display:\n");
99     snmp_out_toggle_options_usage("\t\t\t  ", stderr);
100     fprintf(stderr,
101             "  -I INOPTS\t\tToggle various defaults controlling input parsing:\n");
102     snmp_in_toggle_options_usage("\t\t\t  ", stderr);
103     fprintf(stderr,
104             "  -L LOGOPTS\t\tToggle various defaults controlling logging:\n");
105     snmp_log_options_usage("\t\t\t  ", stderr);
106 }
107 
108 /**
109  * For every line on stdin, assume that it is either a plain OID
110  * or snmpwalk/snmpget output:
111  * mib-2.1.2.3.4
112  * -or-
113  * mib-2.1.2.3.4 = INTEGER: 5
114  *
115  * Replace the OID with its translation.
116  * If translation fails, just output the original string.
117  */
118 #define MAX_LINE_TEMP   10240
119 void
process_stdin(void)120 process_stdin(void)
121 {
122     char        buf[MAX_LINE_TEMP];
123     oid         name[MAX_OID_LEN];
124     size_t      name_length;
125 
126     while ( NULL != fgets( buf, sizeof( buf ), stdin ) ) {
127         char delim = ' ';
128         char *nl = strchr(buf, '\n');
129         char *rest = strchr(buf, delim);
130 
131         if (nl != NULL) {
132             *nl = '\0';
133         } /* else too-long line: output will look weird.  Too bad. */
134         if (rest == NULL) {
135             delim = '\t';
136             rest = strchr(buf, delim);
137         }
138         if (rest != NULL) {
139             *rest++ = '\0';
140         }
141         name_length = MAX_OID_LEN;
142         /*
143          * If it's not the whole line, only try to process buffer
144          * longer than 5 characters.
145          * The idea is to avoid false positives including, e.g.,
146          * a hex dump.
147          */
148         if ( !(rest && strlen( buf ) <= 5) &&
149               read_objid( buf, name, &name_length )) {
150             char objbuf[MAX_LINE_TEMP];
151             snprint_objid( objbuf, MAX_LINE_TEMP, name, name_length );
152             fputs( objbuf, stdout );
153         } else {
154             fputs( buf, stdout );
155         }
156         /*
157          * For future improvement: if delim == ' ' && rest && *rest == '='
158          * see if rest looks like snmpget/snmpwalk output
159          * and handle it in the context of the given node
160          */
161         if (rest) {
162             fputc( delim, stdout );
163             fputs( rest, stdout );
164         }
165         fputc( '\n', stdout );
166     }
167 }
168 
169 int
main(int argc,char * argv[])170 main(int argc, char *argv[])
171 {
172     int             arg;
173     char           *current_name = NULL, *cp = NULL;
174     oid             name[MAX_OID_LEN];
175     size_t          name_length;
176     int             description = 0;
177     int             print = 0;
178     int             find_all = 0;
179     int             width = 1000000;
180     int             exit_code = 1;
181     netsnmp_session dummy;
182 
183     SOCK_STARTUP;
184 
185     /*
186      * usage: snmptranslate name
187      */
188     snmp_sess_init(&dummy);
189     while ((arg = getopt(argc, argv, "Vhm:M:w:D:P:T:O:I:L:")) != EOF) {
190         switch (arg) {
191         case 'h':
192             usage();
193             goto out;
194 
195         case 'm':
196             setenv("MIBS", optarg, 1);
197             break;
198         case 'M':
199             setenv("MIBDIRS", optarg, 1);
200             break;
201         case 'D':
202             debug_register_tokens(optarg);
203             snmp_set_do_debugging(1);
204             break;
205         case 'V':
206             fprintf(stderr, "NET-SNMP version: %s\n",
207                     netsnmp_get_version());
208             exit_code = 0;
209             goto out;
210             break;
211         case 'w':
212 	    width = atoi(optarg);
213 	    if (width <= 0) {
214 		fprintf(stderr, "Invalid width specification: %s\n", optarg);
215 		goto out;
216 	    }
217 	    break;
218 #ifndef NETSNMP_DISABLE_MIB_LOADING
219         case 'P':
220             cp = snmp_mib_toggle_options(optarg);
221             if (cp != NULL) {
222                 fprintf(stderr, "Unknown parser option to -P: %c.\n", *cp);
223                 usage();
224                 goto out;
225             }
226             break;
227 #endif /* NETSNMP_DISABLE_MIB_LOADING */
228         case 'O':
229             cp = snmp_out_toggle_options(optarg);
230             if (cp != NULL) {
231                 fprintf(stderr, "Unknown OID option to -O: %c.\n", *cp);
232                 usage();
233                 goto out;
234             }
235             break;
236         case 'I':
237             cp = snmp_in_toggle_options(optarg);
238             if (cp != NULL) {
239                 fprintf(stderr, "Unknown OID option to -I: %c.\n", *cp);
240                 usage();
241                 goto out;
242             }
243             break;
244         case 'T':
245             for (cp = optarg; *cp; cp++) {
246                 switch (*cp) {
247 #ifndef NETSNMP_DISABLE_MIB_LOADING
248                 case 'l':
249                     print = 3;
250                     print_oid_report_enable_labeledoid();
251                     break;
252                 case 'o':
253                     print = 3;
254                     print_oid_report_enable_oid();
255                     break;
256                 case 's':
257                     print = 3;
258                     print_oid_report_enable_symbolic();
259                     break;
260                 case 't':
261                     print = 3;
262                     print_oid_report_enable_suffix();
263                     break;
264                 case 'z':
265                     print = 3;
266                     print_oid_report_enable_mibchildoid();
267                     break;
268 #endif /* NETSNMP_DISABLE_MIB_LOADING */
269                 case 'd':
270                     description = 1;
271                     netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
272                                            NETSNMP_DS_LIB_SAVE_MIB_DESCRS, 1);
273                     break;
274                 case 'B':
275                     find_all = 1;
276                     break;
277                 case 'p':
278                     print = 1;
279                     break;
280                 case 'a':
281                     print = 2;
282                     break;
283                 default:
284                     fprintf(stderr, "Invalid -T<lostpad> character: %c\n",
285                             *cp);
286                     usage();
287                     goto out;
288                 }
289             }
290             break;
291         case 'L':
292             if (snmp_log_options(optarg, argc, argv) < 0)
293                 goto out;
294             break;
295         default:
296             fprintf(stderr, "invalid option: -%c\n", arg);
297             usage();
298             goto out;
299         }
300     }
301 
302     init_snmp(NETSNMP_APPLICATION_CONFIG_TYPE);
303 
304     if (optind < argc)
305         current_name = argv[optind];
306 
307     if (current_name == NULL) {
308         switch (print) {
309         default:
310             usage();
311             goto out;
312 #ifndef NETSNMP_DISABLE_MIB_LOADING
313         case 1:
314             print_mib_tree(stdout, get_tree_head(), width);
315             break;
316         case 2:
317             print_ascii_dump(stdout);
318             break;
319         case 3:
320             print_oid_report(stdout);
321             break;
322 #endif /* NETSNMP_DISABLE_MIB_LOADING */
323         }
324         exit_code = 0;
325         goto out;
326     }
327 
328     do {
329         if ( strcmp( current_name, "-" ) == 0  && ( print == 0 ) ) {
330             process_stdin();
331             current_name = argv[++optind];
332             continue;
333         }
334 
335         name_length = MAX_OID_LEN;
336         if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
337 				  NETSNMP_DS_LIB_RANDOM_ACCESS)) {
338 #ifndef NETSNMP_DISABLE_MIB_LOADING
339             if (!get_node(current_name, name, &name_length)) {
340 #endif /* NETSNMP_DISABLE_MIB_LOADING */
341                 fprintf(stderr, "Unknown object identifier: %s\n",
342                         current_name);
343                 exit_code = 2;
344                 goto out;
345 #ifndef NETSNMP_DISABLE_MIB_LOADING
346             }
347 #endif /* NETSNMP_DISABLE_MIB_LOADING */
348         } else if (find_all) {
349             if (0 == show_all_matched_objects(stdout, current_name,
350                                               name, &name_length,
351                                               description, width)) {
352                 fprintf(stderr,
353                         "Unable to find a matching object identifier for \"%s\"\n",
354                         current_name);
355                 goto out;
356             }
357             break;
358         } else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
359 					  NETSNMP_DS_LIB_REGEX_ACCESS)) {
360 #ifndef NETSNMP_DISABLE_MIB_LOADING
361             if (0 == get_wild_node(current_name, name, &name_length)) {
362 #endif /* NETSNMP_DISABLE_MIB_LOADING */
363                 fprintf(stderr,
364                         "Unable to find a matching object identifier for \"%s\"\n",
365                         current_name);
366                 goto out;
367 #ifndef NETSNMP_DISABLE_MIB_LOADING
368             }
369 #endif /* NETSNMP_DISABLE_MIB_LOADING */
370         } else {
371             if (!read_objid(current_name, name, &name_length)) {
372                 snmp_perror(current_name);
373                 exit_code = 2;
374                 goto out;
375             }
376         }
377 
378 
379         if (print == 1) {
380 #ifndef NETSNMP_DISABLE_MIB_LOADING
381             struct tree    *tp;
382             tp = get_tree(name, name_length, get_tree_head());
383             if (tp == NULL) {
384 #endif /* NETSNMP_DISABLE_MIB_LOADING */
385                 snmp_log(LOG_ERR,
386                         "Unable to find a matching object identifier for \"%s\"\n",
387                         current_name);
388                 goto out;
389 #ifndef NETSNMP_DISABLE_MIB_LOADING
390             }
391             print_mib_tree(stdout, tp, width);
392 #endif /* NETSNMP_DISABLE_MIB_LOADING */
393         } else {
394             print_objid(name, name_length);
395             if (description) {
396 #ifndef NETSNMP_DISABLE_MIB_LOADING
397                 print_description(name, name_length, width);
398 #endif /* NETSNMP_DISABLE_MIB_LOADING */
399             }
400         }
401         current_name = argv[++optind];
402         if (current_name != NULL)
403             printf("\n");
404     } while (optind < argc);
405 
406     exit_code = 0;
407 
408 out:
409     SOCK_CLEANUP;
410     return exit_code;
411 }
412 
413 /*
414  * Show all object identifiers that match the pattern.
415  */
416 
417 int
show_all_matched_objects(FILE * fp,const char * patmatch,oid * name,size_t * name_length,int f_desc,int width)418 show_all_matched_objects(FILE * fp, const char *patmatch, oid * name, size_t * name_length, int f_desc, /* non-zero if descriptions should be shown */
419                          int width)
420 {
421     int             result = 0, count = 0;
422     size_t          savlen = *name_length;
423 #ifndef NETSNMP_DISABLE_MIB_LOADING
424     clear_tree_flags(get_tree_head());
425 #endif /* NETSNMP_DISABLE_MIB_LOADING */
426 
427     while (1) {
428         *name_length = savlen;
429 #ifndef NETSNMP_DISABLE_MIB_LOADING
430         result = get_wild_node(patmatch, name, name_length);
431 #endif /* NETSNMP_DISABLE_MIB_LOADING */
432         if (!result)
433             break;
434         count++;
435 
436         fprint_objid(fp, name, *name_length);
437 #ifndef NETSNMP_DISABLE_MIB_LOADING
438         if (f_desc)
439             fprint_description(fp, name, *name_length, width);
440 #endif /* NETSNMP_DISABLE_MIB_LOADING */
441     }
442 
443     return (count);
444 }
445