OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [snmp/] [lib/] [v2_0/] [src/] [mib.c] - Blame information for rev 174

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.