comparison packages/net/snmp/lib/current/src/mib.c @ 103:95f3e12a6327 ecos-sw-2000-06-23

Merge from eCos master repository on 2000-06-23-16:41:10-BST
author jlarmour
date Fri, 23 Jun 2000 17:06:31 +0000
parents
children e0c0827131d1
comparison
equal deleted inserted replaced
102:6409b6d94dd7 103:95f3e12a6327
1 //==========================================================================
2 //
3 // ./lib/current/src/mib.c
4 //
5 //
6 //==========================================================================
7 //####COPYRIGHTBEGIN####
8 //
9 // -------------------------------------------
10 // The contents of this file are subject to the Red Hat eCos Public License
11 // Version 1.1 (the "License"); you may not use this file except in
12 // compliance with the License. You may obtain a copy of the License at
13 // http://www.redhat.com/
14 //
15 // Software distributed under the License is distributed on an "AS IS"
16 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
17 // License for the specific language governing rights and limitations under
18 // the License.
19 //
20 // The Original Code is eCos - Embedded Configurable Operating System,
21 // released September 30, 1998.
22 //
23 // The Initial Developer of the Original Code is Red Hat.
24 // Portions created by Red Hat are
25 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
26 // All Rights Reserved.
27 // -------------------------------------------
28 //
29 //####COPYRIGHTEND####
30 //####UCDSNMPCOPYRIGHTBEGIN####
31 //
32 // -------------------------------------------
33 //
34 // Portions of this software may have been derived from the UCD-SNMP
35 // project, <http://ucd-snmp.ucdavis.edu/> from the University of
36 // California at Davis, which was originally based on the Carnegie Mellon
37 // University SNMP implementation. Portions of this software are therefore
38 // covered by the appropriate copyright disclaimers included herein.
39 //
40 // The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2"
41 // -------------------------------------------
42 //
43 //####UCDSNMPCOPYRIGHTEND####
44 //==========================================================================
45 //#####DESCRIPTIONBEGIN####
46 //
47 // Author(s): hmt
48 // Contributors: hmt
49 // Date: 2000-05-30
50 // Purpose: Port of UCD-SNMP distribution to eCos.
51 // Description:
52 //
53 //
54 //####DESCRIPTIONEND####
55 //
56 //==========================================================================
57 /********************************************************************
58 Copyright 1989, 1991, 1992 by Carnegie Mellon University
59
60 Derivative Work -
61 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
62
63 All Rights Reserved
64
65 Permission to use, copy, modify and distribute this software and its
66 documentation for any purpose and without fee is hereby granted,
67 provided that the above copyright notice appears in all copies and
68 that both that copyright notice and this permission notice appear in
69 supporting documentation, and that the name of CMU and The Regents of
70 the University of California not be used in advertising or publicity
71 pertaining to distribution of the software without specific written
72 permission.
73
74 CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
75 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
76 WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR
77 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
78 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
79 FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
80 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
81 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
82 *********************************************************************/
83 /*
84 * mib.c
85 *
86 * Update: 1998-07-17 <jhy@gsu.edu>
87 * Added print_oid_report* functions.
88 *
89 */
90 /**********************************************************************
91 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
92
93 All Rights Reserved
94
95 Permission to use, copy, modify, and distribute this software and its
96 documentation for any purpose and without fee is hereby granted,
97 provided that the above copyright notice appear in all copies and that
98 both that copyright notice and this permission notice appear in
99 supporting documentation, and that the name of CMU not be
100 used in advertising or publicity pertaining to distribution of the
101 software without specific, written prior permission.
102
103 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
104 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
105 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
106 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
107 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
108 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
109 SOFTWARE.
110 ******************************************************************/
111 #include <config.h>
112
113 #include <stdio.h>
114 #include <ctype.h>
115 #include <sys/types.h>
116 #if HAVE_NETINET_IN_H
117 #include <netinet/in.h>
118 #endif
119 #if TIME_WITH_SYS_TIME
120 # ifdef WIN32
121 # include <sys/timeb.h>
122 # else
123 # include <sys/time.h>
124 # endif
125 # include <time.h>
126 #else
127 # if HAVE_SYS_TIME_H
128 # include <sys/time.h>
129 # else
130 # include <time.h>
131 # endif
132 #endif
133 #if HAVE_STRING_H
134 #include <string.h>
135 #else
136 #include <strings.h>
137 #endif
138 #if HAVE_STDLIB_H
139 #include <stdlib.h>
140 #endif
141 #if HAVE_SYS_SELECT_H
142 #include <sys/select.h>
143 #endif
144
145 #if HAVE_WINSOCK_H
146 #include <winsock.h>
147 #endif
148
149 #if HAVE_DMALLOC_H
150 #include <dmalloc.h>
151 #endif
152
153 #include "asn1.h"
154 #include "snmp_api.h"
155 #include "mib.h"
156 #include "snmp.h"
157 #include "snmp_impl.h"
158 #include "parse.h"
159 #include "int64.h"
160 #include "system.h"
161 #include "read_config.h"
162 #include "snmp_debug.h"
163 #include "default_store.h"
164
165 static void sprint_by_type (char *, struct variable_list *, struct enum_list *, const char *, const char *);
166 static int parse_subtree (struct tree *, const char *, oid *, size_t *);
167 static struct tree * _sprint_objid(char *buf, oid *objid, size_t objidlen);
168 static char *uptimeString (u_long, char *);
169 static void sprint_octet_string (char *, struct variable_list *, struct enum_list *, const char *, const char *);
170 static void sprint_opaque (char *, struct variable_list *, struct enum_list *, const char *, const char *);
171 static void sprint_object_identifier (char *, struct variable_list *, struct enum_list *, const char *, const char *);
172 static void sprint_timeticks (char *, struct variable_list *, struct enum_list *, const char *, const char *);
173 static void sprint_hinted_integer (char *, long, const char *, const char *);
174 static void sprint_integer (char *, struct variable_list *, struct enum_list *, const char *, const char *);
175 static void sprint_uinteger (char *, struct variable_list *, struct enum_list *, const char *, const char *);
176 static void sprint_gauge (char *, struct variable_list *, struct enum_list *, const char *, const char *);
177 static void sprint_counter (char *, struct variable_list *, struct enum_list *, const char *, const char *);
178 static void sprint_networkaddress (char *, struct variable_list *, struct enum_list *, const char *, const char *);
179 static void sprint_ipaddress (char *, struct variable_list *, struct enum_list *, const char *, const char *);
180 static void sprint_null (char *, struct variable_list *, struct enum_list *, const char *, const char *);
181 static void sprint_bitstring (char *, struct variable_list *, struct enum_list *, const char *, const char *);
182 static void sprint_nsapaddress (char *, struct variable_list *, struct enum_list *, const char *, const char *);
183 static void sprint_counter64 (char *, struct variable_list *, struct enum_list *, const char *, const char *);
184 static void sprint_unknowntype (char *, struct variable_list *, struct enum_list *, const char *, const char *);
185 static void sprint_badtype (char *, struct variable_list *, struct enum_list *, const char *, const char *);
186 struct tree *_get_symbol(oid *objid, size_t objidlen, struct tree *subtree, char *buf, struct index_list *in_dices, char **end_of_known);
187
188 #ifdef OPAQUE_SPECIAL_TYPES
189 static void sprint_float (char *, struct variable_list *, struct enum_list *, const char *, const char *);
190 static void sprint_double (char *, struct variable_list *, struct enum_list *, const char *, const char *);
191 #endif
192 void print_tree_node (FILE *f, struct tree *tp);
193
194 /* helper functions for get_module_node */
195 int node_to_oid(struct tree *, oid *, size_t *);
196 static int _add_strings_to_oid(struct tree *, char *,
197 oid *, size_t *, size_t);
198
199 extern struct tree *tree_head;
200
201 struct tree *Mib; /* Backwards compatibility */
202
203 oid RFC1213_MIB[] = { 1, 3, 6, 1, 2, 1 };
204 static char Standard_Prefix[] = ".1.3.6.1.2.1";
205
206 /* Set default here as some uses of read_objid require valid pointer. */
207 static char *Prefix = &Standard_Prefix[0];
208 typedef struct _PrefixList {
209 const char *str;
210 int len;
211 } *PrefixListPtr, PrefixList;
212
213 /*
214 * Here are the prefix strings.
215 * Note that the first one finds the value of Prefix or Standard_Prefix.
216 * Any of these MAY start with period; all will NOT end with period.
217 * Period is added where needed. See use of Prefix in this module.
218 */
219 PrefixList mib_prefixes[] = {
220 { &Standard_Prefix[0] }, /* placeholder for Prefix data */
221 { ".iso.org.dod.internet.mgmt.mib-2" },
222 { ".iso.org.dod.internet.experimental" },
223 { ".iso.org.dod.internet.private" },
224 { ".iso.org.dod.internet.snmpParties" },
225 { ".iso.org.dod.internet.snmpSecrets" },
226 { NULL, 0 } /* end of list */
227 };
228
229 static char *
230 uptimeString(u_long timeticks,
231 char *buf)
232 {
233 int centisecs, seconds, minutes, hours, days;
234
235 centisecs = timeticks % 100;
236 timeticks /= 100;
237 days = timeticks / (60 * 60 * 24);
238 timeticks %= (60 * 60 * 24);
239
240 hours = timeticks / (60 * 60);
241 timeticks %= (60 * 60);
242
243 minutes = timeticks / 60;
244 seconds = timeticks % 60;
245
246 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT))
247 sprintf(buf, "%d:%d:%02d:%02d.%02d",
248 days, hours, minutes, seconds, centisecs);
249 else {
250 if (days == 0){
251 sprintf(buf, "%d:%02d:%02d.%02d",
252 hours, minutes, seconds, centisecs);
253 } else if (days == 1) {
254 sprintf(buf, "%d day, %d:%02d:%02d.%02d",
255 days, hours, minutes, seconds, centisecs);
256 } else {
257 sprintf(buf, "%d days, %d:%02d:%02d.%02d",
258 days, hours, minutes, seconds, centisecs);
259 }
260 }
261 return buf;
262 }
263
264
265
266 void sprint_hexstring(char *buf,
267 const u_char *cp,
268 size_t len)
269 {
270
271 for(; len >= 16; len -= 16){
272 sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
273 buf += strlen(buf);
274 cp += 8;
275 sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
276 buf += strlen(buf);
277 if (len > 16) { *buf++ = '\n'; *buf = 0; }
278 cp += 8;
279 }
280 for(; len > 0; len--){
281 sprintf(buf, "%02X ", *cp++);
282 buf += strlen(buf);
283 }
284 *buf = '\0';
285 }
286
287 void sprint_asciistring(char *buf,
288 u_char *cp,
289 size_t len)
290 {
291 int x;
292
293 for(x = 0; x < (int)len; x++){
294 if (isprint(*cp)){
295 *buf++ = *cp++;
296 } else {
297 *buf++ = '.';
298 cp++;
299 }
300 #if 0
301 if ((x % 48) == 47)
302 *buf++ = '\n';
303 #endif
304 }
305 *buf = '\0';
306 }
307
308
309 /*
310 0
311 < 4
312 hex
313
314 0 ""
315 < 4 hex Hex: oo oo oo
316 < 4 "fgh" Hex: oo oo oo
317 > 4 hex Hex: oo oo oo oo oo oo oo oo
318 > 4 "this is a test"
319
320 */
321
322 static void
323 sprint_octet_string(char *buf,
324 struct variable_list *var,
325 struct enum_list *enums,
326 const char *hint,
327 const char *units)
328 {
329 int hex, x;
330 u_char *cp;
331 const char *saved_hint = hint;
332 char *saved_buf = buf;
333
334 if (var->type != ASN_OCTET_STR){
335 sprintf(buf, "Wrong Type (should be OCTET STRING): ");
336 buf += strlen(buf);
337 sprint_by_type(buf, var, NULL, NULL, NULL);
338 return;
339 }
340
341 if (hint) {
342 int repeat, width = 1;
343 long value;
344 char code = 'd', separ = 0, term = 0, ch;
345 u_char *ecp;
346
347 *buf = 0;
348 cp = var->val.string;
349 ecp = cp + var->val_len;
350 while (cp < ecp) {
351 repeat = 1;
352 if (*hint) {
353 if (*hint == '*') {
354 repeat = *cp++;
355 hint++;
356 }
357 width = 0;
358 while ('0' <= *hint && *hint <= '9')
359 width = width * 10 + *hint++ - '0';
360 code = *hint++;
361 if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9')
362 && (width != 0 || (ch != 'x' && ch != 'd' && ch != 'o')))
363 separ = *hint++;
364 else separ = 0;
365 if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9')
366 && (width != 0 || (ch != 'x' && ch != 'd' && ch != 'o')))
367 term = *hint++;
368 else term = 0;
369 if (width == 0) width = 1;
370 }
371 while (repeat && cp < ecp) {
372 value = 0;
373 if (code != 'a')
374 for (x = 0; x < width; x++) value = value * 256 + *cp++;
375 switch (code) {
376 case 'x':
377 sprintf (buf, "%lx", value); break;
378 case 'd':
379 sprintf (buf, "%ld", value); break;
380 case 'o':
381 sprintf (buf, "%lo", value); break;
382 case 'a':
383 for (x = 0; x < width && cp < ecp; x++)
384 *buf++ = *cp++;
385 *buf = 0;
386 break;
387 default:
388 sprintf(saved_buf, "(Bad hint ignored: %s) ", saved_hint);
389 sprint_octet_string(saved_buf+strlen(saved_buf),
390 var, enums, NULL, NULL);
391 return;
392 }
393 buf += strlen (buf);
394 if (cp < ecp && separ) *buf++ = separ;
395 repeat--;
396 }
397 if (term && cp < ecp) *buf++ = term;
398 }
399 if (units) sprintf (buf, " %s", units);
400 return;
401 }
402
403 hex = 0;
404 for(cp = var->val.string, x = 0; x < (int)var->val_len; x++, cp++){
405 if (!(isprint(*cp) || isspace(*cp)))
406 hex = 1;
407 }
408 if (var->val_len == 0){
409 strcpy(buf, "\"\"");
410 return;
411 }
412 if (!hex){
413 *buf++ = '"';
414 sprint_asciistring(buf, var->val.string, var->val_len);
415 buf += strlen(buf);
416 *buf++ = '"';
417 *buf = '\0';
418 }
419 if (hex || ((var->val_len <= 4) && !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT))){
420 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
421 *buf++ = '"';
422 *buf = '\0';
423 } else {
424 sprintf(buf, " Hex: ");
425 buf += strlen(buf);
426 }
427 sprint_hexstring(buf, var->val.string, var->val_len);
428 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
429 buf += strlen(buf);
430 *buf++ = '"';
431 *buf = '\0';
432 }
433 }
434 if (units) sprintf (buf, " %s", units);
435 }
436
437 #ifdef OPAQUE_SPECIAL_TYPES
438
439 static void
440 sprint_float(char *buf,
441 struct variable_list *var,
442 struct enum_list *enums,
443 const char *hint,
444 const char *units)
445 {
446 if (var->type != ASN_OPAQUE_FLOAT) {
447 sprintf(buf, "Wrong Type (should be Float): ");
448 buf += strlen(buf);
449 sprint_by_type(buf, var, NULL, NULL, NULL);
450 return;
451 }
452 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
453 sprintf(buf, "Opaque: Float:");
454 buf += strlen(buf);
455 }
456 sprintf(buf, " %f", *var->val.floatVal);
457 buf += strlen (buf);
458 if (units) sprintf (buf, " %s", units);
459 }
460
461 static void
462 sprint_double(char *buf,
463 struct variable_list *var,
464 struct enum_list *enums,
465 const char *hint,
466 const char *units)
467 {
468 if (var->type != ASN_OPAQUE_DOUBLE) {
469 sprintf(buf, "Wrong Type (should be Double): ");
470 buf += strlen(buf);
471 sprint_by_type(buf, var, NULL, NULL, NULL);
472 return;
473 }
474 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
475 sprintf(buf, "Opaque: Double:");
476 buf += strlen(buf);
477 }
478 sprintf(buf, " %f", *var->val.doubleVal);
479 buf += strlen (buf);
480 if (units) sprintf (buf, " %s", units);
481 }
482
483 #endif /* OPAQUE_SPECIAL_TYPES */
484
485 static void
486 sprint_opaque(char *buf,
487 struct variable_list *var,
488 struct enum_list *enums,
489 const char *hint,
490 const char *units)
491 {
492
493 if (var->type != ASN_OPAQUE
494 #ifdef OPAQUE_SPECIAL_TYPES
495 && var->type != ASN_OPAQUE_COUNTER64
496 && var->type != ASN_OPAQUE_U64
497 && var->type != ASN_OPAQUE_I64
498 && var->type != ASN_OPAQUE_FLOAT
499 && var->type != ASN_OPAQUE_DOUBLE
500 #endif /* OPAQUE_SPECIAL_TYPES */
501 ){
502 sprintf(buf, "Wrong Type (should be Opaque): ");
503 buf += strlen(buf);
504 sprint_by_type(buf, var, NULL, NULL, NULL);
505 return;
506 }
507 #ifdef OPAQUE_SPECIAL_TYPES
508 switch(var->type) {
509 case ASN_OPAQUE_COUNTER64:
510 case ASN_OPAQUE_U64:
511 case ASN_OPAQUE_I64:
512 sprint_counter64(buf, var, enums, hint, units);
513 break;
514
515 case ASN_OPAQUE_FLOAT:
516 sprint_float(buf, var, enums, hint, units);
517 break;
518
519 case ASN_OPAQUE_DOUBLE:
520 sprint_double(buf, var, enums, hint, units);
521 break;
522
523 case ASN_OPAQUE:
524 #endif
525 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
526 sprintf(buf, "OPAQUE: ");
527 buf += strlen(buf);
528 }
529 sprint_hexstring(buf, var->val.string, var->val_len);
530 buf += strlen (buf);
531 #ifdef OPAQUE_SPECIAL_TYPES
532 }
533 #endif
534 if (units) sprintf (buf, " %s", units);
535 }
536
537 static void
538 sprint_object_identifier(char *buf,
539 struct variable_list *var,
540 struct enum_list *enums,
541 const char *hint,
542 const char *units)
543 {
544 if (var->type != ASN_OBJECT_ID){
545 sprintf(buf, "Wrong Type (should be OBJECT IDENTIFIER): ");
546 buf += strlen(buf);
547 sprint_by_type(buf, var, NULL, NULL, NULL);
548 return;
549 }
550 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
551 sprintf(buf, "OID: ");
552 buf += strlen(buf);
553 }
554 _sprint_objid(buf, (oid *)(var->val.objid), var->val_len / sizeof(oid));
555 buf += strlen (buf);
556 if (units) sprintf (buf, " %s", units);
557 }
558
559 static void
560 sprint_timeticks(char *buf,
561 struct variable_list *var,
562 struct enum_list *enums,
563 const char *hint,
564 const char *units)
565 {
566 char timebuf[32];
567
568 if (var->type != ASN_TIMETICKS){
569 sprintf(buf, "Wrong Type (should be Timeticks): ");
570 buf += strlen(buf);
571 sprint_by_type(buf, var, NULL, NULL, NULL);
572 return;
573 }
574 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
575 sprintf(buf, "Timeticks: (%lu) ", *(u_long *)(var->val.integer));
576 buf += strlen(buf);
577 }
578 sprintf(buf, "%s", uptimeString(*(u_long *)(var->val.integer), timebuf));
579 buf += strlen (buf);
580 if (units) sprintf (buf, " %s", units);
581 }
582
583 static void
584 sprint_hinted_integer (char *buf,
585 long val,
586 const char *hint,
587 const char *units)
588 {
589 char code;
590 int shift, len;
591 char tmp[256];
592 char fmt[10];
593
594 code = hint[0];
595 if (hint [1] == '-') {
596 shift = atoi (hint+2);
597 }
598 else shift = 0;
599 fmt[0] = '%';
600 fmt[1] = 'l';
601 fmt[2] = code;
602 fmt[3] = 0;
603 sprintf (tmp, fmt, val);
604 if (shift != 0) {
605 len = strlen (tmp);
606 if (shift <= len) {
607 tmp[len+1] = 0;
608 while (shift--) {
609 tmp[len] = tmp[len-1];
610 len--;
611 }
612 tmp[len] = '.';
613 }
614 else {
615 tmp[shift+1] = 0;
616 while (shift) {
617 if (len-- > 0) tmp [shift] = tmp [len];
618 else tmp[shift] = '0';
619 shift--;
620 }
621 tmp[0] = '.';
622 }
623 }
624 strcpy (buf, tmp);
625 }
626
627 static void
628 sprint_integer(char *buf,
629 struct variable_list *var,
630 struct enum_list *enums,
631 const char *hint,
632 const char *units)
633 {
634 char *enum_string = NULL;
635
636 if (var->type != ASN_INTEGER){
637 sprintf(buf, "Wrong Type (should be INTEGER): ");
638 buf += strlen(buf);
639 sprint_by_type(buf, var, NULL, NULL, NULL);
640 return;
641 }
642 for (; enums; enums = enums->next)
643 if (enums->value == *var->val.integer){
644 enum_string = enums->label;
645 break;
646 }
647 if (enum_string == NULL ||
648 ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_ENUM)) {
649 if (hint) sprint_hinted_integer(buf, *var->val.integer, hint, units);
650 else sprintf(buf, "%ld", *var->val.integer);
651 }
652 else if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT))
653 sprintf(buf, "%s", enum_string);
654 else
655 sprintf(buf, "%s(%ld)", enum_string, *var->val.integer);
656 buf += strlen (buf);
657 if (units) sprintf (buf, " %s", units);
658 }
659
660 static void
661 sprint_uinteger(char *buf,
662 struct variable_list *var,
663 struct enum_list *enums,
664 const char *hint,
665 const char *units)
666 {
667 char *enum_string = NULL;
668
669 if (var->type != ASN_UINTEGER){
670 sprintf(buf, "Wrong Type (should be UInteger32): ");
671 buf += strlen(buf);
672 sprint_by_type(buf, var, NULL, NULL, NULL);
673 return;
674 }
675 for (; enums; enums = enums->next)
676 if (enums->value == *var->val.integer){
677 enum_string = enums->label;
678 break;
679 }
680 if (enum_string == NULL ||
681 ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_ENUM))
682 sprintf(buf, "%lu", *var->val.integer);
683 else if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT))
684 sprintf(buf, "%s", enum_string);
685 else
686 sprintf(buf, "%s(%lu)", enum_string, *var->val.integer);
687 buf += strlen (buf);
688 if (units) sprintf (buf, " %s", units);
689 }
690
691 static void
692 sprint_gauge(char *buf,
693 struct variable_list *var,
694 struct enum_list *enums,
695 const char *hint,
696 const char *units)
697 {
698 if (var->type != ASN_GAUGE){
699 sprintf(buf, "Wrong Type (should be Gauge): ");
700 buf += strlen(buf);
701 sprint_by_type(buf, var, NULL, NULL, NULL);
702 return;
703 }
704 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT))
705 sprintf(buf, "%lu", *var->val.integer);
706 else
707 sprintf(buf, "Gauge: %lu", *var->val.integer);
708 buf += strlen (buf);
709 if (units) sprintf (buf, " %s", units);
710 }
711
712 static void
713 sprint_counter(char *buf,
714 struct variable_list *var,
715 struct enum_list *enums,
716 const char *hint,
717 const char *units)
718 {
719 if (var->type != ASN_COUNTER){
720 sprintf(buf, "Wrong Type (should be Counter): ");
721 buf += strlen(buf);
722 sprint_by_type(buf, var, NULL, NULL, NULL);
723 return;
724 }
725 sprintf(buf, "%lu", *var->val.integer);
726 buf += strlen (buf);
727 if (units) sprintf (buf, " %s", units);
728 }
729
730 static void
731 sprint_networkaddress(char *buf,
732 struct variable_list *var,
733 struct enum_list *enums,
734 const char *hint,
735 const char *units)
736 {
737 int x, len;
738 u_char *cp;
739
740 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
741 sprintf(buf, "Network Address: ");
742 buf += strlen(buf);
743 }
744 cp = var->val.string;
745 len = var->val_len;
746 for(x = 0; x < len; x++){
747 sprintf(buf, "%02X", *cp++);
748 buf += strlen(buf);
749 if (x < (len - 1))
750 *buf++ = ':';
751 }
752 }
753
754 static void
755 sprint_ipaddress(char *buf,
756 struct variable_list *var,
757 struct enum_list *enums,
758 const char *hint,
759 const char *units)
760 {
761 u_char *ip;
762
763 if (var->type != ASN_IPADDRESS){
764 sprintf(buf, "Wrong Type (should be Ipaddress): ");
765 buf += strlen(buf);
766 sprint_by_type(buf, var, NULL, NULL, NULL);
767 return;
768 }
769 ip = var->val.string;
770 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT))
771 sprintf(buf, "%d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]);
772 else
773 sprintf(buf, "IpAddress: %d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]);
774 }
775
776 static void
777 sprint_null(char *buf,
778 struct variable_list *var,
779 struct enum_list *enums,
780 const char *hint,
781 const char *units)
782 {
783 if (var->type != ASN_NULL){
784 sprintf(buf, "Wrong Type (should be NULL): ");
785 buf += strlen(buf);
786 sprint_by_type(buf, var, NULL, NULL, NULL);
787 return;
788 }
789 sprintf(buf, "NULL");
790 }
791
792 static void
793 sprint_bitstring(char *buf,
794 struct variable_list *var,
795 struct enum_list *enums,
796 const char *hint,
797 const char *units)
798 {
799 int len, bit;
800 u_char *cp;
801 char *enum_string;
802
803 if (var->type != ASN_BIT_STR && var->type != ASN_OCTET_STR){
804 sprintf(buf, "Wrong Type (should be BIT STRING): ");
805 buf += strlen(buf);
806 sprint_by_type(buf, var, NULL, NULL, NULL);
807 return;
808 }
809 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
810 *buf++ = '"';
811 *buf = '\0';
812 } else {
813 sprintf(buf, "BITS: ");
814 buf += strlen(buf);
815 }
816 sprint_hexstring(buf, var->val.bitstring, var->val_len);
817 buf += strlen(buf);
818
819 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
820 buf += strlen(buf);
821 *buf++ = '"';
822 *buf = '\0';
823 } else {
824 cp = var->val.bitstring;
825 for(len = 0; len < (int)var->val_len; len++){
826 for(bit = 0; bit < 8; bit++){
827 if (*cp & (0x80 >> bit)){
828 enum_string = NULL;
829 for (; enums; enums = enums->next)
830 if (enums->value == (len * 8) + bit){
831 enum_string = enums->label;
832 break;
833 }
834 if (enum_string == NULL ||
835 ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_ENUM))
836 sprintf(buf, "%d ", (len * 8) + bit);
837 else
838 sprintf(buf, "%s(%d) ", enum_string, (len * 8) + bit);
839 buf += strlen(buf);
840 }
841 }
842 cp ++;
843 }
844 }
845 }
846
847 static void
848 sprint_nsapaddress(char *buf,
849 struct variable_list *var,
850 struct enum_list *enums,
851 const char *hint,
852 const char *units)
853 {
854 if (var->type != ASN_NSAP){
855 sprintf(buf, "Wrong Type (should be NsapAddress): ");
856 buf += strlen(buf);
857 sprint_by_type(buf, var, NULL, NULL, NULL);
858 return;
859 }
860 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
861 sprintf(buf, "NsapAddress: ");
862 buf += strlen(buf);
863 }
864 sprint_hexstring(buf, var->val.string, var->val_len);
865 }
866
867 static void
868 sprint_counter64(char *buf,
869 struct variable_list *var,
870 struct enum_list *enums,
871 const char *hint,
872 const char *units)
873 {
874 char a64buf[I64CHARSZ+1];
875
876 if (var->type != ASN_COUNTER64
877 #ifdef OPAQUE_SPECIAL_TYPES
878 && var->type != ASN_OPAQUE_COUNTER64
879 && var->type != ASN_OPAQUE_I64
880 && var->type != ASN_OPAQUE_U64
881 #endif
882 ){
883 sprintf(buf, "Wrong Type (should be Counter64): ");
884 buf += strlen(buf);
885 sprint_by_type(buf, var, NULL, NULL, NULL);
886 return;
887 }
888 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){
889 #ifdef OPAQUE_SPECIAL_TYPES
890 if (var->type != ASN_COUNTER64) {
891 sprintf(buf, "Opaque: ");
892 buf += strlen(buf);
893 }
894 #endif
895 #ifdef OPAQUE_SPECIAL_TYPES
896 switch(var->type) {
897 case ASN_OPAQUE_U64:
898 sprintf(buf, "UInt64: ");
899 break;
900 case ASN_OPAQUE_I64:
901 sprintf(buf, "Int64: ");
902 break;
903 case ASN_COUNTER64:
904 case ASN_OPAQUE_COUNTER64:
905 #endif
906 sprintf(buf, "Counter64: ");
907 #ifdef OPAQUE_SPECIAL_TYPES
908 }
909 #endif
910 buf += strlen(buf);
911 }
912 #ifdef OPAQUE_SPECIAL_TYPES
913 if (var->type == ASN_OPAQUE_I64)
914 {
915 printI64(a64buf, var->val.counter64);
916 sprintf(buf, a64buf);
917 }
918 else
919 #endif
920 {
921 printU64(a64buf, var->val.counter64);
922 sprintf(buf, a64buf);
923 }
924 buf += strlen (buf);
925 if (units) sprintf (buf, " %s", units);
926 }
927
928 static void
929 sprint_unknowntype(char *buf,
930 struct variable_list *var,
931 struct enum_list *enums,
932 const char *hint,
933 const char *units)
934 {
935 /* sprintf(buf, "Variable has bad type"); */
936 sprint_by_type(buf, var, NULL, NULL, NULL);
937 }
938
939 static void
940 sprint_badtype(char *buf,
941 struct variable_list *var,
942 struct enum_list *enums,
943 const char *hint,
944 const char *units)
945 {
946 sprintf(buf, "Variable has bad type");
947 }
948
949 static void
950 sprint_by_type(char *buf,
951 struct variable_list *var,
952 struct enum_list *enums,
953 const char *hint,
954 const char *units)
955 {
956 switch (var->type){
957 case ASN_INTEGER:
958 sprint_integer(buf, var, enums, hint, units);
959 break;
960 case ASN_OCTET_STR:
961 sprint_octet_string(buf, var, enums, hint, units);
962 break;
963 case ASN_BIT_STR:
964 sprint_bitstring(buf, var, enums, hint, units);
965 break;
966 case ASN_OPAQUE:
967 sprint_opaque(buf, var, enums, hint, units);
968 break;
969 case ASN_OBJECT_ID:
970 sprint_object_identifier(buf, var, enums, hint, units);
971 break;
972 case ASN_TIMETICKS:
973 sprint_timeticks(buf, var, enums, hint, units);
974 break;
975 case ASN_GAUGE:
976 sprint_gauge(buf, var, enums, hint, units);
977 break;
978 case ASN_COUNTER:
979 sprint_counter(buf, var, enums, hint, units);
980 break;
981 case ASN_IPADDRESS:
982 sprint_ipaddress(buf, var, enums, hint, units);
983 break;
984 case ASN_NULL:
985 sprint_null(buf, var, enums, hint, units);
986 break;
987 case ASN_UINTEGER:
988 sprint_uinteger(buf, var, enums, hint, units);
989 break;
990 case ASN_COUNTER64:
991 #ifdef OPAQUE_SPECIAL_TYPES
992 case ASN_OPAQUE_U64:
993 case ASN_OPAQUE_I64:
994 case ASN_OPAQUE_COUNTER64:
995 #endif /* OPAQUE_SPECIAL_TYPES */
996 sprint_counter64(buf, var, enums, hint, units);
997 break;
998 #ifdef OPAQUE_SPECIAL_TYPES
999 case ASN_OPAQUE_FLOAT:
1000 sprint_float(buf, var, enums, hint, units);
1001 break;
1002 case ASN_OPAQUE_DOUBLE:
1003 sprint_double(buf, var, enums, hint, units);
1004 break;
1005 #endif /* OPAQUE_SPECIAL_TYPES */
1006 default:
1007 DEBUGMSGTL(("sprint_by_type", "bad type: %d\n", var->type));
1008 sprint_badtype(buf, var, enums, hint, units);
1009 break;
1010 }
1011 }
1012
1013
1014 struct tree *get_tree_head(void)
1015 {
1016 return(tree_head);
1017 }
1018
1019 static char *confmibdir=NULL;
1020 static char *confmibs=NULL;
1021
1022 void
1023 handle_mibdirs_conf(const char *token,
1024 char *line)
1025 {
1026 char *ctmp;
1027
1028 if (confmibdir) {
1029 ctmp = (char *)malloc(strlen(confmibdir) + strlen(line) + 1);
1030 if (*line == '+')
1031 line++;
1032 sprintf(ctmp,"%s%c%s",confmibdir, ENV_SEPARATOR_CHAR, line);
1033 free(confmibdir);
1034 confmibdir = ctmp;
1035 } else {
1036 confmibdir=strdup(line);
1037 }
1038 DEBUGMSGTL(("read_config:initmib", "using mibdirs: %s\n", confmibdir));
1039 }
1040
1041 void
1042 handle_mibs_conf(const char *token,
1043 char *line)
1044 {
1045 char *ctmp;
1046
1047 if (confmibs) {
1048 ctmp = (char *)malloc(strlen(confmibs) + strlen(line) + 1);
1049 if (*line == '+')
1050 line++;
1051 sprintf(ctmp,"%s%c%s",confmibs, ENV_SEPARATOR_CHAR, line);
1052 free(confmibs);
1053 confmibs = ctmp;
1054 } else {
1055 confmibs=strdup(line);
1056 }
1057 DEBUGMSGTL(("read_config:initmib", "using mibs: %s\n", confmibs));
1058 }
1059
1060 void
1061 handle_mibfile_conf(const char *token,
1062 char *line)
1063 {
1064 DEBUGMSGTL(("read_config:initmib", "reading mibfile: %s\n", line));
1065 read_mib(line);
1066 }
1067
1068 char *
1069 snmp_out_toggle_options(char *options)
1070 {
1071 while(*options) {
1072 switch(*options++) {
1073 case 'n':
1074 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_OIDS);
1075 break;
1076 case 'e':
1077 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_ENUM);
1078 break;
1079 case 'b':
1080 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_DONT_BREAKDOWN_OIDS);
1081 break;
1082 case 'q':
1083 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT);
1084 break;
1085 case 'f':
1086 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_FULL_OID);
1087 break;
1088 case 's':
1089 snmp_set_suffix_only(1);
1090 break;
1091 case 'S':
1092 snmp_set_suffix_only(2);
1093 break;
1094 default:
1095 return options-1;
1096 }
1097 }
1098 return NULL;
1099 }
1100
1101 void snmp_out_toggle_options_usage(const char *lead, FILE *outf)
1102 {
1103 fprintf(outf, "%sOUTOPTS values:\n", lead);
1104 fprintf(outf, "%s n: Print oids numerically.\n", lead);
1105 fprintf(outf, "%s e: Print enums numerically.\n", lead);
1106 fprintf(outf, "%s b: Dont break oid indexes down.\n", lead);
1107 fprintf(outf, "%s q: Quick print for easier parsing.\n", lead);
1108 fprintf(outf, "%s f: Print full oids on output.\n", lead);
1109 fprintf(outf, "%s s: Print only last symbolic element of oid.\n", lead);
1110 fprintf(outf, "%s S: Print MIB module-id plus last element.\n", lead);
1111 }
1112
1113 char *
1114 snmp_in_toggle_options(char *options)
1115 {
1116 while(*options) {
1117 switch(*options++) {
1118 case 'R':
1119 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_RANDOM_ACCESS);
1120 break;
1121 case 'b':
1122 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_REGEX_ACCESS);
1123 break;
1124 default:
1125 return options-1;
1126 }
1127 }
1128 return NULL;
1129 }
1130
1131 void snmp_in_toggle_options_usage(const char *lead, FILE *outf)
1132 {
1133 fprintf(outf, "%sINOPTS values:\n", lead);
1134 fprintf(outf, "%s R: Do random access to oid labels.\n", lead);
1135 fprintf(outf, "%s b: Do best/regex matching to find a MIB node.\n", lead);
1136 }
1137
1138 void
1139 register_mib_handlers (void)
1140 {
1141 register_premib_handler("snmp","mibdirs",
1142 handle_mibdirs_conf, NULL,
1143 "[mib-dirs|+mib-dirs]");
1144 register_premib_handler("snmp","mibs",
1145 handle_mibs_conf,NULL,
1146 "[mib-tokens|+mib-tokens]");
1147 register_config_handler("snmp","mibfile",
1148 handle_mibfile_conf, NULL,
1149 "mibfile-to-read");
1150
1151 /* register the snmp.conf configuration handlers for default
1152 parsing behaviour */
1153
1154 ds_register_premib(ASN_BOOLEAN, "snmp","showMibErrors",
1155 DS_LIBRARY_ID, DS_LIB_MIB_ERRORS);
1156 ds_register_premib(ASN_BOOLEAN, "snmp","strictCommentTerm",
1157 DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM);
1158 ds_register_premib(ASN_BOOLEAN, "snmp","mibAllowUnderline",
1159 DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL);
1160 ds_register_premib(ASN_INTEGER, "snmp","mibWarningLevel",
1161 DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS);
1162 ds_register_premib(ASN_BOOLEAN, "snmp","mibReplaceWithLatest",
1163 DS_LIBRARY_ID, DS_LIB_MIB_REPLACE);
1164
1165 ds_register_config(ASN_BOOLEAN, "snmp","printNumericEnums",
1166 DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_ENUM);
1167 ds_register_config(ASN_BOOLEAN, "snmp","printNumericOids",
1168 DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_OIDS);
1169 ds_register_config(ASN_BOOLEAN, "snmp","dontBreakdownOids",
1170 DS_LIBRARY_ID, DS_LIB_DONT_BREAKDOWN_OIDS);
1171 ds_register_config(ASN_BOOLEAN, "snmp","quickPrinting",
1172 DS_LIBRARY_ID, DS_LIB_QUICK_PRINT);
1173 ds_register_config(ASN_INTEGER, "snmp","suffixPrinting",
1174 DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY);
1175
1176 /* setup the default parser configurations, as specified by configure */
1177 #ifdef MIB_COMMENT_IS_EOL_TERMINATED
1178 ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM, 1);
1179 #else /* !MIB_COMMENT_IS_EOL_TERMINATED */
1180 ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM, 0);
1181 #endif /* !MIB_COMMENT_IS_EOL_TERMINATED */
1182 }
1183
1184 void
1185 init_mib (void)
1186 {
1187 const char *prefix;
1188 char *env_var, *entry;
1189 PrefixListPtr pp = &mib_prefixes[0];
1190 char *new_mibdirs, *homepath, *cp_home;
1191
1192 if (Mib) return;
1193
1194 /* Initialise the MIB directory/ies */
1195
1196 /* we can't use the environment variable directly, because strtok
1197 will modify it. */
1198
1199 env_var = getenv("MIBDIRS");
1200 if ( env_var == NULL ) {
1201 if (confmibdir != NULL)
1202 env_var = strdup(confmibdir);
1203 else
1204 env_var = strdup(DEFAULT_MIBDIRS);
1205 } else {
1206 env_var = strdup(env_var);
1207 }
1208 if (*env_var == '+') {
1209 entry = (char *)malloc(strlen(DEFAULT_MIBDIRS)+strlen(env_var)+2);
1210 sprintf(entry, "%s%c%s", DEFAULT_MIBDIRS, ENV_SEPARATOR_CHAR, env_var+1);
1211 free(env_var);
1212 env_var = entry;
1213 }
1214
1215 /* replace $HOME in the path with the users home directory */
1216 homepath=getenv("HOME");
1217
1218 if (homepath) {
1219 while((cp_home = strstr(env_var, "$HOME"))) {
1220 new_mibdirs = (char *) malloc(strlen(env_var) - strlen("$HOME") +
1221 strlen(homepath)+1);
1222 *cp_home = 0; /* null out the spot where we stop copying */
1223 sprintf(new_mibdirs, "%s%s%s", env_var, homepath,
1224 cp_home + strlen("$HOME"));
1225 /* swap in the new value and repeat */
1226 free(env_var);
1227 env_var = new_mibdirs;
1228 }
1229 }
1230
1231 DEBUGMSGTL(("init_mib","Seen MIBDIRS: Looking in '%s' for mib dirs ...\n",env_var));
1232
1233 entry = strtok( env_var, ENV_SEPARATOR );
1234 while ( entry ) {
1235 add_mibdir(entry);
1236 entry = strtok( NULL, ENV_SEPARATOR);
1237 }
1238 free(env_var);
1239
1240 init_mib_internals();
1241
1242 /* Read in any modules or mibs requested */
1243
1244 env_var = getenv("MIBS");
1245 if ( env_var == NULL ) {
1246 if (confmibs != NULL)
1247 env_var = strdup(confmibs);
1248 else
1249 env_var = strdup(DEFAULT_MIBS);
1250 } else {
1251 env_var = strdup(env_var);
1252 }
1253 if (*env_var == '+') {
1254 entry = (char *)malloc(strlen(DEFAULT_MIBS)+strlen(env_var)+2);
1255 sprintf(entry, "%s%c%s", DEFAULT_MIBS, ENV_SEPARATOR_CHAR, env_var+1);
1256 free(env_var);
1257 env_var = entry;
1258 }
1259
1260 DEBUGMSGTL(("init_mib","Seen MIBS: Looking in '%s' for mib files ...\n",env_var));
1261 entry = strtok( env_var, ENV_SEPARATOR );
1262 while ( entry ) {
1263 if (strcasecmp(entry, DEBUG_ALWAYS_TOKEN) == 0) {
1264 read_all_mibs();
1265 }
1266 else if (strstr (entry, "/") != 0) {
1267 read_mib(entry);
1268 }
1269 else {
1270 read_module(entry);
1271 }
1272 entry = strtok( NULL, ENV_SEPARATOR);
1273 }
1274 adopt_orphans();
1275 free(env_var);
1276
1277 env_var = getenv("MIBFILES");
1278 if ( env_var != NULL ) {
1279 if (*env_var == '+') {
1280 #ifdef DEFAULT_MIBFILES
1281 entry = (char *)malloc(strlen(DEFAULT_MIBFILES)+strlen(env_var)+2);
1282 sprintf(entry, "%s%c%s", DEFAULT_MIBFILES, ENV_SEPARATOR_CHAR,
1283 env_var+1);
1284 free(env_var);
1285 env_var = entry;
1286 #else
1287 env_var = strdup(env_var+1);
1288 #endif
1289 } else {
1290 env_var = strdup(env_var);
1291 }
1292 } else {
1293 #ifdef DEFAULT_MIBFILES
1294 env_var = strdup(DEFAULT_MIBFILES);
1295 #endif
1296 }
1297
1298 if ( env_var != 0 ) {
1299 DEBUGMSGTL(("init_mib","Seen MIBFILES: Looking in '%s' for mib files ...\n",env_var));
1300 entry = strtok( env_var, ENV_SEPARATOR );
1301 while ( entry ) {
1302 read_mib(entry);
1303 entry = strtok( NULL, ENV_SEPARATOR);
1304 }
1305 free(env_var);
1306 }
1307
1308 prefix = getenv("PREFIX");
1309
1310 if (!prefix)
1311 prefix = Standard_Prefix;
1312
1313 Prefix = (char*)malloc(strlen(prefix)+2);
1314 strcpy(Prefix, prefix);
1315
1316 DEBUGMSGTL(("init_mib","Seen PREFIX: Looking in '%s' for prefix ...\n", Prefix));
1317
1318 /* remove trailing dot */
1319 env_var = &Prefix[strlen(Prefix) - 1];
1320 if (*env_var == '.') *env_var = '\0';
1321
1322 pp->str = Prefix; /* fixup first mib_prefix entry */
1323 /* now that the list of prefixes is built, save each string length. */
1324 while (pp->str) {
1325 pp->len = strlen(pp->str);
1326 pp++;
1327 }
1328
1329 if (getenv("SUFFIX"))
1330 ds_set_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY, 1);
1331
1332 Mib = tree_head; /* Backwards compatibility */
1333 }
1334
1335 void
1336 print_mib (FILE *fp)
1337 {
1338 print_subtree (fp, tree_head, 0);
1339 }
1340
1341 void
1342 print_ascii_dump (FILE *fp)
1343 {
1344 fprintf(fp, "dump DEFINITIONS ::= BEGIN\n");
1345 print_ascii_dump_tree (fp, tree_head, 0);
1346 fprintf(fp, "END\n");
1347 }
1348
1349 void
1350 set_function(struct tree *subtree)
1351 {
1352 switch(subtree->type){
1353 case TYPE_OBJID:
1354 subtree->printer = sprint_object_identifier;
1355 break;
1356 case TYPE_OCTETSTR:
1357 subtree->printer = sprint_octet_string;
1358 break;
1359 case TYPE_INTEGER:
1360 subtree->printer = sprint_integer;
1361 break;
1362 case TYPE_NETADDR:
1363 subtree->printer = sprint_networkaddress;
1364 break;
1365 case TYPE_IPADDR:
1366 subtree->printer = sprint_ipaddress;
1367 break;
1368 case TYPE_COUNTER:
1369 subtree->printer = sprint_counter;
1370 break;
1371 case TYPE_GAUGE:
1372 subtree->printer = sprint_gauge;
1373 break;
1374 case TYPE_TIMETICKS:
1375 subtree->printer = sprint_timeticks;
1376 break;
1377 case TYPE_OPAQUE:
1378 subtree->printer = sprint_opaque;
1379 break;
1380 case TYPE_NULL:
1381 subtree->printer = sprint_null;
1382 break;
1383 case TYPE_BITSTRING:
1384 subtree->printer = sprint_bitstring;
1385 break;
1386 case TYPE_NSAPADDRESS:
1387 subtree->printer = sprint_nsapaddress;
1388 break;
1389 case TYPE_COUNTER64:
1390 subtree->printer = sprint_counter64;
1391 break;
1392 case TYPE_UINTEGER:
1393 subtree->printer = sprint_uinteger;
1394 break;
1395 case TYPE_OTHER:
1396 default:
1397 subtree->printer = sprint_unknowntype;
1398 break;
1399 }
1400 }
1401
1402 /*
1403 * Read an object identifier from input string into internal OID form.
1404 * Returns 1 if successful.
1405 * If an error occurs, this function returns 0 and MAY set snmp_errno.
1406 * snmp_errno is NOT set if SET_SNMP_ERROR evaluates to nothing.
1407 * This can make multi-threaded use a tiny bit more robust.
1408 */
1409 int read_objid(const char *input,
1410 oid *output,
1411 size_t *out_len) /* number of subid's in "output" */
1412 {
1413 struct tree *root = tree_head;
1414 char buf[SPRINT_MAX_LEN];
1415 int ret;
1416
1417 if (strchr(input, ':')) {
1418 return get_node(input, output, out_len);
1419 }
1420
1421 if (*input == '.')
1422 input++;
1423 else {
1424 /* get past leading '.', append '.' to Prefix. */
1425 if (*Prefix == '.')
1426 strcpy(buf, Prefix+1);
1427 else
1428 strcpy(buf, Prefix);
1429 strcat(buf, ".");
1430 strcat(buf, input);
1431 input = buf;
1432 }
1433
1434 if (root == NULL){
1435 SET_SNMP_ERROR(SNMPERR_NOMIB);
1436 *out_len = 0;
1437 return(0);
1438 }
1439 if ((ret = parse_subtree(root, input, output, out_len)) <= 0)
1440 {
1441 int errc = (ret ? ret : SNMPERR_UNKNOWN_OBJID);
1442 SET_SNMP_ERROR(errc);
1443 return (0);
1444 }
1445 *out_len = ret;
1446
1447 return (1);
1448 }
1449
1450
1451 /*
1452 * RECURSIVE helper methods for read_objid
1453 * Returns:
1454 * < 0 the SNMPERR_ errorcode
1455 * = 0 input string is empty.
1456 * > 0 the number of sub-identifiers found in the input string.
1457 */
1458 static int
1459 parse_subtree(struct tree *subtree,
1460 const char *input,
1461 oid *output,
1462 size_t *out_len) /* number of subid's */
1463 {
1464 char buf[SPRINT_MAX_LEN], *to = buf, *cp;
1465 u_long subid = 0;
1466 struct tree *tp;
1467 int ret, len;
1468
1469 /*
1470 * No empty strings. Can happen if there is a trailing '.' or two '.'s
1471 * in a row, i.e. "..".
1472 */
1473 if ((*input == '\0') ||
1474 (*input == '.'))
1475 return (0);
1476
1477 if (*input == '"' || *input == '\'') {
1478 /*
1479 * This is a string that should be converted into an OID
1480 * Note: assumes variable length index is required, and prepends
1481 * the string length.
1482 */
1483 if ((cp = strchr(input+1, *input)) == NULL) {
1484 /* error. Should be a matching quote somewhere. */
1485 return (0);
1486 }
1487
1488 /* is there room enough for the string in question plus its length */
1489 len = cp-input-1;
1490 if ((int)*out_len <= len){
1491 return (SNMPERR_LONG_OID);
1492 }
1493
1494 /* copy everything in */
1495 if (*input++ == '"') {
1496 /* add the length for " quoted objects */
1497 *output++ = len++;
1498 }
1499
1500 *out_len -= len;
1501 while (input < cp) {
1502 *output++ = *input++;
1503 }
1504
1505 /* Now, we assume that nothing beyond this exists in the parse
1506 tree, which should always be true (or else we have a really wacked
1507 mib designer somewhere. */
1508 input = cp + 1; /* past the quote */
1509
1510 if (*input != '.')
1511 return (len);
1512
1513 ret = parse_subtree(NULL, ++input, output, out_len);
1514 if (ret <= 0)
1515 return (ret);
1516 return ret+len;
1517
1518 } else if (isdigit(*input)) {
1519 /*
1520 * Read the number, then try to find it in the subtree.
1521 */
1522 while (isdigit(*input)) {
1523 *to++ = *input;
1524 subid *= 10;
1525 subid += *input++ - '0';
1526 }
1527 if (*input != '.' && *input != 0) {
1528 while (*input != 0 && *input != '.') *to++ = *input++;
1529 *to = 0;
1530 snmp_set_detail(buf);
1531 return SNMPERR_BAD_SUBID;
1532 }
1533 *to = '\0';
1534
1535 for (tp = subtree; tp; tp = tp->next_peer) {
1536 if (tp->subid == subid)
1537 goto found;
1538 }
1539 }
1540 else {
1541 /*
1542 * Read the name into a buffer.
1543 */
1544 while ((*input != '\0') &&
1545 (*input != '.')) {
1546 *to++ = *input++;
1547 }
1548 *to = '\0';
1549
1550 /*
1551 * Find the name in the subtree;
1552 */
1553 for (tp = subtree; tp; tp = tp->next_peer) {
1554 if (strcasecmp(tp->label, buf) == 0) {
1555 subid = tp->subid;
1556 goto found;
1557 }
1558 }
1559
1560 /*
1561 * If we didn't find the entry, punt...
1562 */
1563 if (tp == NULL) {
1564 snmp_set_detail(buf);
1565 return (SNMPERR_BAD_SUBID);
1566 }
1567 }
1568
1569 found:
1570 if(subid > (u_long)MAX_SUBID){
1571 snmp_set_detail(buf);
1572 return (SNMPERR_MAX_SUBID);
1573 }
1574
1575 if ((int)*out_len <= 0){
1576 return (SNMPERR_LONG_OID);
1577 }
1578
1579 (*out_len)--;
1580 *output++ = subid;
1581
1582 if (*input != '.')
1583 return (1);
1584
1585 ret = parse_subtree(tp ? tp->child_list : NULL,
1586 ++input, output, out_len);
1587 if (ret <= 0)
1588 return (ret);
1589 return ret+1;
1590 }
1591
1592 static struct tree *
1593 _sprint_objid(char *buf,
1594 oid *objid,
1595 size_t objidlen) /* number of subidentifiers */
1596 {
1597 char tempbuf[SPRINT_MAX_LEN], *cp;
1598 struct tree *subtree = tree_head;
1599 char *midpoint = 0;
1600
1601 *tempbuf = '.'; /* this is a fully qualified name */
1602 subtree = _get_symbol(objid, objidlen, subtree, tempbuf + 1, 0, &midpoint);
1603 if (ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_OIDS)) {
1604 cp = tempbuf;
1605 } else if (ds_get_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY)){
1606 for(cp = tempbuf; *cp; cp++)
1607 ;
1608 if (midpoint)
1609 cp = midpoint-2; /* beyond the '.' */
1610 else {
1611 while(cp >= tempbuf){
1612 if (isalpha(*cp))
1613 break;
1614 cp--;
1615 }
1616 }
1617 while(cp >= tempbuf){
1618 if (*cp == '.')
1619 break;
1620 cp--;
1621 }
1622 cp++;
1623 if (ds_get_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY) == 2 && cp > tempbuf) {
1624 char modbuf[256];
1625 char *mod = module_name(subtree->modid, modbuf);
1626 size_t len = strlen(mod);
1627 if ((int)len+1 >= cp-tempbuf) {
1628 memmove(tempbuf+len+2, cp, strlen(cp)+1);
1629 cp = tempbuf+len+2;
1630 }
1631 cp -= len+2;
1632 memcpy(cp, mod, len);
1633 cp[len] = ':';
1634 cp[len+1] = ':';
1635 }
1636 }
1637 else if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_FULL_OID)) {
1638 PrefixListPtr pp = &mib_prefixes[0];
1639 int ii;
1640 size_t ilen, tlen;
1641 const char *testcp;
1642 cp = tempbuf; tlen = strlen(tempbuf);
1643 ii = 0;
1644 while (pp->str) {
1645 ilen = pp->len; testcp = pp->str;
1646 if ((tlen > ilen) && !memcmp(tempbuf, testcp, ilen)) {
1647 cp += (ilen + 1);
1648 break;
1649 }
1650 pp++;
1651 }
1652 }
1653 else cp = tempbuf;
1654 strcpy(buf, cp);
1655 return subtree;
1656 }
1657
1658 char * sprint_objid(char *buf, oid *objid, size_t objidlen)
1659 {
1660 _sprint_objid(buf,objid,objidlen);
1661 return buf;
1662 }
1663
1664 void
1665 print_objid(oid *objid,
1666 size_t objidlen) /* number of subidentifiers */
1667 {
1668 fprint_objid(stdout, objid, objidlen);
1669 }
1670
1671 void
1672 fprint_objid(FILE *f,
1673 oid *objid,
1674 size_t objidlen) /* number of subidentifiers */
1675 {
1676 char buf[SPRINT_MAX_LEN];
1677
1678 _sprint_objid(buf, objid, objidlen);
1679 fprintf(f, "%s\n", buf);
1680 }
1681
1682 void
1683 sprint_variable(char *buf,
1684 oid *objid,
1685 size_t objidlen,
1686 struct variable_list *variable)
1687 {
1688 struct tree *subtree;
1689
1690 subtree = _sprint_objid(buf, objid, objidlen);
1691 buf += strlen(buf);
1692 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT))
1693 strcat(buf, " ");
1694 else
1695 strcat(buf, " = ");
1696 buf += strlen(buf);
1697
1698 if (variable->type == SNMP_NOSUCHOBJECT)
1699 strcpy(buf, "No Such Object available on this agent");
1700 else if (variable->type == SNMP_NOSUCHINSTANCE)
1701 strcpy(buf, "No Such Instance currently exists");
1702 else if (variable->type == SNMP_ENDOFMIBVIEW)
1703 strcpy(buf, "No more variables left in this MIB View");
1704 else if (subtree) {
1705 if (subtree->printer)
1706 (*subtree->printer)(buf, variable, subtree->enums, subtree->hint, subtree->units);
1707 else {
1708 sprint_by_type(buf, variable, subtree->enums, subtree->hint, subtree->units);
1709 }
1710 }
1711 else { /* handle rare case where tree is empty */
1712 sprint_by_type(buf, variable, 0, 0, 0);
1713 }
1714 }
1715
1716 void
1717 print_variable(oid *objid,
1718 size_t objidlen,
1719 struct variable_list *variable)
1720 {
1721 fprint_variable(stdout, objid, objidlen, variable);
1722 }
1723
1724 void
1725 fprint_variable(FILE *f,
1726 oid *objid,
1727 size_t objidlen,
1728 struct variable_list *variable)
1729 {
1730 char buf[SPRINT_MAX_LEN];
1731
1732 sprint_variable(buf, objid, objidlen, variable);
1733 fprintf(f, "%s\n", buf);
1734 }
1735
1736 void
1737 sprint_value(char *buf,
1738 oid *objid,
1739 size_t objidlen,
1740 struct variable_list *variable)
1741 {
1742 char tempbuf[SPRINT_MAX_LEN];
1743 struct tree *subtree = tree_head;
1744
1745 if (variable->type == SNMP_NOSUCHOBJECT)
1746 sprintf(buf, "No Such Object available on this agent");
1747 else if (variable->type == SNMP_NOSUCHINSTANCE)
1748 sprintf(buf, "No Such Instance currently exists");
1749 else if (variable->type == SNMP_ENDOFMIBVIEW)
1750 sprintf(buf, "No more variables left in this MIB View");
1751 else {
1752 subtree = get_symbol(objid, objidlen, subtree, tempbuf);
1753 if (subtree->printer)
1754 (*subtree->printer)(buf, variable, subtree->enums, subtree->hint, subtree->units);
1755 else {
1756 sprint_by_type(buf, variable, subtree->enums, subtree->hint, subtree->units);
1757 }
1758 }
1759 }
1760
1761 void
1762 print_value(oid *objid,
1763 size_t objidlen,
1764 struct variable_list *variable)
1765 {
1766 fprint_value(stdout, objid, objidlen, variable);
1767 }
1768
1769 void
1770 fprint_value(FILE *f,
1771 oid *objid,
1772 size_t objidlen,
1773 struct variable_list *variable)
1774 {
1775 char tempbuf[SPRINT_MAX_LEN];
1776
1777 sprint_value(tempbuf, objid, objidlen, variable);
1778 fprintf(f, "%s\n", tempbuf);
1779 }
1780
1781
1782 /*
1783 * Append a quoted printable string to buffer "buf"
1784 * that represents a range of sub-identifiers "objid".
1785 *
1786 * Display '.' for all non-printable sub-identifiers.
1787 * If successful, "buf" points past the appended string.
1788 */
1789 char *
1790 dump_oid_to_string(oid *objid,
1791 size_t objidlen,
1792 char *buf,
1793 char quotechar)
1794 {
1795 if (buf)
1796 { int ii, alen;
1797 char *scp;
1798 char *cp = buf + (strlen(buf));
1799 scp = cp;
1800 for (ii= 0, alen = 0; ii < (int)objidlen; ii++)
1801 {
1802 oid tst = objid[ii];
1803 if ((tst > 254) || (!isprint(tst)))
1804 tst = (oid)'.';
1805
1806 if (alen == 0) *cp++ = quotechar;
1807 *cp++ = (char)tst;
1808 alen++;
1809 }
1810 if (alen) *cp++ = quotechar;
1811 *cp = '\0';
1812 buf = cp;
1813 }
1814
1815 return buf;
1816 }
1817
1818 struct tree *
1819 _get_symbol(oid *objid,
1820 size_t objidlen,
1821 struct tree *subtree,
1822 char *buf,
1823 struct index_list *in_dices,
1824 char **end_of_known)
1825 {
1826 struct tree *return_tree = NULL;
1827
1828 if (!objid || !buf)
1829 return NULL;
1830
1831 for(; subtree; subtree = subtree->next_peer){
1832 if (*objid == subtree->subid){
1833 if (subtree->indexes)
1834 in_dices = subtree->indexes;
1835 if (!strncmp( subtree->label, ANON, ANON_LEN) ||
1836 ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_OIDS))
1837 sprintf(buf, "%lu", subtree->subid);
1838 else
1839 strcpy(buf, subtree->label);
1840 goto found;
1841 }
1842 }
1843
1844 if (end_of_known)
1845 *end_of_known = buf;
1846
1847 /* subtree not found */
1848
1849 while (in_dices && (objidlen > 0) &&
1850 !ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_OIDS) &&
1851 !ds_get_boolean(DS_LIBRARY_ID,DS_LIB_DONT_BREAKDOWN_OIDS)) {
1852 size_t numids;
1853 struct tree *tp;
1854 tp = find_tree_node(in_dices->ilabel, -1);
1855 if (0 == tp) {
1856 /* ack. Can't find an index in the mib tree. bail */
1857 goto finish_it;
1858 }
1859 switch(tp->type) {
1860 case TYPE_OCTETSTR:
1861 if (in_dices->isimplied) {
1862 numids = objidlen;
1863 buf = dump_oid_to_string(objid, numids, buf, '\'');
1864 } else {
1865 numids = (size_t)*objid+1;
1866 if (numids > objidlen)
1867 goto finish_it;
1868 if (numids == 1) {
1869 *buf++ = '"'; *buf++ = '"';
1870 }
1871 else
1872 buf = dump_oid_to_string(objid+1, numids-1, buf, '"');
1873 }
1874 objid += (numids);
1875 objidlen -= (numids);
1876 *buf++ = '.';
1877 *buf = '\0';
1878 break;
1879 case TYPE_INTEGER:
1880 sprintf(buf, "%lu.", *objid++);
1881 while(*buf)
1882 buf++;
1883 objidlen--;
1884 break;
1885 case TYPE_OBJID:
1886 if (in_dices->isimplied) {
1887 numids = objidlen;
1888 } else {
1889 numids = (size_t)*objid+1;
1890 }
1891 if ( numids > objidlen)
1892 goto finish_it;
1893 _get_symbol(objid, numids, NULL, buf, NULL, NULL);
1894 objid += (numids);
1895 objidlen -= (numids);
1896 buf += strlen(buf);
1897 *buf++ = '.';
1898 *buf = '\0';
1899 break;
1900 default:
1901 goto finish_it;
1902 break;
1903 }
1904 in_dices = in_dices->next;
1905 }
1906
1907 finish_it:
1908
1909 while(objidlen-- > 0){ /* output rest of name, uninterpreted */
1910 sprintf(buf, "%lu.", *objid++);
1911 while(*buf)
1912 buf++;
1913 }
1914 *(buf - 1) = '\0'; /* remove trailing dot */
1915 return NULL;
1916
1917 found:
1918 if (objidlen > 1){
1919 while(*buf)
1920 buf++;
1921 *buf++ = '.';
1922 *buf = '\0';
1923
1924 return_tree = _get_symbol(objid + 1, objidlen - 1, subtree->child_list,
1925 buf, in_dices, end_of_known);
1926 }
1927 if (return_tree != NULL)
1928 return return_tree;
1929 else
1930 return subtree;
1931 }
1932
1933 struct tree *
1934 get_symbol(oid *objid,
1935 size_t objidlen,
1936 struct tree *subtree,
1937 char *buf)
1938 {
1939 return _get_symbol(objid,objidlen,subtree,buf,0,0);
1940 }
1941
1942 /*
1943 * Clone of get_symbol that doesn't take a buffer argument
1944 */
1945 struct tree *
1946 get_tree(oid *objid,
1947 size_t objidlen,
1948 struct tree *subtree)
1949 {
1950 struct tree *return_tree = NULL;
1951
1952 for(; subtree; subtree = subtree->next_peer){
1953 if (*objid == subtree->subid)
1954 goto found;
1955 }
1956
1957 return NULL;
1958
1959 found:
1960 if (objidlen > 1)
1961 return_tree = get_tree(objid + 1, objidlen - 1, subtree->child_list);
1962 if (return_tree != NULL)
1963 return return_tree;
1964 else
1965 return subtree;
1966 }
1967
1968 void
1969 print_description(oid *objid,
1970 size_t objidlen) /* number of subidentifiers */
1971 {
1972 fprint_description(stdout, objid, objidlen);
1973 }
1974
1975 void
1976 fprint_description(FILE *f,
1977 oid *objid,
1978 size_t objidlen) /* number of subidentifiers */
1979 {
1980 struct tree *tp = get_tree(objid, objidlen, tree_head);
1981 struct tree *subtree = tree_head;
1982 fprintf(f, "%s OBJECT-TYPE\n", tp->label);
1983 print_tree_node(f, tp);
1984 fprintf(f, "::= {");
1985 while (objidlen > 1) {
1986 for(; subtree; subtree = subtree->next_peer){
1987 if (*objid == subtree->subid){
1988 if (strncmp( subtree->label, ANON, ANON_LEN))
1989 fprintf(f, " %s(%lu)", subtree->label, subtree->subid);
1990 else
1991 fprintf(f, " %lu", subtree->subid);
1992 break;
1993 }
1994 }
1995 if (subtree == 0) break;
1996 objid++; objidlen--; subtree = subtree->child_list;
1997 if (subtree == 0) break;
1998 }
1999 fprintf(f, " %lu }\n", *objid);
2000 }
2001
2002 void
2003 print_tree_node(FILE *f,
2004 struct tree *tp)
2005 {
2006 const char *cp;
2007 char str[MAXTOKEN];
2008 int i, prevmod;
2009 if (tp) {
2010 module_name(tp->modid, str);
2011 fprintf(f, " -- FROM\t%s", str);
2012 for (i = 1, prevmod = tp->modid; i < tp->number_modules; i++) {
2013 if (prevmod != tp->module_list[i]) {
2014 module_name(tp->module_list[i], str);
2015 fprintf(f, ", %s", str);
2016 }
2017 prevmod = tp->module_list[i];
2018 }
2019 fprintf(f, "\n");
2020 if (tp->tc_index != -1) {
2021 fprintf(f, " -- TEXTUAL CONVENTION %s\n", get_tc_descriptor(tp->tc_index));
2022 }
2023 switch (tp->type) {
2024 case TYPE_OBJID: cp = "OBJECT IDENTIFIER"; break;
2025 case TYPE_OCTETSTR: cp = "OCTET STRING"; break;
2026 case TYPE_INTEGER: cp = "INTEGER"; break;
2027 case TYPE_NETADDR: cp = "NetworkAddress"; break;
2028 case TYPE_IPADDR: cp = "IpAddress"; break;
2029 case TYPE_COUNTER: cp = "Counter"; break;
2030 case TYPE_GAUGE: cp = "Gauge"; break;
2031 case TYPE_TIMETICKS: cp = "TimeTicks"; break;
2032 case TYPE_OPAQUE: cp = "Opaque"; break;
2033 case TYPE_NULL: cp = "NULL"; break;
2034 case TYPE_COUNTER64: cp = "Counter64"; break;
2035 case TYPE_BITSTRING: cp = "BIT STRING"; break;
2036 case TYPE_NSAPADDRESS: cp = "NsapAddress"; break;
2037 case TYPE_UINTEGER: cp = "UInteger32"; break;
2038 case 0: cp = NULL; break;
2039 default: sprintf(str,"type_%d", tp->type); cp = str;
2040 }
2041 #if SNMP_TESTING_CODE
2042 if (!cp && (tp->ranges || tp->enums)) { /* ranges without type ? */
2043 sprintf(str,"?0 with %s %s ?",
2044 tp->ranges ? "Range" : "",
2045 tp->enums ? "Enum" : "");
2046 cp = str;
2047 }
2048 #endif /* SNMP_TESTING_CODE */
2049 if (cp) fprintf(f, " SYNTAX\t%s", cp);
2050 if (tp->ranges) {
2051 struct range_list *rp = tp->ranges;
2052 int first = 1;
2053 fprintf(f, " (");
2054 while (rp) {
2055 if (first) first = 0;
2056 else fprintf(f, " | ");
2057 if (rp->low == rp->high) fprintf(f, "%d", rp->low);
2058 else fprintf(f, "%d..%d", rp->low, rp->high);
2059 rp = rp->next;
2060 }
2061 fprintf(f, ") ");
2062 }
2063 if (tp->enums) {
2064 struct enum_list *ep = tp->enums;
2065 int first = 1;
2066 fprintf(f," { ");
2067 while (ep) {
2068 if (first) first = 0;
2069 else fprintf(f, ", ");
2070 fprintf(f, "%s(%d)", ep->label, ep->value);
2071 ep = ep->next;
2072 }
2073 fprintf(f," } ");
2074 }
2075 if (cp) fprintf(f, "\n");
2076 if (tp->hint) fprintf(f, " DISPLAY-HINT\t\"%s\"\n", tp->hint);
2077 if (tp->units) fprintf(f, " UNITS\t\"%s\"\n", tp->units);
2078 switch (tp->access) {
2079 case MIB_ACCESS_READONLY: cp = "read-only"; break;
2080 case MIB_ACCESS_READWRITE: cp = "read-write"; break;
2081 case MIB_ACCESS_WRITEONLY: cp = "write-only"; break;
2082 case MIB_ACCESS_NOACCESS: cp = "not-accessible"; break;
2083 case MIB_ACCESS_NOTIFY: cp = "accessible-for-notify"; break;
2084 case MIB_ACCESS_CREATE: cp = "read-create"; break;
2085 case 0: cp = NULL; break;
2086 default: sprintf(str,"access_%d", tp->access); cp = str;
2087 }
2088 if (cp) fprintf(f, " MAX-ACCESS\t%s\n", cp);
2089 switch (tp->status) {
2090 case MIB_STATUS_MANDATORY: cp = "mandatory"; break;
2091 case MIB_STATUS_OPTIONAL: cp = "optional"; break;
2092 case MIB_STATUS_OBSOLETE: cp = "obsolete"; break;
2093 case MIB_STATUS_DEPRECATED: cp = "deprecated"; break;
2094 case MIB_STATUS_CURRENT: cp = "current"; break;
2095 case 0: cp = NULL; break;
2096 default: sprintf(str,"status_%d", tp->status); cp = str;
2097 }
2098 #if SNMP_TESTING_CODE
2099 if (!cp && (tp->indexes)) { /* index without status ? */
2100 sprintf(str,"?0 with %s ?",
2101 tp->indexes ? "Index" : "");
2102 cp = str;
2103 }
2104 #endif /* SNMP_TESTING_CODE */
2105 if (cp) fprintf(f, " STATUS\t%s\n", cp);
2106 if (tp->indexes) {
2107 struct index_list *ip = tp->indexes;
2108 int first=1;
2109 fprintf(f, " INDEXES\t");
2110 fprintf(f," { ");
2111 while (ip) {
2112 if (first) first = 0;
2113 else fprintf(f, ", ");
2114 if (ip->isimplied)
2115 fprintf(f, "IMPLIED ");
2116 fprintf(f, "%s", ip->ilabel);
2117 ip = ip->next;
2118 }
2119 fprintf(f," }\n");
2120 }
2121 if (tp->description) fprintf(f, " DESCRIPTION\t\"%s\"\n", tp->description);
2122 }
2123 else
2124 fprintf(f, "No description\n");
2125 }
2126
2127 int
2128 get_module_node(const char *fname,
2129 const char *module,
2130 oid *objid,
2131 size_t *objidlen)
2132 {
2133 int modid, rc = 0;
2134 struct tree *tp;
2135 char *name, *cp;
2136
2137 if ( !strcmp(module, "ANY") )
2138 modid = -1;
2139 else {
2140 read_module(module);
2141 modid = which_module( module );
2142 if (modid == -1) return 0;
2143 }
2144
2145 /* Isolate the first component of the name ... */
2146 name = strdup(fname);
2147 cp = strchr( name, '.' );
2148 if ( cp != NULL ) {
2149 *cp = '\0';
2150 cp++;
2151 }
2152 /* ... and locate it in the tree. */
2153 tp = find_tree_node(name, modid);
2154 if (tp){
2155 size_t maxlen = *objidlen;
2156
2157 /* Set the first element of the object ID */
2158 if (node_to_oid(tp, objid, objidlen)) {
2159 rc = 1;
2160
2161 /* If the name requested was more than one element,
2162 tag on the rest of the components */
2163 if (cp != NULL)
2164 rc = _add_strings_to_oid(tp, cp, objid, objidlen, maxlen);
2165 }
2166 }
2167
2168 free(name);
2169 return (rc);
2170 }
2171
2172
2173 /*
2174 * Populate object identifier from a node in the MIB hierarchy.
2175 * Build up the object ID, working backwards,
2176 * starting from the end of the objid buffer.
2177 * When the top of the MIB tree is reached, adjust the buffer.
2178 *
2179 * The buffer length is set to the number of subidentifiers
2180 * for the object identifier associated with the MIB node.
2181 * Returns the number of subidentifiers copied.
2182 *
2183 * If 0 is returned, the objid buffer is too small,
2184 * and the buffer contents are indeterminate.
2185 * The buffer length can be used to create a larger buffer.
2186 */
2187 int
2188 node_to_oid(struct tree *tp, oid *objid, size_t *objidlen)
2189 {
2190 int numids, lenids;
2191 oid *op;
2192
2193 if (!tp || !objid || !objidlen)
2194 return 0;
2195
2196 lenids = (int)*objidlen;
2197 op = objid + lenids; /* points after the last element */
2198
2199 for(numids = 0; tp; tp = tp->parent, numids++)
2200 {
2201 if (numids >= lenids) continue;
2202 --op;
2203 *op = tp->subid;
2204 }
2205
2206 *objidlen = (size_t)numids;
2207 if (numids > lenids) {
2208 return 0;
2209 }
2210
2211 if (numids < lenids)
2212 memmove(objid, op, numids * sizeof(oid));
2213
2214 return (numids);
2215 }
2216
2217 static int
2218 _add_strings_to_oid(struct tree *tp, char *cp,
2219 oid *objid, size_t *objidlen,
2220 size_t maxlen)
2221 {
2222 int subid;
2223 struct tree *tp2 = NULL;
2224 char *cp2 = NULL;
2225 char doingquote = 0;
2226
2227 while ( cp != NULL ) {
2228 cp2 = strchr( cp, '.' ); /* Isolate the next entry */
2229 if ( cp2 != NULL ) {
2230 *cp2 = '\0';
2231 cp2++;
2232 }
2233
2234 if ( *cp == '"' || *cp == '\'') { /* Is it the beggining
2235 of a quoted string */
2236 doingquote = *cp++;
2237 /* insert length if requested */
2238 if (doingquote == '"') {
2239 if (*objidlen >= maxlen)
2240 return 0;
2241 objid[ *objidlen ] = (strchr(cp,doingquote) - cp);
2242 (*objidlen)++;
2243 }
2244
2245 while(*cp != doingquote) {
2246 if (*objidlen >= maxlen)
2247 return 0;
2248 objid[ *objidlen ] = *cp++;
2249 (*objidlen)++;
2250 }
2251
2252 tp = NULL; /* must be pure numeric from here, right? */
2253 cp = cp2;
2254 continue;
2255 }
2256
2257 /* Is it numeric ? */
2258 if ( isdigit( *cp ) )
2259 subid=(strtol(cp,0,0));
2260 else
2261 subid = -1;
2262
2263 /* Search for the appropriate child */
2264 if ( tp != NULL )
2265 tp2 = tp->child_list;
2266 while ( tp2 != NULL ) {
2267 if (( (int)tp2->subid == subid ) ||
2268 ( !strcasecmp( tp2->label, cp ))) {
2269 if (*objidlen >= maxlen)
2270 return 0;
2271 objid[ *objidlen ] = tp2->subid;
2272 (*objidlen)++;
2273 tp = tp2;
2274 break;
2275 }
2276 tp2 = tp2->next_peer;
2277 }
2278 if ( tp2 == NULL ) {
2279 if ( subid == -1 ) {
2280 return 0;
2281 }
2282 /* pure numeric from now on */
2283 if (*objidlen >= maxlen)
2284 return 0;
2285 objid[ *objidlen ] = subid;
2286 (*objidlen)++;
2287 tp = NULL;
2288 }
2289 cp = cp2;
2290 }
2291
2292 return 1;
2293 }
2294
2295
2296 /*
2297 * see comments on find_best_tree_node for usage after first time.
2298 */
2299 int
2300 get_wild_node(const char *name,
2301 oid *objid,
2302 size_t *objidlen)
2303 {
2304 struct tree *tp = find_best_tree_node(name, tree_head, NULL);
2305 if (!tp)
2306 return 0;
2307 return get_node(tp->label, objid, objidlen);
2308 }
2309
2310 int
2311 get_node(const char *name,
2312 oid *objid,
2313 size_t *objidlen)
2314 {
2315 char *cp;
2316 int res;
2317
2318 if (( cp=strchr(name, ':')) == NULL )
2319 res = get_module_node( name, "ANY", objid, objidlen );
2320 else {
2321 char *module;
2322 /*
2323 * requested name is of the form
2324 * "module:subidentifier"
2325 */
2326 module = (char *)malloc((size_t)(cp-name+1));
2327 memcpy(module,name,(size_t)(cp-name));
2328 module[cp-name] = 0;
2329 cp++; /* cp now point to the subidentifier */
2330 if (*cp == ':') cp++;
2331
2332 /* 'cp' and 'name' *do* go that way round! */
2333 res = get_module_node( cp, module, objid, objidlen );
2334 free(module);
2335 }
2336 if (res == 0) {
2337 SET_SNMP_ERROR(SNMPERR_UNKNOWN_OBJID);
2338 }
2339
2340 return res;
2341 }
2342
2343 #ifdef testing
2344
2345 main(int argc, char* argv[])
2346 {
2347 oid objid[MAX_OID_LEN];
2348 int objidlen = MAX_OID_LEN;
2349 int count;
2350 struct variable_list variable;
2351
2352 init_mib();
2353 if (argc < 2)
2354 print_subtree(stdout, tree_head, 0);
2355 variable.type = ASN_INTEGER;
2356 variable.val.integer = 3;
2357 variable.val_len = 4;
2358 for (argc--; argc; argc--, argv++) {
2359 objidlen = MAX_OID_LEN;
2360 printf("read_objid(%s) = %d\n",
2361 argv[1], read_objid(argv[1], objid, &objidlen));
2362 for(count = 0; count < objidlen; count++)
2363 printf("%d.", objid[count]);
2364 printf("\n");
2365 print_variable(objid, objidlen, &variable);
2366 }
2367 }
2368
2369 #endif /* testing */
2370
2371 /* initialize: no peers included in the report. */
2372 void clear_tree_flags(register struct tree *tp)
2373 {
2374 for (; tp; tp = tp->next_peer)
2375 {
2376 tp->reported = 0;
2377 if (tp->child_list)
2378 clear_tree_flags(tp->child_list); /*RECURSE*/
2379 }
2380 }
2381
2382 /*
2383 * Update: 1998-07-17 <jhy@gsu.edu>
2384 * Added print_oid_report* functions.
2385 */
2386 static int print_subtree_oid_report_labeledoid = 0;
2387 static int print_subtree_oid_report_oid = 0;
2388 static int print_subtree_oid_report_symbolic = 0;
2389 static int print_subtree_oid_report_suffix = 0;
2390
2391 /* These methods recurse. */
2392 static void print_parent_labeledoid(FILE *, struct tree *);
2393 static void print_parent_oid(FILE *, struct tree *);
2394 static void print_parent_label(FILE *, struct tree *);
2395 static void print_subtree_oid_report(FILE *, struct tree *, int);
2396
2397
2398 void
2399 print_oid_report (FILE *fp)
2400 {
2401 struct tree *tp;
2402 clear_tree_flags(tree_head);
2403 for (tp = tree_head ; tp ; tp=tp->next_peer)
2404 print_subtree_oid_report (fp, tp, 0);
2405 }
2406
2407 void
2408 print_oid_report_enable_labeledoid (void)
2409 {
2410 print_subtree_oid_report_labeledoid = 1;
2411 }
2412
2413 void
2414 print_oid_report_enable_oid (void)
2415 {
2416 print_subtree_oid_report_oid = 1;
2417 }
2418
2419 void
2420 print_oid_report_enable_suffix (void)
2421 {
2422 print_subtree_oid_report_suffix = 1;
2423 }
2424
2425 void
2426 print_oid_report_enable_symbolic (void)
2427 {
2428 print_subtree_oid_report_symbolic = 1;
2429 }
2430
2431 /*
2432 * helper methods for print_subtree_oid_report()
2433 * each one traverses back up the node tree
2434 * until there is no parent. Then, the label combination
2435 * is output, such that the parent is displayed first.
2436 *
2437 * Warning: these methods are all recursive.
2438 */
2439
2440 static void
2441 print_parent_labeledoid(FILE *f,
2442 struct tree *tp)
2443 {
2444 if(tp)
2445 {
2446 if(tp->parent)
2447 {
2448 print_parent_labeledoid(f, tp->parent); /*RECURSE*/
2449 }
2450 fprintf(f, ".%s(%lu)", tp->label, tp->subid);
2451 }
2452 }
2453
2454 static void
2455 print_parent_oid(FILE *f,
2456 struct tree *tp)
2457 {
2458 if(tp)
2459 {
2460 if(tp->parent)
2461 {
2462 print_parent_oid(f, tp->parent); /*RECURSE*/
2463 }
2464 fprintf(f, ".%lu", tp->subid);
2465 }
2466 }
2467
2468 static void
2469 print_parent_label(FILE *f,
2470 struct tree *tp)
2471 {
2472 if(tp)
2473 {
2474 if(tp->parent)
2475 {
2476 print_parent_label(f, tp->parent); /*RECURSE*/
2477 }
2478 fprintf(f, ".%s", tp->label);
2479 }
2480 }
2481
2482 /*
2483 * print_subtree_oid_report():
2484 *
2485 * This methods generates variations on the original print_subtree() report.
2486 * Traverse the tree depth first, from least to greatest sub-identifier.
2487 * Warning: this methods recurses and calls methods that recurse.
2488 */
2489
2490 static void
2491 print_subtree_oid_report(FILE *f,
2492 struct tree *tree,
2493 int count)
2494 {
2495 struct tree *tp;
2496
2497 count++;
2498
2499 /* sanity check */
2500 if(!tree)
2501 {
2502 return;
2503 }
2504
2505 /*
2506 * find the not reported peer with the lowest sub-identifier.
2507 * if no more, break the loop and cleanup.
2508 * set "reported" flag, and create report for this peer.
2509 * recurse using the children of this peer, if any.
2510 */
2511 while (1)
2512 {
2513 register struct tree *ntp;
2514
2515 tp = 0;
2516 for (ntp = tree->child_list; ntp; ntp = ntp->next_peer)
2517 {
2518 if (ntp->reported) continue;
2519
2520 if (!tp || (tp->subid > ntp->subid))
2521 tp = ntp;
2522 }
2523 if (!tp) break;
2524
2525 tp->reported = 1;
2526
2527 if(print_subtree_oid_report_labeledoid)
2528 {
2529 print_parent_labeledoid(f, tp);
2530 fprintf(f, "\n");
2531 }
2532 if(print_subtree_oid_report_oid)
2533 {
2534 print_parent_oid(f, tp);
2535 fprintf(f, "\n");
2536 }
2537 if(print_subtree_oid_report_symbolic)
2538 {
2539 print_parent_label(f, tp);
2540 fprintf(f, "\n");
2541 }
2542 if(print_subtree_oid_report_suffix)
2543 {
2544 int i;
2545 for(i = 0; i < count; i++)
2546 fprintf(f, " ");
2547 fprintf(f, "%s(%ld) type=%d", tp->label, tp->subid, tp->type);
2548 if (tp->tc_index != -1) fprintf(f, " tc=%d", tp->tc_index);
2549 if (tp->hint) fprintf(f, " hint=%s", tp->hint);
2550 if (tp->units) fprintf(f, " units=%s", tp->units);
2551
2552 fprintf(f, "\n");
2553 }
2554 print_subtree_oid_report(f, tp, count); /*RECURSE*/
2555 }
2556 }
2557
2558
2559 /*
2560 * Convert timeticks to hours, minutes, seconds string.
2561 * CMU compatible does not show centiseconds.
2562 */
2563 char *uptime_string(u_long timeticks, char *buf)
2564 {
2565 char tbuf[64];
2566 char * cp;
2567 uptimeString(timeticks, tbuf);
2568 cp = strrchr(tbuf, '.');
2569 #ifdef CMU_COMPATIBLE
2570 if (cp) *cp = '\0';
2571 #endif
2572 strcpy(buf, tbuf);
2573 return buf;
2574 }
2575
2576 #ifdef CMU_COMPATIBLE
2577
2578 int mib_TxtToOid(char *Buf, oid **OidP, size_t *LenP)
2579 {
2580 return read_objid(Buf, *OidP, LenP);
2581 }
2582
2583 int mib_OidToTxt(oid *O, size_t OidLen, char *Buf, size_t BufLen)
2584 {
2585 _sprint_objid(Buf, O, OidLen);
2586 return 1;
2587 }
2588
2589 #endif /* CMU_COMPATIBLE */