~ubuntu-branches/ubuntu/trusty/net-snmp/trusty

« back to all changes in this revision

Viewing changes to snmplib/mib.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * mib.c
 
3
 *
 
4
 * $Id: mib.c,v 5.47.2.9 2004/02/17 13:54:52 slif Exp $
 
5
 *
 
6
 * Update: 1998-07-17 <jhy@gsu.edu>
 
7
 * Added print_oid_report* functions.
 
8
 *
 
9
 */
 
10
/* Portions of this file are subject to the following copyrights.  See
 
11
 * the Net-SNMP's COPYING file for more details and other copyrights
 
12
 * that may apply:
 
13
 */
 
14
/**********************************************************************
 
15
        Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
 
16
 
 
17
                      All Rights Reserved
 
18
 
 
19
Permission to use, copy, modify, and distribute this software and its
 
20
documentation for any purpose and without fee is hereby granted,
 
21
provided that the above copyright notice appear in all copies and that
 
22
both that copyright notice and this permission notice appear in
 
23
supporting documentation, and that the name of CMU not be
 
24
used in advertising or publicity pertaining to distribution of the
 
25
software without specific, written prior permission.
 
26
 
 
27
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
28
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
29
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
30
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
31
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
32
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
33
SOFTWARE.
 
34
******************************************************************/
 
35
/*
 
36
 * Copyright ļæ½ 2003 Sun Microsystems, Inc. All rights reserved.
 
37
 * Use is subject to license terms specified in the COPYING file
 
38
 * distributed with the Net-SNMP package.
 
39
 */
 
40
#include <net-snmp/net-snmp-config.h>
 
41
 
 
42
#include <stdio.h>
 
43
#include <ctype.h>
 
44
#include <sys/types.h>
 
45
#if HAVE_NETINET_IN_H
 
46
#include <netinet/in.h>
 
47
#endif
 
48
#if TIME_WITH_SYS_TIME
 
49
# ifdef WIN32
 
50
#  include <sys/timeb.h>
 
51
# else
 
52
#  include <sys/time.h>
 
53
# endif
 
54
# include <time.h>
 
55
#else
 
56
# if HAVE_SYS_TIME_H
 
57
#  include <sys/time.h>
 
58
# else
 
59
#  include <time.h>
 
60
# endif
 
61
#endif
 
62
#if HAVE_STRING_H
 
63
#include <string.h>
 
64
#else
 
65
#include <strings.h>
 
66
#endif
 
67
#if HAVE_STDLIB_H
 
68
#include <stdlib.h>
 
69
#endif
 
70
#if HAVE_SYS_SELECT_H
 
71
#include <sys/select.h>
 
72
#endif
 
73
 
 
74
#if HAVE_WINSOCK_H
 
75
#include <winsock.h>
 
76
#endif
 
77
 
 
78
#if HAVE_DMALLOC_H
 
79
#include <dmalloc.h>
 
80
#endif
 
81
 
 
82
#include <net-snmp/types.h>
 
83
#include <net-snmp/output_api.h>
 
84
#include <net-snmp/config_api.h>
 
85
#include <net-snmp/utilities.h>
 
86
 
 
87
#include <net-snmp/library/asn1.h>
 
88
#include <net-snmp/library/snmp_api.h>
 
89
#include <net-snmp/library/mib.h>
 
90
#include <net-snmp/library/parse.h>
 
91
#include <net-snmp/library/int64.h>
 
92
#include <net-snmp/library/snmp_client.h>
 
93
 
 
94
/** @defgroup mib_utilities mib parsing and datatype manipulation routines.
 
95
 *  @ingroup library
 
96
 *
 
97
 *  @{
 
98
 */
 
99
 
 
100
static char    *uptimeString(u_long, char *);
 
101
 
 
102
static struct tree *_get_realloc_symbol(const oid * objid, size_t objidlen,
 
103
                                        struct tree *subtree,
 
104
                                        u_char ** buf, size_t * buf_len,
 
105
                                        size_t * out_len,
 
106
                                        int allow_realloc,
 
107
                                        int *buf_overflow,
 
108
                                        struct index_list *in_dices,
 
109
                                        size_t * end_of_known);
 
110
 
 
111
static int      print_tree_node(u_char ** buf, size_t * buf_len,
 
112
                                size_t * out_len, int allow_realloc,
 
113
                                struct tree *tp, int width);
 
114
static void     handle_mibdirs_conf(const char *token, char *line);
 
115
static void     handle_mibs_conf(const char *token, char *line);
 
116
static void     handle_mibfile_conf(const char *token, char *line);
 
117
 
 
118
static void     _oid_finish_printing(const oid * objid, size_t objidlen,
 
119
                                     u_char ** buf, size_t * buf_len,
 
120
                                     size_t * out_len,
 
121
                                     int allow_realloc, int *buf_overflow);
 
122
 
 
123
/*
 
124
 * helper functions for get_module_node 
 
125
 */
 
126
static int      node_to_oid(struct tree *, oid *, size_t *);
 
127
#ifndef DISABLE_MIB_LOADING
 
128
static int      _add_strings_to_oid(struct tree *, char *,
 
129
                                    oid *, size_t *, size_t);
 
130
#else
 
131
static int      _add_strings_to_oid(void *, char *,
 
132
                                    oid *, size_t *, size_t);
 
133
#endif /* DISABLE_MIB_LOADING */
 
134
 
 
135
#ifndef DISABLE_MIB_LOADING
 
136
extern struct tree *tree_head;
 
137
static struct tree *tree_top;
 
138
 
 
139
struct tree    *Mib;            /* Backwards compatibility */
 
140
#endif /* DISABLE_MIB_LOADING */
 
141
 
 
142
oid             RFC1213_MIB[] = { 1, 3, 6, 1, 2, 1 };
 
143
static char     Standard_Prefix[] = ".1.3.6.1.2.1";
 
144
 
 
145
/*
 
146
 * Set default here as some uses of read_objid require valid pointer. 
 
147
 */
 
148
static char    *Prefix = &Standard_Prefix[0];
 
149
typedef struct _PrefixList {
 
150
    const char     *str;
 
151
    int             len;
 
152
}              *PrefixListPtr, PrefixList;
 
153
 
 
154
/*
 
155
 * Here are the prefix strings.
 
156
 * Note that the first one finds the value of Prefix or Standard_Prefix.
 
157
 * Any of these MAY start with period; all will NOT end with period.
 
158
 * Period is added where needed.  See use of Prefix in this module.
 
159
 */
 
160
PrefixList      mib_prefixes[] = {
 
161
    {&Standard_Prefix[0]},      /* placeholder for Prefix data */
 
162
    {".iso.org.dod.internet.mgmt.mib-2"},
 
163
    {".iso.org.dod.internet.experimental"},
 
164
    {".iso.org.dod.internet.private"},
 
165
    {".iso.org.dod.internet.snmpParties"},
 
166
    {".iso.org.dod.internet.snmpSecrets"},
 
167
    {NULL, 0}                   /* end of list */
 
168
};
 
169
 
 
170
 
 
171
/**
 
172
 * @internal
 
173
 * Converts timeticks to hours, minutes, seconds string.
 
174
 *
 
175
 * @param timeticks    The timeticks to convert.
 
176
 * @param buf          Buffer to write to, has to be at 
 
177
 *                     least 40 Bytes large.
 
178
 *       
 
179
 * @return The buffer.
 
180
 */
 
181
static char    *
 
182
uptimeString(u_long timeticks, char *buf)
 
183
{
 
184
    int             centisecs, seconds, minutes, hours, days;
 
185
 
 
186
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS)) {
 
187
        sprintf(buf, "%lu", timeticks);
 
188
        return buf;
 
189
    }
 
190
 
 
191
 
 
192
    centisecs = timeticks % 100;
 
193
    timeticks /= 100;
 
194
    days = timeticks / (60 * 60 * 24);
 
195
    timeticks %= (60 * 60 * 24);
 
196
 
 
197
    hours = timeticks / (60 * 60);
 
198
    timeticks %= (60 * 60);
 
199
 
 
200
    minutes = timeticks / 60;
 
201
    seconds = timeticks % 60;
 
202
 
 
203
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT))
 
204
        sprintf(buf, "%d:%d:%02d:%02d.%02d",
 
205
                days, hours, minutes, seconds, centisecs);
 
206
    else {
 
207
        if (days == 0) {
 
208
            sprintf(buf, "%d:%02d:%02d.%02d",
 
209
                    hours, minutes, seconds, centisecs);
 
210
        } else if (days == 1) {
 
211
            sprintf(buf, "%d day, %d:%02d:%02d.%02d",
 
212
                    days, hours, minutes, seconds, centisecs);
 
213
        } else {
 
214
            sprintf(buf, "%d days, %d:%02d:%02d.%02d",
 
215
                    days, hours, minutes, seconds, centisecs);
 
216
        }
 
217
    }
 
218
    return buf;
 
219
}
 
220
 
 
221
 
 
222
 
 
223
/**
 
224
 * @internal
 
225
 * Prints the character pointed to if in human-readable ASCII range,
 
226
 * otherwise prints a dot.
 
227
 *
 
228
 * @param buf Buffer to print the character to.
 
229
 * @param ch  Character to print.
 
230
 */
 
231
static void
 
232
sprint_char(char *buf, const u_char ch)
 
233
{
 
234
    if (isprint(ch)) {
 
235
        sprintf(buf, "%c", (int) ch);
 
236
    } else {
 
237
        sprintf(buf, ".");
 
238
    }
 
239
}
 
240
 
 
241
 
 
242
 
 
243
/**
 
244
 * Prints a hexadecimal string into a buffer.
 
245
 *
 
246
 * The characters pointed by *cp are encoded as hexadecimal string.
 
247
 *
 
248
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
249
 * needed size. (Note: *buf may change due to this.)
 
250
 * 
 
251
 * @param buf      address of the buffer to print to.
 
252
 * @param buf_len  address to an integer containing the size of buf.
 
253
 * @param out_len  incremented by the number of characters printed.
 
254
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
255
 *                      needed size.
 
256
 * @param cp       the array of characters to encode.
 
257
 * @param len      the array length of cp.
 
258
 * 
 
259
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
260
 *         small when not allowed to realloc.)
 
261
 */
 
262
int
 
263
sprint_realloc_hexstring(u_char ** buf, size_t * buf_len, size_t * out_len,
 
264
                         int allow_realloc, const u_char * cp, size_t len)
 
265
{
 
266
    const u_char   *tp;
 
267
    size_t          lenleft;
 
268
 
 
269
    for (; len >= 16; len -= 16) {
 
270
        while ((*out_len + 50) >= *buf_len) {
 
271
            if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
272
                return 0;
 
273
            }
 
274
        }
 
275
 
 
276
        sprintf((char *) (*buf + *out_len),
 
277
                "%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1],
 
278
                cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
 
279
        *out_len += strlen((char *) (*buf + *out_len));
 
280
        cp += 8;
 
281
        sprintf((char *) (*buf + *out_len),
 
282
                "%02X %02X %02X %02X %02X %02X %02X %02X", cp[0], cp[1],
 
283
                cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
 
284
        *out_len += strlen((char *) (*buf + *out_len));
 
285
        cp += 8;
 
286
 
 
287
        if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT)) {
 
288
            while ((*out_len + 21) >= *buf_len) {
 
289
                if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
290
                    return 0;
 
291
                }
 
292
            }
 
293
            sprintf((char *) (*buf + *out_len), "  [");
 
294
            *out_len += strlen((char *) (*buf + *out_len));
 
295
            for (tp = cp - 16; tp < cp; tp++) {
 
296
                sprint_char((char *) (*buf + *out_len), *tp);
 
297
                (*out_len)++;
 
298
            }
 
299
            sprintf((char *) (*buf + *out_len), "]");
 
300
            *out_len += strlen((char *) (*buf + *out_len));
 
301
        }
 
302
        if (len > 16) {
 
303
            while ((*out_len + 2) >= *buf_len) {
 
304
                if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
305
                    return 0;
 
306
                }
 
307
            }
 
308
            *(*buf + (*out_len)++) = '\n';
 
309
            *(*buf + *out_len) = 0;
 
310
        }
 
311
    }
 
312
 
 
313
    lenleft = len;
 
314
    for (; len > 0; len--) {
 
315
        while ((*out_len + 4) >= *buf_len) {
 
316
            if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
317
                return 0;
 
318
            }
 
319
        }
 
320
        sprintf((char *) (*buf + *out_len), "%02X ", *cp++);
 
321
        *out_len += strlen((char *) (*buf + *out_len));
 
322
    }
 
323
 
 
324
    if ((lenleft > 0)
 
325
        && netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT)) {
 
326
        while ((*out_len + 5 + lenleft) >= *buf_len) {
 
327
            if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
328
                return 0;
 
329
            }
 
330
        }
 
331
        sprintf((char *) (*buf + *out_len), "  [");
 
332
        *out_len += strlen((char *) (*buf + *out_len));
 
333
        for (tp = cp - lenleft; tp < cp; tp++) {
 
334
            sprint_char((char *) (*buf + *out_len), *tp);
 
335
            (*out_len)++;
 
336
        }
 
337
        sprintf((char *) (*buf + *out_len), "]");
 
338
        *out_len += strlen((char *) (*buf + *out_len));
 
339
    }
 
340
    return 1;
 
341
}
 
342
 
 
343
 
 
344
 
 
345
/**
 
346
 * Prints an ascii string into a buffer.
 
347
 *
 
348
 * The characters pointed by *cp are encoded as an ascii string.
 
349
 * 
 
350
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
351
 * needed size. (Note: *buf may change due to this.)
 
352
 * 
 
353
 * @param buf      address of the buffer to print to.
 
354
 * @param buf_len  address to an integer containing the size of buf.
 
355
 * @param out_len  incremented by the number of characters printed.
 
356
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
357
 *                      needed size.
 
358
 * @param cp       the array of characters to encode.
 
359
 * @param len      the array length of cp.
 
360
 * 
 
361
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
362
 *         small when not allowed to realloc.)
 
363
 */
 
364
int
 
365
sprint_realloc_asciistring(u_char ** buf, size_t * buf_len,
 
366
                           size_t * out_len, int allow_realloc,
 
367
                           const u_char * cp, size_t len)
 
368
{
 
369
    int             i;
 
370
 
 
371
    for (i = 0; i < (int) len; i++) {
 
372
        if (isprint(*cp)) {
 
373
            if (*cp == '\\' || *cp == '"') {
 
374
                if ((*out_len >= *buf_len) &&
 
375
                    !(allow_realloc && snmp_realloc(buf, buf_len))) {
 
376
                    return 0;
 
377
                }
 
378
                *(*buf + (*out_len)++) = '\\';
 
379
            }
 
380
            if ((*out_len >= *buf_len) &&
 
381
                !(allow_realloc && snmp_realloc(buf, buf_len))) {
 
382
                return 0;
 
383
            }
 
384
            *(*buf + (*out_len)++) = *cp++;
 
385
        } else {
 
386
            if ((*out_len >= *buf_len) &&
 
387
                !(allow_realloc && snmp_realloc(buf, buf_len))) {
 
388
                return 0;
 
389
            }
 
390
            *(*buf + (*out_len)++) = '.';
 
391
            cp++;
 
392
        }
 
393
    }
 
394
    if ((*out_len >= *buf_len) &&
 
395
        !(allow_realloc && snmp_realloc(buf, buf_len))) {
 
396
        return 0;
 
397
    }
 
398
    *(*buf + *out_len) = '\0';
 
399
    return 1;
 
400
}
 
401
 
 
402
/**
 
403
 * Prints an octet string into a buffer.
 
404
 *
 
405
 * The variable var is encoded as octet string.
 
406
 * 
 
407
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
408
 * needed size. (Note: *buf may change due to this.)
 
409
 * 
 
410
 * @param buf      Address of the buffer to print to.
 
411
 * @param buf_len  Address to an integer containing the size of buf.
 
412
 * @param out_len  Incremented by the number of characters printed.
 
413
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
414
 *                      needed size.
 
415
 * @param var      The variable to encode.
 
416
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
417
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
418
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
419
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
420
 * 
 
421
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
422
 *         small when not allowed to realloc.)
 
423
 */
 
424
int
 
425
sprint_realloc_octet_string(u_char ** buf, size_t * buf_len,
 
426
                            size_t * out_len, int allow_realloc,
 
427
                            const netsnmp_variable_list * var,
 
428
                            const struct enum_list *enums, const char *hint,
 
429
                            const char *units)
 
430
{
 
431
    size_t          saved_out_len = *out_len;
 
432
    const char     *saved_hint = hint;
 
433
    int             hex = 0, x = 0;
 
434
    u_char         *cp;
 
435
    int             output_format;
 
436
 
 
437
    if ((var->type != ASN_OCTET_STR) && 
 
438
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
439
        const char      str[] = "Wrong Type (should be OCTET STRING): ";
 
440
        if (snmp_strcat
 
441
            (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
 
442
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
443
                                          allow_realloc, var, NULL, NULL,
 
444
                                          NULL);
 
445
        } else {
 
446
            return 0;
 
447
        }
 
448
    }
 
449
 
 
450
 
 
451
    if (hint) {
 
452
        int             repeat, width = 1;
 
453
        long            value;
 
454
        char            code = 'd', separ = 0, term = 0, ch, intbuf[16];
 
455
        u_char         *ecp;
 
456
 
 
457
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
458
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
459
                             (const u_char *) "STRING: ")) {
 
460
                return 0;
 
461
            }
 
462
        }
 
463
        cp = var->val.string;
 
464
        ecp = cp + var->val_len;
 
465
 
 
466
        while (cp < ecp) {
 
467
            repeat = 1;
 
468
            if (*hint) {
 
469
                if (*hint == '*') {
 
470
                    repeat = *cp++;
 
471
                    hint++;
 
472
                }
 
473
                width = 0;
 
474
                while ('0' <= *hint && *hint <= '9')
 
475
                    width = (width * 10) + (*hint++ - '0');
 
476
                code = *hint++;
 
477
                if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9')
 
478
                    && (width != 0
 
479
                        || (ch != 'x' && ch != 'd' && ch != 'o')))
 
480
                    separ = *hint++;
 
481
                else
 
482
                    separ = 0;
 
483
                if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9')
 
484
                    && (width != 0
 
485
                        || (ch != 'x' && ch != 'd' && ch != 'o')))
 
486
                    term = *hint++;
 
487
                else
 
488
                    term = 0;
 
489
                if (width == 0)
 
490
                    width = 1;
 
491
            }
 
492
 
 
493
            while (repeat && cp < ecp) {
 
494
                value = 0;
 
495
                if (code != 'a' && code != 't') {
 
496
                    for (x = 0; x < width; x++) {
 
497
                        value = value * 256 + *cp++;
 
498
                    }
 
499
                }
 
500
                switch (code) {
 
501
                case 'x':
 
502
                    sprintf(intbuf, "%lx", value);
 
503
                    if (!snmp_strcat
 
504
                        (buf, buf_len, out_len, allow_realloc,
 
505
                         (u_char *) intbuf)) {
 
506
                        return 0;
 
507
                    }
 
508
                    break;
 
509
                case 'd':
 
510
                    sprintf(intbuf, "%ld", value);
 
511
                    if (!snmp_strcat
 
512
                        (buf, buf_len, out_len, allow_realloc,
 
513
                         (u_char *) intbuf)) {
 
514
                        return 0;
 
515
                    }
 
516
                    break;
 
517
                case 'o':
 
518
                    sprintf(intbuf, "%lo", value);
 
519
                    if (!snmp_strcat
 
520
                        (buf, buf_len, out_len, allow_realloc,
 
521
                         (u_char *) intbuf)) {
 
522
                        return 0;
 
523
                    }
 
524
                    break;
 
525
                case 't': /* new in rfc 3411 */
 
526
                case 'a':
 
527
                    while ((*out_len + width + 1) >= *buf_len) {
 
528
                        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
529
                            return 0;
 
530
                        }
 
531
                    }
 
532
                    for (x = 0; x < width && cp < ecp; x++) {
 
533
                        *(*buf + *out_len) = *cp++;
 
534
                        (*out_len)++;
 
535
                    }
 
536
                    *(*buf + *out_len) = '\0';
 
537
                    break;
 
538
                default:
 
539
                    *out_len = saved_out_len;
 
540
                    if (snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
541
                                    (const u_char *) "(Bad hint ignored: ")
 
542
                        && snmp_strcat(buf, buf_len, out_len,
 
543
                                       allow_realloc,
 
544
                                       (const u_char *) saved_hint)
 
545
                        && snmp_strcat(buf, buf_len, out_len,
 
546
                                       allow_realloc,
 
547
                                       (const u_char *) ") ")) {
 
548
                        return sprint_realloc_octet_string(buf, buf_len,
 
549
                                                           out_len,
 
550
                                                           allow_realloc,
 
551
                                                           var, enums,
 
552
                                                           NULL, NULL);
 
553
                    } else {
 
554
                        return 0;
 
555
                    }
 
556
                }
 
557
 
 
558
                if (cp < ecp && separ) {
 
559
                    while ((*out_len + 1) >= *buf_len) {
 
560
                        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
561
                            return 0;
 
562
                        }
 
563
                    }
 
564
                    *(*buf + *out_len) = separ;
 
565
                    (*out_len)++;
 
566
                    *(*buf + *out_len) = '\0';
 
567
                }
 
568
                repeat--;
 
569
            }
 
570
 
 
571
            if (term && cp < ecp) {
 
572
                while ((*out_len + 1) >= *buf_len) {
 
573
                    if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
574
                        return 0;
 
575
                    }
 
576
                }
 
577
                *(*buf + *out_len) = term;
 
578
                (*out_len)++;
 
579
                *(*buf + *out_len) = '\0';
 
580
            }
 
581
        }
 
582
 
 
583
        if (units) {
 
584
            return (snmp_strcat
 
585
                    (buf, buf_len, out_len, allow_realloc,
 
586
                     (const u_char *) " ")
 
587
                    && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
588
                                   (const u_char *) units));
 
589
        }
 
590
        if ((*out_len >= *buf_len) &&
 
591
            !(allow_realloc && snmp_realloc(buf, buf_len))) {
 
592
            return 0;
 
593
        }
 
594
        *(*buf + *out_len) = '\0';
 
595
 
 
596
        return 1;
 
597
    }
 
598
 
 
599
    output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT);
 
600
    if (0 == output_format) {
 
601
        output_format = NETSNMP_STRING_OUTPUT_GUESS;
 
602
    }
 
603
    switch (output_format) {
 
604
    case NETSNMP_STRING_OUTPUT_GUESS:
 
605
        hex = 0;
 
606
        for (cp = var->val.string, x = 0; x < (int) var->val_len; x++, cp++) {
 
607
            if (!isprint(*cp) && !isspace(*cp)) {
 
608
                hex = 1;
 
609
            }
 
610
        }
 
611
        break;
 
612
 
 
613
    case NETSNMP_STRING_OUTPUT_ASCII:
 
614
        hex = 0;
 
615
        break;
 
616
 
 
617
    case NETSNMP_STRING_OUTPUT_HEX:
 
618
        hex = 1;
 
619
        break;
 
620
    }
 
621
 
 
622
    if (var->val_len == 0) {
 
623
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
624
                           (const u_char *) "\"\"");
 
625
    }
 
626
 
 
627
    if (hex) {
 
628
        if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
629
            if (!snmp_strcat
 
630
                (buf, buf_len, out_len, allow_realloc,
 
631
                 (const u_char *) "\"")) {
 
632
                return 0;
 
633
            }
 
634
        } else {
 
635
            if (!snmp_strcat
 
636
                (buf, buf_len, out_len, allow_realloc,
 
637
                 (const u_char *) "Hex-STRING: ")) {
 
638
                return 0;
 
639
            }
 
640
        }
 
641
 
 
642
        if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc,
 
643
                                      var->val.string, var->val_len)) {
 
644
            return 0;
 
645
        }
 
646
 
 
647
        if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
648
            if (!snmp_strcat
 
649
                (buf, buf_len, out_len, allow_realloc,
 
650
                 (const u_char *) "\"")) {
 
651
                return 0;
 
652
            }
 
653
        }
 
654
    } else {
 
655
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
656
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
657
                             (const u_char *) "STRING: ")) {
 
658
                return 0;
 
659
            }
 
660
        }
 
661
        if (!snmp_strcat
 
662
            (buf, buf_len, out_len, allow_realloc,
 
663
             (const u_char *) "\"")) {
 
664
            return 0;
 
665
        }
 
666
        if (!sprint_realloc_asciistring
 
667
            (buf, buf_len, out_len, allow_realloc, var->val.string,
 
668
             var->val_len)) {
 
669
            return 0;
 
670
        }
 
671
        if (!snmp_strcat
 
672
            (buf, buf_len, out_len, allow_realloc,
 
673
             (const u_char *) "\"")) {
 
674
            return 0;
 
675
        }
 
676
    }
 
677
 
 
678
    if (units) {
 
679
        return (snmp_strcat
 
680
                (buf, buf_len, out_len, allow_realloc,
 
681
                 (const u_char *) " ")
 
682
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
683
                               (const u_char *) units));
 
684
    }
 
685
    return 1;
 
686
}
 
687
 
 
688
#ifdef OPAQUE_SPECIAL_TYPES
 
689
 
 
690
/**
 
691
 * Prints a float into a buffer.
 
692
 *
 
693
 * The variable var is encoded as a floating point value.
 
694
 * 
 
695
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
696
 * needed size. (Note: *buf may change due to this.)
 
697
 * 
 
698
 * @param buf      Address of the buffer to print to.
 
699
 * @param buf_len  Address to an integer containing the size of buf.
 
700
 * @param out_len  Incremented by the number of characters printed.
 
701
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
702
 *                      needed size.
 
703
 * @param var      The variable to encode.
 
704
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
705
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
706
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
707
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
708
 * 
 
709
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
710
 *         small when not allowed to realloc.)
 
711
 */
 
712
int
 
713
sprint_realloc_float(u_char ** buf, size_t * buf_len,
 
714
                     size_t * out_len, int allow_realloc,
 
715
                     const netsnmp_variable_list * var,
 
716
                     const struct enum_list *enums,
 
717
                     const char *hint, const char *units)
 
718
{
 
719
    if ((var->type != ASN_OPAQUE_FLOAT) &&
 
720
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
721
        u_char          str[] = "Wrong Type (should be Float): ";
 
722
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
723
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
724
                                          allow_realloc, var, NULL, NULL,
 
725
                                          NULL);
 
726
        } else {
 
727
            return 0;
 
728
        }
 
729
    }
 
730
 
 
731
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
732
        if (!snmp_strcat
 
733
            (buf, buf_len, out_len, allow_realloc,
 
734
             (const u_char *) "Opaque: Float: ")) {
 
735
            return 0;
 
736
        }
 
737
    }
 
738
 
 
739
 
 
740
    /*
 
741
     * How much space needed for max. length float?  128 is overkill.  
 
742
     */
 
743
 
 
744
    while ((*out_len + 128 + 1) >= *buf_len) {
 
745
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
746
            return 0;
 
747
        }
 
748
    }
 
749
 
 
750
    sprintf((char *) (*buf + *out_len), "%f", *var->val.floatVal);
 
751
    *out_len += strlen((char *) (*buf + *out_len));
 
752
 
 
753
    if (units) {
 
754
        return (snmp_strcat
 
755
                (buf, buf_len, out_len, allow_realloc,
 
756
                 (const u_char *) " ")
 
757
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
758
                               (const u_char *) units));
 
759
    }
 
760
    return 1;
 
761
}
 
762
 
 
763
 
 
764
/**
 
765
 * Prints a double into a buffer.
 
766
 *
 
767
 * The variable var is encoded as a double precision floating point value.
 
768
 * 
 
769
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
770
 * needed size. (Note: *buf may change due to this.)
 
771
 * 
 
772
 * @param buf      Address of the buffer to print to.
 
773
 * @param buf_len  Address to an integer containing the size of buf.
 
774
 * @param out_len  Incremented by the number of characters printed.
 
775
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
776
 *                      needed size.
 
777
 * @param var      The variable to encode.
 
778
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
779
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
780
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
781
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
782
 * 
 
783
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
784
 *         small when not allowed to realloc.)
 
785
 */
 
786
int
 
787
sprint_realloc_double(u_char ** buf, size_t * buf_len,
 
788
                      size_t * out_len, int allow_realloc,
 
789
                      const netsnmp_variable_list * var,
 
790
                      const struct enum_list *enums,
 
791
                      const char *hint, const char *units)
 
792
{
 
793
    if ((var->type != ASN_OPAQUE_DOUBLE) && 
 
794
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
795
        const char      str[] = "Wrong Type (should be Double): ";
 
796
        if (snmp_strcat
 
797
            (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
 
798
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
799
                                          allow_realloc, var, NULL, NULL,
 
800
                                          NULL);
 
801
        } else {
 
802
            return 0;
 
803
        }
 
804
    }
 
805
 
 
806
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
807
        if (!snmp_strcat
 
808
            (buf, buf_len, out_len, allow_realloc,
 
809
             (const u_char *) "Opaque: Float: ")) {
 
810
            return 0;
 
811
        }
 
812
    }
 
813
 
 
814
    /*
 
815
     * How much space needed for max. length double?  128 is overkill.  
 
816
     */
 
817
 
 
818
    while ((*out_len + 128 + 1) >= *buf_len) {
 
819
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
820
            return 0;
 
821
        }
 
822
    }
 
823
 
 
824
    sprintf((char *) (*buf + *out_len), "%f", *var->val.doubleVal);
 
825
    *out_len += strlen((char *) (*buf + *out_len));
 
826
 
 
827
    if (units) {
 
828
        return (snmp_strcat
 
829
                (buf, buf_len, out_len, allow_realloc,
 
830
                 (const u_char *) " ")
 
831
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
832
                               (const u_char *) units));
 
833
    }
 
834
    return 1;
 
835
}
 
836
 
 
837
#endif                          /* OPAQUE_SPECIAL_TYPES */
 
838
 
 
839
 
 
840
/**
 
841
 * Prints a counter into a buffer.
 
842
 *
 
843
 * The variable var is encoded as a counter value.
 
844
 * 
 
845
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
846
 * needed size. (Note: *buf may change due to this.)
 
847
 * 
 
848
 * @param buf      Address of the buffer to print to.
 
849
 * @param buf_len  Address to an integer containing the size of buf.
 
850
 * @param out_len  Incremented by the number of characters printed.
 
851
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
852
 *                      needed size.
 
853
 * @param var      The variable to encode.
 
854
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
855
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
856
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
857
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
858
 * 
 
859
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
860
 *         small when not allowed to realloc.)
 
861
 */
 
862
int
 
863
sprint_realloc_counter64(u_char ** buf, size_t * buf_len, size_t * out_len,
 
864
                         int allow_realloc,
 
865
                         const netsnmp_variable_list * var,
 
866
                         const struct enum_list *enums,
 
867
                         const char *hint, const char *units)
 
868
{
 
869
    char            a64buf[I64CHARSZ + 1];
 
870
 
 
871
    if ((var->type != ASN_COUNTER64
 
872
#ifdef OPAQUE_SPECIAL_TYPES
 
873
        && var->type != ASN_OPAQUE_COUNTER64
 
874
        && var->type != ASN_OPAQUE_I64 && var->type != ASN_OPAQUE_U64
 
875
#endif
 
876
        ) && (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
877
        u_char          str[] = "Wrong Type (should be Counter64): ";
 
878
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
879
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
880
                                          allow_realloc, var, NULL, NULL,
 
881
                                          NULL);
 
882
        } else {
 
883
            return 0;
 
884
        }
 
885
    }
 
886
 
 
887
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
888
#ifdef OPAQUE_SPECIAL_TYPES
 
889
        if (var->type != ASN_COUNTER64) {
 
890
            if (!snmp_strcat
 
891
                (buf, buf_len, out_len, allow_realloc,
 
892
                 (const u_char *) "Opaque: ")) {
 
893
                return 0;
 
894
            }
 
895
        }
 
896
#endif
 
897
#ifdef OPAQUE_SPECIAL_TYPES
 
898
        switch (var->type) {
 
899
        case ASN_OPAQUE_U64:
 
900
            if (!snmp_strcat
 
901
                (buf, buf_len, out_len, allow_realloc,
 
902
                 (const u_char *) "UInt64: ")) {
 
903
                return 0;
 
904
            }
 
905
            break;
 
906
        case ASN_OPAQUE_I64:
 
907
            if (!snmp_strcat
 
908
                (buf, buf_len, out_len, allow_realloc,
 
909
                 (const u_char *) "Int64: ")) {
 
910
                return 0;
 
911
            }
 
912
            break;
 
913
        case ASN_COUNTER64:
 
914
        case ASN_OPAQUE_COUNTER64:
 
915
#endif
 
916
            if (!snmp_strcat
 
917
                (buf, buf_len, out_len, allow_realloc,
 
918
                 (const u_char *) "Counter64: ")) {
 
919
                return 0;
 
920
            }
 
921
#ifdef OPAQUE_SPECIAL_TYPES
 
922
        }
 
923
#endif
 
924
    }
 
925
#ifdef OPAQUE_SPECIAL_TYPES
 
926
    if (var->type == ASN_OPAQUE_I64) {
 
927
        printI64(a64buf, var->val.counter64);
 
928
        if (!snmp_strcat
 
929
            (buf, buf_len, out_len, allow_realloc,
 
930
             (const u_char *) a64buf)) {
 
931
            return 0;
 
932
        }
 
933
    } else {
 
934
#endif
 
935
        printU64(a64buf, var->val.counter64);
 
936
        if (!snmp_strcat
 
937
            (buf, buf_len, out_len, allow_realloc,
 
938
             (const u_char *) a64buf)) {
 
939
            return 0;
 
940
        }
 
941
#ifdef OPAQUE_SPECIAL_TYPES
 
942
    }
 
943
#endif
 
944
 
 
945
    if (units) {
 
946
        return (snmp_strcat
 
947
                (buf, buf_len, out_len, allow_realloc,
 
948
                 (const u_char *) " ")
 
949
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
950
                               (const u_char *) units));
 
951
    }
 
952
    return 1;
 
953
}
 
954
 
 
955
 
 
956
/**
 
957
 * Prints an object identifier into a buffer.
 
958
 *
 
959
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
960
 * needed size. (Note: *buf may change due to this.)
 
961
 * 
 
962
 * @param buf      Address of the buffer to print to.
 
963
 * @param buf_len  Address to an integer containing the size of buf.
 
964
 * @param out_len  Incremented by the number of characters printed.
 
965
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
966
 *                      needed size.
 
967
 * @param var      The variable to encode.
 
968
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
969
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
970
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
971
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
972
 * 
 
973
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
974
 *         small when not allowed to realloc.)
 
975
 */
 
976
int
 
977
sprint_realloc_opaque(u_char ** buf, size_t * buf_len,
 
978
                      size_t * out_len, int allow_realloc,
 
979
                      const netsnmp_variable_list * var,
 
980
                      const struct enum_list *enums,
 
981
                      const char *hint, const char *units)
 
982
{
 
983
    if ((var->type != ASN_OPAQUE
 
984
#ifdef OPAQUE_SPECIAL_TYPES
 
985
        && var->type != ASN_OPAQUE_COUNTER64
 
986
        && var->type != ASN_OPAQUE_U64
 
987
        && var->type != ASN_OPAQUE_I64
 
988
        && var->type != ASN_OPAQUE_FLOAT && var->type != ASN_OPAQUE_DOUBLE
 
989
#endif                          /* OPAQUE_SPECIAL_TYPES */
 
990
        ) && (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
991
        u_char          str[] = "Wrong Type (should be Opaque): ";
 
992
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
993
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
994
                                          allow_realloc, var, NULL, NULL,
 
995
                                          NULL);
 
996
        } else {
 
997
            return 0;
 
998
        }
 
999
    }
 
1000
#ifdef OPAQUE_SPECIAL_TYPES
 
1001
    switch (var->type) {
 
1002
    case ASN_OPAQUE_COUNTER64:
 
1003
    case ASN_OPAQUE_U64:
 
1004
    case ASN_OPAQUE_I64:
 
1005
        return sprint_realloc_counter64(buf, buf_len, out_len,
 
1006
                                        allow_realloc, var, enums, hint,
 
1007
                                        units);
 
1008
        break;
 
1009
 
 
1010
    case ASN_OPAQUE_FLOAT:
 
1011
        return sprint_realloc_float(buf, buf_len, out_len, allow_realloc,
 
1012
                                    var, enums, hint, units);
 
1013
        break;
 
1014
 
 
1015
    case ASN_OPAQUE_DOUBLE:
 
1016
        return sprint_realloc_double(buf, buf_len, out_len, allow_realloc,
 
1017
                                     var, enums, hint, units);
 
1018
        break;
 
1019
 
 
1020
    case ASN_OPAQUE:
 
1021
#endif
 
1022
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1023
            u_char          str[] = "OPAQUE: ";
 
1024
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1025
                return 0;
 
1026
            }
 
1027
        }
 
1028
        if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc,
 
1029
                                      var->val.string, var->val_len)) {
 
1030
            return 0;
 
1031
        }
 
1032
#ifdef OPAQUE_SPECIAL_TYPES
 
1033
    }
 
1034
#endif
 
1035
    if (units) {
 
1036
        return (snmp_strcat
 
1037
                (buf, buf_len, out_len, allow_realloc,
 
1038
                 (const u_char *) " ")
 
1039
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
1040
                               (const u_char *) units));
 
1041
    }
 
1042
    return 1;
 
1043
}
 
1044
 
 
1045
 
 
1046
/**
 
1047
 * Prints an object identifier into a buffer.
 
1048
 *
 
1049
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1050
 * needed size. (Note: *buf may change due to this.)
 
1051
 * 
 
1052
 * @param buf      Address of the buffer to print to.
 
1053
 * @param buf_len  Address to an integer containing the size of buf.
 
1054
 * @param out_len  Incremented by the number of characters printed.
 
1055
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1056
 *                      needed size.
 
1057
 * @param var      The variable to encode.
 
1058
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1059
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1060
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1061
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1062
 * 
 
1063
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1064
 *         small when not allowed to realloc.)
 
1065
 */
 
1066
int
 
1067
sprint_realloc_object_identifier(u_char ** buf, size_t * buf_len,
 
1068
                                 size_t * out_len, int allow_realloc,
 
1069
                                 const netsnmp_variable_list * var,
 
1070
                                 const struct enum_list *enums,
 
1071
                                 const char *hint, const char *units)
 
1072
{
 
1073
    int             buf_overflow = 0;
 
1074
 
 
1075
    if ((var->type != ASN_OBJECT_ID) &&
 
1076
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1077
        u_char          str[] =
 
1078
            "Wrong Type (should be OBJECT IDENTIFIER): ";
 
1079
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1080
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1081
                                          allow_realloc, var, NULL, NULL,
 
1082
                                          NULL);
 
1083
        } else {
 
1084
            return 0;
 
1085
        }
 
1086
    }
 
1087
 
 
1088
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1089
        u_char          str[] = "OID: ";
 
1090
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1091
            return 0;
 
1092
        }
 
1093
    }
 
1094
 
 
1095
    netsnmp_sprint_realloc_objid_tree(buf, buf_len, out_len, allow_realloc,
 
1096
                                      &buf_overflow,
 
1097
                                      (oid *) (var->val.objid),
 
1098
                                      var->val_len / sizeof(oid));
 
1099
 
 
1100
    if (buf_overflow) {
 
1101
        return 0;
 
1102
    }
 
1103
 
 
1104
    if (units) {
 
1105
        return (snmp_strcat
 
1106
                (buf, buf_len, out_len, allow_realloc,
 
1107
                 (const u_char *) " ")
 
1108
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
1109
                               (const u_char *) units));
 
1110
    }
 
1111
    return 1;
 
1112
}
 
1113
 
 
1114
 
 
1115
 
 
1116
/**
 
1117
 * Prints a timetick variable into a buffer.
 
1118
 *
 
1119
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1120
 * needed size. (Note: *buf may change due to this.)
 
1121
 * 
 
1122
 * @param buf      Address of the buffer to print to.
 
1123
 * @param buf_len  Address to an integer containing the size of buf.
 
1124
 * @param out_len  Incremented by the number of characters printed.
 
1125
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1126
 *                      needed size.
 
1127
 * @param var      The variable to encode.
 
1128
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1129
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1130
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1131
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1132
 * 
 
1133
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1134
 *         small when not allowed to realloc.)
 
1135
 */
 
1136
int
 
1137
sprint_realloc_timeticks(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1138
                         int allow_realloc,
 
1139
                         const netsnmp_variable_list * var,
 
1140
                         const struct enum_list *enums,
 
1141
                         const char *hint, const char *units)
 
1142
{
 
1143
    char            timebuf[40];
 
1144
 
 
1145
    if ((var->type != ASN_TIMETICKS) && 
 
1146
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1147
        u_char          str[] = "Wrong Type (should be Timeticks): ";
 
1148
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1149
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1150
                                          allow_realloc, var, NULL, NULL,
 
1151
                                          NULL);
 
1152
        } else {
 
1153
            return 0;
 
1154
        }
 
1155
    }
 
1156
 
 
1157
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS)) {
 
1158
        char            str[16];
 
1159
        sprintf(str, "%lu", *(u_long *) var->val.integer);
 
1160
        if (!snmp_strcat
 
1161
            (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
 
1162
            return 0;
 
1163
        }
 
1164
        return 1;
 
1165
    }
 
1166
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1167
        char            str[32];
 
1168
        sprintf(str, "Timeticks: (%lu) ", *(u_long *) var->val.integer);
 
1169
        if (!snmp_strcat
 
1170
            (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
 
1171
            return 0;
 
1172
        }
 
1173
    }
 
1174
    uptimeString(*(u_long *) (var->val.integer), timebuf);
 
1175
    if (!snmp_strcat
 
1176
        (buf, buf_len, out_len, allow_realloc, (const u_char *) timebuf)) {
 
1177
        return 0;
 
1178
    }
 
1179
    if (units) {
 
1180
        return (snmp_strcat
 
1181
                (buf, buf_len, out_len, allow_realloc,
 
1182
                 (const u_char *) " ")
 
1183
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
1184
                               (const u_char *) units));
 
1185
    }
 
1186
    return 1;
 
1187
}
 
1188
 
 
1189
 
 
1190
/**
 
1191
 * Prints an integer according to the hint into a buffer.
 
1192
 *
 
1193
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1194
 * needed size. (Note: *buf may change due to this.)
 
1195
 * 
 
1196
 * @param buf      Address of the buffer to print to.
 
1197
 * @param buf_len  Address to an integer containing the size of buf.
 
1198
 * @param out_len  Incremented by the number of characters printed.
 
1199
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1200
 *                      needed size.
 
1201
 * @param var      The variable to encode.
 
1202
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1203
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1204
 *                 See RFC 1903 Section 3.1 for details. may _NOT_ be NULL.
 
1205
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1206
 * 
 
1207
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1208
 *         small when not allowed to realloc.)
 
1209
 */
 
1210
int
 
1211
sprint_realloc_hinted_integer(u_char ** buf, size_t * buf_len,
 
1212
                              size_t * out_len, int allow_realloc,
 
1213
                              long val, const char decimaltype,
 
1214
                              const char *hint, const char *units)
 
1215
{
 
1216
    char            fmt[10] = "%l@", tmp[256];
 
1217
    int             shift, len;
 
1218
 
 
1219
    if (hint[1] == '-') {
 
1220
        shift = atoi(hint + 2);
 
1221
    } else {
 
1222
        shift = 0;
 
1223
    }
 
1224
 
 
1225
    if (hint[0] == 'd') {
 
1226
        /*
 
1227
         * We might *actually* want a 'u' here.  
 
1228
         */
 
1229
        fmt[2] = decimaltype;
 
1230
    } else {
 
1231
        /*
 
1232
         * DISPLAY-HINT character is 'b', 'o', or 'x'.  
 
1233
         */
 
1234
        fmt[2] = hint[0];
 
1235
    }
 
1236
 
 
1237
    sprintf(tmp, fmt, val);
 
1238
    if (shift != 0) {
 
1239
        len = strlen(tmp);
 
1240
        if (shift <= len) {
 
1241
            tmp[len + 1] = 0;
 
1242
            while (shift--) {
 
1243
                tmp[len] = tmp[len - 1];
 
1244
                len--;
 
1245
            }
 
1246
            tmp[len] = '.';
 
1247
        } else {
 
1248
            tmp[shift + 1] = 0;
 
1249
            while (shift) {
 
1250
                if (len-- > 0) {
 
1251
                    tmp[shift] = tmp[len];
 
1252
                } else {
 
1253
                    tmp[shift] = '0';
 
1254
                }
 
1255
                shift--;
 
1256
            }
 
1257
            tmp[0] = '.';
 
1258
        }
 
1259
    }
 
1260
    return snmp_strcat(buf, buf_len, out_len, allow_realloc, tmp);
 
1261
}
 
1262
 
 
1263
 
 
1264
/**
 
1265
 * Prints an integer into a buffer.
 
1266
 *
 
1267
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1268
 * needed size. (Note: *buf may change due to this.)
 
1269
 * 
 
1270
 * @param buf      Address of the buffer to print to.
 
1271
 * @param buf_len  Address to an integer containing the size of buf.
 
1272
 * @param out_len  Incremented by the number of characters printed.
 
1273
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1274
 *                      needed size.
 
1275
 * @param var      The variable to encode.
 
1276
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1277
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1278
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1279
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1280
 * 
 
1281
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1282
 *         small when not allowed to realloc.)
 
1283
 */
 
1284
int
 
1285
sprint_realloc_integer(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1286
                       int allow_realloc,
 
1287
                       const netsnmp_variable_list * var,
 
1288
                       const struct enum_list *enums,
 
1289
                       const char *hint, const char *units)
 
1290
{
 
1291
    char           *enum_string = NULL;
 
1292
 
 
1293
    if ((var->type != ASN_INTEGER) && 
 
1294
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1295
        u_char          str[] = "Wrong Type (should be INTEGER): ";
 
1296
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1297
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1298
                                          allow_realloc, var, NULL, NULL,
 
1299
                                          NULL);
 
1300
        } else {
 
1301
            return 0;
 
1302
        }
 
1303
    }
 
1304
    for (; enums; enums = enums->next) {
 
1305
        if (enums->value == *var->val.integer) {
 
1306
            enum_string = enums->label;
 
1307
            break;
 
1308
        }
 
1309
    }
 
1310
 
 
1311
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1312
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
1313
                         (const u_char *) "INTEGER: ")) {
 
1314
            return 0;
 
1315
        }
 
1316
    }
 
1317
 
 
1318
    if (enum_string == NULL ||
 
1319
        netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) {
 
1320
        if (hint) {
 
1321
            if (!(sprint_realloc_hinted_integer(buf, buf_len, out_len,
 
1322
                                                allow_realloc,
 
1323
                                                *var->val.integer, 'd',
 
1324
                                                hint, units))) {
 
1325
                return 0;
 
1326
            }
 
1327
        } else {
 
1328
            char            str[16];
 
1329
            sprintf(str, "%ld", *var->val.integer);
 
1330
            if (!snmp_strcat
 
1331
                (buf, buf_len, out_len, allow_realloc,
 
1332
                 (const u_char *) str)) {
 
1333
                return 0;
 
1334
            }
 
1335
        }
 
1336
    } else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1337
        if (!snmp_strcat
 
1338
            (buf, buf_len, out_len, allow_realloc,
 
1339
             (const u_char *) enum_string)) {
 
1340
            return 0;
 
1341
        }
 
1342
    } else {
 
1343
        char            str[16];
 
1344
        sprintf(str, "(%ld)", *var->val.integer);
 
1345
        if (!snmp_strcat
 
1346
            (buf, buf_len, out_len, allow_realloc,
 
1347
             (const u_char *) enum_string)) {
 
1348
            return 0;
 
1349
        }
 
1350
        if (!snmp_strcat
 
1351
            (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
 
1352
            return 0;
 
1353
        }
 
1354
    }
 
1355
 
 
1356
    if (units) {
 
1357
        return (snmp_strcat
 
1358
                (buf, buf_len, out_len, allow_realloc,
 
1359
                 (const u_char *) " ")
 
1360
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
1361
                               (const u_char *) units));
 
1362
    }
 
1363
    return 1;
 
1364
}
 
1365
 
 
1366
 
 
1367
/**
 
1368
 * Prints an unsigned integer into a buffer.
 
1369
 *
 
1370
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1371
 * needed size. (Note: *buf may change due to this.)
 
1372
 * 
 
1373
 * @param buf      Address of the buffer to print to.
 
1374
 * @param buf_len  Address to an integer containing the size of buf.
 
1375
 * @param out_len  Incremented by the number of characters printed.
 
1376
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1377
 *                      needed size.
 
1378
 * @param var      The variable to encode.
 
1379
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1380
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1381
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1382
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1383
 * 
 
1384
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1385
 *         small when not allowed to realloc.)
 
1386
 */
 
1387
int
 
1388
sprint_realloc_uinteger(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1389
                        int allow_realloc,
 
1390
                        const netsnmp_variable_list * var,
 
1391
                        const struct enum_list *enums,
 
1392
                        const char *hint, const char *units)
 
1393
{
 
1394
    char           *enum_string = NULL;
 
1395
 
 
1396
    if ((var->type != ASN_UINTEGER) && 
 
1397
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1398
        u_char          str[] = "Wrong Type (should be UInteger32): ";
 
1399
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1400
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1401
                                          allow_realloc, var, NULL, NULL,
 
1402
                                          NULL);
 
1403
        } else {
 
1404
            return 0;
 
1405
        }
 
1406
    }
 
1407
 
 
1408
    for (; enums; enums = enums->next) {
 
1409
        if (enums->value == *var->val.integer) {
 
1410
            enum_string = enums->label;
 
1411
            break;
 
1412
        }
 
1413
    }
 
1414
 
 
1415
    if (enum_string == NULL ||
 
1416
        netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) {
 
1417
        if (hint) {
 
1418
            if (!(sprint_realloc_hinted_integer(buf, buf_len, out_len,
 
1419
                                                allow_realloc,
 
1420
                                                *var->val.integer, 'u',
 
1421
                                                hint, units))) {
 
1422
                return 0;
 
1423
            }
 
1424
        } else {
 
1425
            char            str[16];
 
1426
            sprintf(str, "%lu", *var->val.integer);
 
1427
            if (!snmp_strcat
 
1428
                (buf, buf_len, out_len, allow_realloc,
 
1429
                 (const u_char *) str)) {
 
1430
                return 0;
 
1431
            }
 
1432
        }
 
1433
    } else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1434
        if (!snmp_strcat
 
1435
            (buf, buf_len, out_len, allow_realloc,
 
1436
             (const u_char *) enum_string)) {
 
1437
            return 0;
 
1438
        }
 
1439
    } else {
 
1440
        char            str[16];
 
1441
        sprintf(str, "(%lu)", *var->val.integer);
 
1442
        if (!snmp_strcat
 
1443
            (buf, buf_len, out_len, allow_realloc,
 
1444
             (const u_char *) enum_string)) {
 
1445
            return 0;
 
1446
        }
 
1447
        if (!snmp_strcat
 
1448
            (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
 
1449
            return 0;
 
1450
        }
 
1451
    }
 
1452
 
 
1453
    if (units) {
 
1454
        return (snmp_strcat
 
1455
                (buf, buf_len, out_len, allow_realloc,
 
1456
                 (const u_char *) " ")
 
1457
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
1458
                               (const u_char *) units));
 
1459
    }
 
1460
    return 1;
 
1461
}
 
1462
 
 
1463
 
 
1464
/**
 
1465
 * Prints a gauge value into a buffer.
 
1466
 *
 
1467
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1468
 * needed size. (Note: *buf may change due to this.)
 
1469
 * 
 
1470
 * @param buf      Address of the buffer to print to.
 
1471
 * @param buf_len  Address to an integer containing the size of buf.
 
1472
 * @param out_len  Incremented by the number of characters printed.
 
1473
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1474
 *                      needed size.
 
1475
 * @param var      The variable to encode.
 
1476
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1477
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1478
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1479
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1480
 * 
 
1481
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1482
 *         small when not allowed to realloc.)
 
1483
 */
 
1484
int
 
1485
sprint_realloc_gauge(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1486
                     int allow_realloc,
 
1487
                     const netsnmp_variable_list * var,
 
1488
                     const struct enum_list *enums,
 
1489
                     const char *hint, const char *units)
 
1490
{
 
1491
    char            tmp[32];
 
1492
 
 
1493
    if ((var->type != ASN_GAUGE) && 
 
1494
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1495
        u_char          str[] =
 
1496
            "Wrong Type (should be Gauge32 or Unsigned32): ";
 
1497
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1498
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1499
                                          allow_realloc, var, NULL, NULL,
 
1500
                                          NULL);
 
1501
        } else {
 
1502
            return 0;
 
1503
        }
 
1504
    }
 
1505
 
 
1506
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1507
        u_char          str[] = "Gauge32: ";
 
1508
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1509
            return 0;
 
1510
        }
 
1511
    }
 
1512
    if (hint) {
 
1513
        if (!sprint_realloc_hinted_integer(buf, buf_len, out_len,
 
1514
                                           allow_realloc,
 
1515
                                           *var->val.integer, 'u', hint,
 
1516
                                           units)) {
 
1517
            return 0;
 
1518
        }
 
1519
    } else {
 
1520
        sprintf(tmp, "%lu", *var->val.integer);
 
1521
        if (!snmp_strcat
 
1522
            (buf, buf_len, out_len, allow_realloc, (const u_char *) tmp)) {
 
1523
            return 0;
 
1524
        }
 
1525
    }
 
1526
    if (units) {
 
1527
        return (snmp_strcat
 
1528
                (buf, buf_len, out_len, allow_realloc,
 
1529
                 (const u_char *) " ")
 
1530
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
1531
                               (const u_char *) units));
 
1532
    }
 
1533
    return 1;
 
1534
}
 
1535
 
 
1536
 
 
1537
/**
 
1538
 * Prints a counter value into a buffer.
 
1539
 *
 
1540
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1541
 * needed size. (Note: *buf may change due to this.)
 
1542
 * 
 
1543
 * @param buf      Address of the buffer to print to.
 
1544
 * @param buf_len  Address to an integer containing the size of buf.
 
1545
 * @param out_len  Incremented by the number of characters printed.
 
1546
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1547
 *                      needed size.
 
1548
 * @param var      The variable to encode.
 
1549
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1550
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1551
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1552
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1553
 * 
 
1554
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1555
 *         small when not allowed to realloc.)
 
1556
 */
 
1557
int
 
1558
sprint_realloc_counter(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1559
                       int allow_realloc,
 
1560
                       const netsnmp_variable_list * var,
 
1561
                       const struct enum_list *enums,
 
1562
                       const char *hint, const char *units)
 
1563
{
 
1564
    char            tmp[32];
 
1565
 
 
1566
    if ((var->type != ASN_COUNTER) && 
 
1567
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1568
        u_char          str[] = "Wrong Type (should be Counter32): ";
 
1569
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1570
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1571
                                          allow_realloc, var, NULL, NULL,
 
1572
                                          NULL);
 
1573
        } else {
 
1574
            return 0;
 
1575
        }
 
1576
    }
 
1577
 
 
1578
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1579
        u_char          str[] = "Counter32: ";
 
1580
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1581
            return 0;
 
1582
        }
 
1583
    }
 
1584
    sprintf(tmp, "%lu", *var->val.integer);
 
1585
    if (!snmp_strcat
 
1586
        (buf, buf_len, out_len, allow_realloc, (const u_char *) tmp)) {
 
1587
        return 0;
 
1588
    }
 
1589
    if (units) {
 
1590
        return (snmp_strcat
 
1591
                (buf, buf_len, out_len, allow_realloc,
 
1592
                 (const u_char *) " ")
 
1593
                && snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
1594
                               (const u_char *) units));
 
1595
    }
 
1596
    return 1;
 
1597
}
 
1598
 
 
1599
 
 
1600
/**
 
1601
 * Prints a network address into a buffer.
 
1602
 *
 
1603
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1604
 * needed size. (Note: *buf may change due to this.)
 
1605
 * 
 
1606
 * @param buf      Address of the buffer to print to.
 
1607
 * @param buf_len  Address to an integer containing the size of buf.
 
1608
 * @param out_len  Incremented by the number of characters printed.
 
1609
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1610
 *                      needed size.
 
1611
 * @param var      The variable to encode.
 
1612
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1613
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1614
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1615
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1616
 * 
 
1617
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1618
 *         small when not allowed to realloc.)
 
1619
 */
 
1620
int
 
1621
sprint_realloc_networkaddress(u_char ** buf, size_t * buf_len,
 
1622
                              size_t * out_len, int allow_realloc,
 
1623
                              const netsnmp_variable_list * var,
 
1624
                              const struct enum_list *enums, const char *hint,
 
1625
                              const char *units)
 
1626
{
 
1627
    size_t          i;
 
1628
 
 
1629
    if ((var->type != ASN_IPADDRESS) && 
 
1630
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1631
        u_char          str[] = "Wrong Type (should be NetworkAddress): ";
 
1632
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1633
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1634
                                          allow_realloc, var, NULL, NULL,
 
1635
                                          NULL);
 
1636
        } else {
 
1637
            return 0;
 
1638
        }
 
1639
    }
 
1640
 
 
1641
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1642
        u_char          str[] = "Network Address: ";
 
1643
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1644
            return 0;
 
1645
        }
 
1646
    }
 
1647
 
 
1648
    while ((*out_len + (var->val_len * 3) + 2) >= *buf_len) {
 
1649
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
1650
            return 0;
 
1651
        }
 
1652
    }
 
1653
 
 
1654
    for (i = 0; i < var->val_len; i++) {
 
1655
        sprintf((char *) (*buf + *out_len), "%02X", var->val.string[i]);
 
1656
        *out_len += 2;
 
1657
        if (i < var->val_len - 1) {
 
1658
            *(*buf + *out_len) = ':';
 
1659
            (*out_len)++;
 
1660
        }
 
1661
    }
 
1662
    return 1;
 
1663
}
 
1664
 
 
1665
 
 
1666
/**
 
1667
 * Prints an ip-address into a buffer.
 
1668
 *
 
1669
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1670
 * needed size. (Note: *buf may change due to this.)
 
1671
 * 
 
1672
 * @param buf      Address of the buffer to print to.
 
1673
 * @param buf_len  Address to an integer containing the size of buf.
 
1674
 * @param out_len  Incremented by the number of characters printed.
 
1675
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1676
 *                      needed size.
 
1677
 * @param var      The variable to encode.
 
1678
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1679
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1680
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1681
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1682
 * 
 
1683
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1684
 *         small when not allowed to realloc.)
 
1685
 */
 
1686
int
 
1687
sprint_realloc_ipaddress(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1688
                         int allow_realloc,
 
1689
                         const netsnmp_variable_list * var,
 
1690
                         const struct enum_list *enums,
 
1691
                         const char *hint, const char *units)
 
1692
{
 
1693
    u_char         *ip = var->val.string;
 
1694
 
 
1695
    if ((var->type != ASN_IPADDRESS) && 
 
1696
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1697
        u_char          str[] = "Wrong Type (should be IpAddress): ";
 
1698
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1699
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1700
                                          allow_realloc, var, NULL, NULL,
 
1701
                                          NULL);
 
1702
        } else {
 
1703
            return 0;
 
1704
        }
 
1705
    }
 
1706
 
 
1707
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1708
        u_char          str[] = "IpAddress: ";
 
1709
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1710
            return 0;
 
1711
        }
 
1712
    }
 
1713
    while ((*out_len + 17) >= *buf_len) {
 
1714
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
1715
            return 0;
 
1716
        }
 
1717
    }
 
1718
    if (ip)
 
1719
        sprintf((char *) (*buf + *out_len), "%d.%d.%d.%d",
 
1720
                                            ip[0], ip[1], ip[2], ip[3]);
 
1721
    *out_len += strlen((char *) (*buf + *out_len));
 
1722
    return 1;
 
1723
}
 
1724
 
 
1725
 
 
1726
/**
 
1727
 * Prints a null value into a buffer.
 
1728
 *
 
1729
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1730
 * needed size. (Note: *buf may change due to this.)
 
1731
 * 
 
1732
 * @param buf      Address of the buffer to print to.
 
1733
 * @param buf_len  Address to an integer containing the size of buf.
 
1734
 * @param out_len  Incremented by the number of characters printed.
 
1735
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1736
 *                      needed size.
 
1737
 * @param var      The variable to encode.
 
1738
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1739
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1740
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1741
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1742
 * 
 
1743
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1744
 *         small when not allowed to realloc.)
 
1745
 */
 
1746
int
 
1747
sprint_realloc_null(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1748
                    int allow_realloc,
 
1749
                    const netsnmp_variable_list * var,
 
1750
                    const struct enum_list *enums,
 
1751
                    const char *hint, const char *units)
 
1752
{
 
1753
    if ((var->type != ASN_NULL) && 
 
1754
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1755
        u_char          str[] = "Wrong Type (should be NULL): ";
 
1756
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1757
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1758
                                          allow_realloc, var, NULL, NULL,
 
1759
                                          NULL);
 
1760
        } else {
 
1761
            return 0;
 
1762
        }
 
1763
    } else {
 
1764
        u_char          str[] = "NULL";
 
1765
        return snmp_strcat(buf, buf_len, out_len, allow_realloc, str);
 
1766
    }
 
1767
}
 
1768
 
 
1769
 
 
1770
/**
 
1771
 * Prints a bit string into a buffer.
 
1772
 *
 
1773
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1774
 * needed size. (Note: *buf may change due to this.)
 
1775
 * 
 
1776
 * @param buf      Address of the buffer to print to.
 
1777
 * @param buf_len  Address to an integer containing the size of buf.
 
1778
 * @param out_len  Incremented by the number of characters printed.
 
1779
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1780
 *                      needed size.
 
1781
 * @param var      The variable to encode.
 
1782
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1783
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1784
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1785
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1786
 * 
 
1787
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1788
 *         small when not allowed to realloc.)
 
1789
 */
 
1790
int
 
1791
sprint_realloc_bitstring(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1792
                         int allow_realloc,
 
1793
                         const netsnmp_variable_list * var,
 
1794
                         const struct enum_list *enums,
 
1795
                         const char *hint, const char *units)
 
1796
{
 
1797
    int             len, bit;
 
1798
    u_char         *cp;
 
1799
    char           *enum_string;
 
1800
 
 
1801
    if ((var->type != ASN_BIT_STR && var->type != ASN_OCTET_STR) &&
 
1802
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1803
        u_char          str[] = "Wrong Type (should be BITS): ";
 
1804
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1805
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1806
                                          allow_realloc, var, NULL, NULL,
 
1807
                                          NULL);
 
1808
        } else {
 
1809
            return 0;
 
1810
        }
 
1811
    }
 
1812
 
 
1813
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1814
        u_char          str[] = "\"";
 
1815
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1816
            return 0;
 
1817
        }
 
1818
    } else {
 
1819
        u_char          str[] = "BITS: ";
 
1820
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1821
            return 0;
 
1822
        }
 
1823
    }
 
1824
    if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc,
 
1825
                                  var->val.bitstring, var->val_len)) {
 
1826
        return 0;
 
1827
    }
 
1828
 
 
1829
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1830
        u_char          str[] = "\"";
 
1831
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1832
            return 0;
 
1833
        }
 
1834
    } else {
 
1835
        cp = var->val.bitstring;
 
1836
        for (len = 0; len < (int) var->val_len; len++) {
 
1837
            for (bit = 0; bit < 8; bit++) {
 
1838
                if (*cp & (0x80 >> bit)) {
 
1839
                    enum_string = NULL;
 
1840
                    for (; enums; enums = enums->next) {
 
1841
                        if (enums->value == (len * 8) + bit) {
 
1842
                            enum_string = enums->label;
 
1843
                            break;
 
1844
                        }
 
1845
                    }
 
1846
                    if (enum_string == NULL ||
 
1847
                        netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
 
1848
                                       NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) {
 
1849
                        char            str[16];
 
1850
                        sprintf(str, "%d ", (len * 8) + bit);
 
1851
                        if (!snmp_strcat
 
1852
                            (buf, buf_len, out_len, allow_realloc,
 
1853
                             (const u_char *) str)) {
 
1854
                            return 0;
 
1855
                        }
 
1856
                    } else {
 
1857
                        char            str[16];
 
1858
                        sprintf(str, "(%d) ", (len * 8) + bit);
 
1859
                        if (!snmp_strcat
 
1860
                            (buf, buf_len, out_len, allow_realloc,
 
1861
                             (const u_char *) enum_string)) {
 
1862
                            return 0;
 
1863
                        }
 
1864
                        if (!snmp_strcat
 
1865
                            (buf, buf_len, out_len, allow_realloc,
 
1866
                             (const u_char *) str)) {
 
1867
                            return 0;
 
1868
                        }
 
1869
                    }
 
1870
                }
 
1871
            }
 
1872
            cp++;
 
1873
        }
 
1874
    }
 
1875
    return 1;
 
1876
}
 
1877
 
 
1878
int
 
1879
sprint_realloc_nsapaddress(u_char ** buf, size_t * buf_len,
 
1880
                           size_t * out_len, int allow_realloc,
 
1881
                           const netsnmp_variable_list * var,
 
1882
                           const struct enum_list *enums, const char *hint,
 
1883
                           const char *units)
 
1884
{
 
1885
    if ((var->type != ASN_NSAP) && 
 
1886
        (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) {
 
1887
        u_char          str[] = "Wrong Type (should be NsapAddress): ";
 
1888
        if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1889
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
1890
                                          allow_realloc, var, NULL, NULL,
 
1891
                                          NULL);
 
1892
        } else {
 
1893
            return 0;
 
1894
        }
 
1895
    }
 
1896
 
 
1897
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
1898
        u_char          str[] = "NsapAddress: ";
 
1899
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
 
1900
            return 0;
 
1901
        }
 
1902
    }
 
1903
 
 
1904
    return sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc,
 
1905
                                    var->val.string, var->val_len);
 
1906
}
 
1907
 
 
1908
 
 
1909
/**
 
1910
 * Fallback routine for a bad type, prints "Variable has bad type" into a buffer.
 
1911
 *
 
1912
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1913
 * needed size. (Note: *buf may change due to this.)
 
1914
 * 
 
1915
 * @param buf      Address of the buffer to print to.
 
1916
 * @param buf_len  Address to an integer containing the size of buf.
 
1917
 * @param out_len  Incremented by the number of characters printed.
 
1918
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1919
 *                      needed size.
 
1920
 * @param var      The variable to encode.
 
1921
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1922
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1923
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1924
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1925
 * 
 
1926
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1927
 *         small when not allowed to realloc.)
 
1928
 */
 
1929
int
 
1930
sprint_realloc_badtype(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1931
                       int allow_realloc,
 
1932
                       const netsnmp_variable_list * var,
 
1933
                       const struct enum_list *enums,
 
1934
                       const char *hint, const char *units)
 
1935
{
 
1936
    u_char          str[] = "Variable has bad type";
 
1937
 
 
1938
    return snmp_strcat(buf, buf_len, out_len, allow_realloc, str);
 
1939
}
 
1940
 
 
1941
 
 
1942
 
 
1943
/**
 
1944
 * Universal print routine, prints a variable into a buffer according to the variable 
 
1945
 * type.
 
1946
 *
 
1947
 * If allow_realloc is true the buffer will be (re)allocated to fit in the 
 
1948
 * needed size. (Note: *buf may change due to this.)
 
1949
 * 
 
1950
 * @param buf      Address of the buffer to print to.
 
1951
 * @param buf_len  Address to an integer containing the size of buf.
 
1952
 * @param out_len  Incremented by the number of characters printed.
 
1953
 * @param allow_realloc if not zero reallocate the buffer to fit the 
 
1954
 *                      needed size.
 
1955
 * @param var      The variable to encode.
 
1956
 * @param enums    The enumeration ff this variable is enumerated. may be NULL.
 
1957
 * @param hint     Contents of the DISPLAY-HINT clause of the MIB.
 
1958
 *                 See RFC 1903 Section 3.1 for details. may be NULL.
 
1959
 * @param units    Contents of the UNITS clause of the MIB. may be NULL.
 
1960
 * 
 
1961
 * @return 1 on success, or 0 on failure (out of memory, or buffer to
 
1962
 *         small when not allowed to realloc.)
 
1963
 */
 
1964
int
 
1965
sprint_realloc_by_type(u_char ** buf, size_t * buf_len, size_t * out_len,
 
1966
                       int allow_realloc,
 
1967
                       const netsnmp_variable_list * var,
 
1968
                       const struct enum_list *enums,
 
1969
                       const char *hint, const char *units)
 
1970
{
 
1971
    DEBUGMSGTL(("output", "sprint_by_type, type %d\n", var->type));
 
1972
 
 
1973
    switch (var->type) {
 
1974
    case ASN_INTEGER:
 
1975
        return sprint_realloc_integer(buf, buf_len, out_len, allow_realloc,
 
1976
                                      var, enums, hint, units);
 
1977
    case ASN_OCTET_STR:
 
1978
        return sprint_realloc_octet_string(buf, buf_len, out_len,
 
1979
                                           allow_realloc, var, enums, hint,
 
1980
                                           units);
 
1981
    case ASN_BIT_STR:
 
1982
        return sprint_realloc_bitstring(buf, buf_len, out_len,
 
1983
                                        allow_realloc, var, enums, hint,
 
1984
                                        units);
 
1985
    case ASN_OPAQUE:
 
1986
        return sprint_realloc_opaque(buf, buf_len, out_len, allow_realloc,
 
1987
                                     var, enums, hint, units);
 
1988
    case ASN_OBJECT_ID:
 
1989
        return sprint_realloc_object_identifier(buf, buf_len, out_len,
 
1990
                                                allow_realloc, var, enums,
 
1991
                                                hint, units);
 
1992
    case ASN_TIMETICKS:
 
1993
        return sprint_realloc_timeticks(buf, buf_len, out_len,
 
1994
                                        allow_realloc, var, enums, hint,
 
1995
                                        units);
 
1996
    case ASN_GAUGE:
 
1997
        return sprint_realloc_gauge(buf, buf_len, out_len, allow_realloc,
 
1998
                                    var, enums, hint, units);
 
1999
    case ASN_COUNTER:
 
2000
        return sprint_realloc_counter(buf, buf_len, out_len, allow_realloc,
 
2001
                                      var, enums, hint, units);
 
2002
    case ASN_IPADDRESS:
 
2003
        return sprint_realloc_ipaddress(buf, buf_len, out_len,
 
2004
                                        allow_realloc, var, enums, hint,
 
2005
                                        units);
 
2006
    case ASN_NULL:
 
2007
        return sprint_realloc_null(buf, buf_len, out_len, allow_realloc,
 
2008
                                   var, enums, hint, units);
 
2009
    case ASN_UINTEGER:
 
2010
        return sprint_realloc_uinteger(buf, buf_len, out_len,
 
2011
                                       allow_realloc, var, enums, hint,
 
2012
                                       units);
 
2013
    case ASN_COUNTER64:
 
2014
#ifdef OPAQUE_SPECIAL_TYPES
 
2015
    case ASN_OPAQUE_U64:
 
2016
    case ASN_OPAQUE_I64:
 
2017
    case ASN_OPAQUE_COUNTER64:
 
2018
#endif                          /* OPAQUE_SPECIAL_TYPES */
 
2019
        return sprint_realloc_counter64(buf, buf_len, out_len,
 
2020
                                        allow_realloc, var, enums, hint,
 
2021
                                        units);
 
2022
#ifdef OPAQUE_SPECIAL_TYPES
 
2023
    case ASN_OPAQUE_FLOAT:
 
2024
        return sprint_realloc_float(buf, buf_len, out_len, allow_realloc,
 
2025
                                    var, enums, hint, units);
 
2026
    case ASN_OPAQUE_DOUBLE:
 
2027
        return sprint_realloc_double(buf, buf_len, out_len, allow_realloc,
 
2028
                                     var, enums, hint, units);
 
2029
#endif                          /* OPAQUE_SPECIAL_TYPES */
 
2030
    default:
 
2031
        DEBUGMSGTL(("sprint_by_type", "bad type: %d\n", var->type));
 
2032
        return sprint_realloc_badtype(buf, buf_len, out_len, allow_realloc,
 
2033
                                      var, enums, hint, units);
 
2034
    }
 
2035
}
 
2036
 
 
2037
 
 
2038
#ifndef DISABLE_MIB_LOADING
 
2039
/**
 
2040
 * Retrieves the tree head.
 
2041
 *
 
2042
 * @return the tree head.
 
2043
 */
 
2044
struct tree    *
 
2045
get_tree_head(void)
 
2046
{
 
2047
    return (tree_head);
 
2048
}
 
2049
 
 
2050
static char    *confmibdir = NULL;
 
2051
static char    *confmibs = NULL;
 
2052
 
 
2053
static void
 
2054
handle_mibdirs_conf(const char *token, char *line)
 
2055
{
 
2056
    char           *ctmp;
 
2057
 
 
2058
    if (confmibdir) {
 
2059
        ctmp = (char *) malloc(strlen(confmibdir) + strlen(line) + 2);
 
2060
        if (!ctmp) {
 
2061
            DEBUGMSGTL(("read_config:initmib", "mibdir conf malloc failed"));
 
2062
            return;
 
2063
        }
 
2064
        if (*line == '+')
 
2065
            line++;
 
2066
        sprintf(ctmp, "%s%c%s", confmibdir, ENV_SEPARATOR_CHAR, line);
 
2067
        SNMP_FREE(confmibdir);
 
2068
        confmibdir = ctmp;
 
2069
    } else {
 
2070
        confmibdir = strdup(line);
 
2071
    }
 
2072
    DEBUGMSGTL(("read_config:initmib", "using mibdirs: %s\n", confmibdir));
 
2073
}
 
2074
 
 
2075
static void
 
2076
handle_mibs_conf(const char *token, char *line)
 
2077
{
 
2078
    char           *ctmp;
 
2079
 
 
2080
    if (confmibs) {
 
2081
        ctmp = (char *) malloc(strlen(confmibs) + strlen(line) + 2);
 
2082
        if (!ctmp) {
 
2083
            DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed"));
 
2084
            return;
 
2085
        }
 
2086
        if (*line == '+')
 
2087
            line++;
 
2088
        sprintf(ctmp, "%s%c%s", confmibs, ENV_SEPARATOR_CHAR, line);
 
2089
        SNMP_FREE(confmibs);
 
2090
        confmibs = ctmp;
 
2091
    } else {
 
2092
        confmibs = strdup(line);
 
2093
    }
 
2094
    DEBUGMSGTL(("read_config:initmib", "using mibs: %s\n", confmibs));
 
2095
}
 
2096
 
 
2097
 
 
2098
static void
 
2099
handle_mibfile_conf(const char *token, char *line)
 
2100
{
 
2101
    DEBUGMSGTL(("read_config:initmib", "reading mibfile: %s\n", line));
 
2102
    read_mib(line);
 
2103
}
 
2104
#endif
 
2105
 
 
2106
static void
 
2107
handle_print_numeric(const char *token, char *line)
 
2108
{
 
2109
    const char *value;
 
2110
 
 
2111
    value = strtok(line, " \t\n");
 
2112
    if ((strcasecmp(value, "yes")  == 0) || 
 
2113
        (strcasecmp(value, "true") == 0) ||
 
2114
        (*value == '1')) {
 
2115
 
 
2116
        netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
 
2117
                                                  NETSNMP_OID_OUTPUT_NUMERIC);
 
2118
    }
 
2119
}
 
2120
 
 
2121
char           *
 
2122
snmp_out_toggle_options(char *options)
 
2123
{
 
2124
    while (*options) {
 
2125
        switch (*options++) {
 
2126
        case 'a':
 
2127
            netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT,
 
2128
                                                      NETSNMP_STRING_OUTPUT_ASCII);
 
2129
            break;
 
2130
        case 'b':
 
2131
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS);
 
2132
            break;
 
2133
        case 'e':
 
2134
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
 
2135
            break;
 
2136
        case 'E':
 
2137
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES);
 
2138
            break;
 
2139
        case 'f':
 
2140
            netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
 
2141
                                                      NETSNMP_OID_OUTPUT_FULL);
 
2142
            break;
 
2143
        case 'n':
 
2144
            netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
 
2145
                                                      NETSNMP_OID_OUTPUT_NUMERIC);
 
2146
            break;
 
2147
        case 'q':
 
2148
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
 
2149
            break;
 
2150
        case 'Q':
 
2151
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT, 1);
 
2152
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
 
2153
            break;
 
2154
        case 's':
 
2155
            netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
 
2156
                                                      NETSNMP_OID_OUTPUT_SUFFIX);
 
2157
            break;
 
2158
        case 'S':
 
2159
            netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
 
2160
                                                      NETSNMP_OID_OUTPUT_MODULE);
 
2161
            break;
 
2162
        case 't':
 
2163
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS);
 
2164
            break;
 
2165
        case 'T':
 
2166
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT);
 
2167
            break;
 
2168
        case 'u':
 
2169
            netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
 
2170
                                                      NETSNMP_OID_OUTPUT_UCD);
 
2171
            break;
 
2172
        case 'U':
 
2173
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS);
 
2174
            break;
 
2175
        case 'v':
 
2176
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE);
 
2177
            break;
 
2178
        case 'x':
 
2179
            netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT,
 
2180
                                                      NETSNMP_STRING_OUTPUT_HEX);
 
2181
            break;
 
2182
        case 'X':
 
2183
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX);
 
2184
            break;
 
2185
        default:
 
2186
            return options - 1;
 
2187
        }
 
2188
    }
 
2189
    return NULL;
 
2190
}
 
2191
 
 
2192
void
 
2193
snmp_out_toggle_options_usage(const char *lead, FILE * outf)
 
2194
{
 
2195
    fprintf(outf, "%sa:  print all strings in ascii format\n", lead);
 
2196
    fprintf(outf, "%sb:  do not break OID indexes down\n", lead);
 
2197
    fprintf(outf, "%se:  print enums numerically\n", lead);
 
2198
    fprintf(outf, "%sE:  escape quotes in string indices\n", lead);
 
2199
    fprintf(outf, "%sf:  print full OIDs on output\n", lead);
 
2200
    fprintf(outf, "%sn:  print OIDs numerically\n", lead);
 
2201
    fprintf(outf, "%sq:  quick print for easier parsing\n", lead);
 
2202
    fprintf(outf, "%sQ:  quick print with equal-signs\n", lead);    /* @@JDW */
 
2203
    fprintf(outf, "%ss:  print only last symbolic element of OID\n", lead);
 
2204
    fprintf(outf, "%sS:  print MIB module-id plus last element\n", lead);
 
2205
    fprintf(outf, "%st:  print timeticks unparsed as numeric integers\n",
 
2206
            lead);
 
2207
    fprintf(outf,
 
2208
            "%sT:  print human-readable text along with hex strings\n",
 
2209
            lead);
 
2210
    fprintf(outf, "%su:  print OIDs using UCD-style prefix suppression\n",
 
2211
            lead);
 
2212
    fprintf(outf, "%sU:  don't print units\n", lead);
 
2213
    fprintf(outf, "%sv:  print values only (not OID = value)\n", lead);
 
2214
    fprintf(outf, "%sx:  print all strings in hex format\n", lead);
 
2215
    fprintf(outf, "%sX:  extended index format\n", lead);
 
2216
}
 
2217
 
 
2218
char *
 
2219
snmp_in_options(char *optarg, int argc, char *const *argv)
 
2220
{
 
2221
    char *cp;
 
2222
 
 
2223
    for (cp = optarg; *cp; cp++) {
 
2224
        switch (*cp) {
 
2225
        case 'b':
 
2226
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REGEX_ACCESS);
 
2227
            break;
 
2228
        case 'R':
 
2229
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS);
 
2230
            break;
 
2231
        case 'r':
 
2232
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE);
 
2233
            break;
 
2234
        case 'h':
 
2235
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT);
 
2236
            break;
 
2237
        case 'u':
 
2238
            netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID);
 
2239
            break;
 
2240
        case 's':
 
2241
            /* What if argc/argv are null ? */
 
2242
            if (!*(++cp))
 
2243
                cp = argv[optind++];
 
2244
            netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
 
2245
                                  NETSNMP_DS_LIB_OIDSUFFIX,
 
2246
                                  cp);
 
2247
            return NULL;
 
2248
 
 
2249
        case 'S':
 
2250
            /* What if argc/argv are null ? */
 
2251
            if (!*(++cp))
 
2252
                cp = argv[optind++];
 
2253
            netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
 
2254
                                  NETSNMP_DS_LIB_OIDPREFIX,
 
2255
                                  cp);
 
2256
            return NULL;
 
2257
 
 
2258
        default:
 
2259
           /*
 
2260
            *  Here?  Or in snmp_parse_args?
 
2261
            snmp_log(LOG_ERR, "Unknown input option passed to -I: %c.\n", *cp);
 
2262
            */
 
2263
            return cp;
 
2264
        }
 
2265
    }
 
2266
    return NULL;
 
2267
}
 
2268
 
 
2269
char           *
 
2270
snmp_in_toggle_options(char *options)
 
2271
{
 
2272
    return snmp_in_options( options, 0, NULL );
 
2273
}
 
2274
 
 
2275
 
 
2276
/**
 
2277
 * Prints out a help usage for the in* toggle options.
 
2278
 *
 
2279
 * @param lead      The lead to print for every line.
 
2280
 * @param outf      The file descriptor to write to.
 
2281
 * 
 
2282
 */
 
2283
void
 
2284
snmp_in_toggle_options_usage(const char *lead, FILE * outf)
 
2285
{
 
2286
    fprintf(outf, "%sb:  do best/regex matching to find a MIB node\n", lead);
 
2287
    fprintf(outf, "%sh:  don't apply DISPLAY-HINTs\n", lead);
 
2288
    fprintf(outf, "%sr:  do not check values for range/type legality\n", lead);
 
2289
    fprintf(outf, "%sR:  do random access to OID labels\n", lead);
 
2290
    fprintf(outf,
 
2291
            "%su:  top-level OIDs must have '.' prefix (UCD-style)\n", lead);
 
2292
    fprintf(outf,
 
2293
            "%ss SUFFIX:  Append all textual OIDs with SUFFIX before parsing\n",
 
2294
            lead);
 
2295
    fprintf(outf,
 
2296
            "%sS PREFIX:  Prepend all textual OIDs with PREFIX before parsing\n",
 
2297
            lead);
 
2298
}
 
2299
 
 
2300
/***
 
2301
 *
 
2302
 */ 
 
2303
void
 
2304
register_mib_handlers(void)
 
2305
{
 
2306
#ifndef DISABLE_MIB_LOADING
 
2307
    register_prenetsnmp_mib_handler("snmp", "mibdirs",
 
2308
                                    handle_mibdirs_conf, NULL,
 
2309
                                    "[mib-dirs|+mib-dirs]");
 
2310
    register_prenetsnmp_mib_handler("snmp", "mibs",
 
2311
                                    handle_mibs_conf, NULL,
 
2312
                                    "[mib-tokens|+mib-tokens]");
 
2313
    register_config_handler("snmp", "mibfile",
 
2314
                            handle_mibfile_conf, NULL, "mibfile-to-read");
 
2315
    /*
 
2316
     * register the snmp.conf configuration handlers for default
 
2317
     * parsing behaviour 
 
2318
     */
 
2319
 
 
2320
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "showMibErrors",
 
2321
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_ERRORS);
 
2322
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "strictCommentTerm",
 
2323
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_COMMENT_TERM);
 
2324
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "mibAllowUnderline",
 
2325
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_PARSE_LABEL);
 
2326
    netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "mibWarningLevel",
 
2327
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_WARNINGS);
 
2328
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "mibReplaceWithLatest",
 
2329
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_REPLACE);
 
2330
#endif
 
2331
 
 
2332
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "printNumericEnums",
 
2333
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
 
2334
    register_prenetsnmp_mib_handler("snmp", "printNumericOids",
 
2335
                       handle_print_numeric, NULL, "(1|yes|true|0|no|false)");
 
2336
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "escapeQuotes",
 
2337
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES);
 
2338
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "dontBreakdownOids",
 
2339
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS);
 
2340
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "quickPrinting",
 
2341
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
 
2342
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "numericTimeticks",
 
2343
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS);
 
2344
    netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "oidOutputFormat",
 
2345
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 
2346
    netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "suffixPrinting",
 
2347
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 
2348
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "extendedIndex",
 
2349
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX);
 
2350
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "printHexText",
 
2351
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT);
 
2352
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "printValueOnly",
 
2353
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE);
 
2354
    netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "dontPrintUnits",
 
2355
                       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS);
 
2356
}
 
2357
 
 
2358
#ifndef DISABLE_MIB_LOADING
 
2359
/*
 
2360
 * function : netsnmp_set_mib_directory
 
2361
 *            - This function sets the string of the directories
 
2362
 *              from which the MIB modules will be searched or
 
2363
 *              loaded.
 
2364
 * arguments: const char *dir, which are the directories
 
2365
 *              from which the MIB modules will be searched or
 
2366
 *              loaded.
 
2367
 * returns  : -
 
2368
 */
 
2369
void
 
2370
netsnmp_set_mib_directory(const char *dir)
 
2371
{
 
2372
    const char *newdir;
 
2373
    char *olddir, *tmpdir = NULL;
 
2374
 
 
2375
    DEBUGTRACE;
 
2376
    if (NULL == dir) {
 
2377
        return;
 
2378
    }
 
2379
    
 
2380
    olddir = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
 
2381
                                   NETSNMP_DS_LIB_MIBDIRS);
 
2382
    if (olddir) {
 
2383
        if (*dir == '+') {
 
2384
            /** New dir starts with '+', thus we add it. */
 
2385
            tmpdir = malloc(strlen(dir) + strlen(olddir) + 2);
 
2386
            if (!tmpdir) {
 
2387
                DEBUGMSGTL(("read_config:initmib", "set mibdir malloc failed"));
 
2388
                return;
 
2389
            }
 
2390
            sprintf(tmpdir, "%s%c%s", ++dir, ENV_SEPARATOR_CHAR, olddir);
 
2391
            newdir = tmpdir;
 
2392
        } else {
 
2393
            newdir = dir;
 
2394
        }
 
2395
    } else {
 
2396
        /** If dir starts with '+' skip '+' it. */
 
2397
        newdir = ((*dir == '+') ? ++dir : dir);
 
2398
    }
 
2399
    netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS,
 
2400
                          newdir);
 
2401
 
 
2402
    /** set_string calls strdup, so if we allocated memory, free it */
 
2403
    if (tmpdir == newdir) {
 
2404
        SNMP_FREE(tmpdir);
 
2405
    }
 
2406
}
 
2407
 
 
2408
/*
 
2409
 * function : netsnmp_get_mib_directory
 
2410
 *            - This function returns a string of the directories
 
2411
 *              from which the MIB modules will be searched or
 
2412
 *              loaded.
 
2413
 *              If the value still does not exists, it will be made
 
2414
 *              from the evironment variable 'MIBDIRS' and/or the
 
2415
 *              default.
 
2416
 * arguments: -
 
2417
 * returns  : char * of the directories in which the MIB modules
 
2418
 *            will be searched/loaded.
 
2419
 */
 
2420
 
 
2421
char *
 
2422
netsnmp_get_mib_directory(void)
 
2423
{
 
2424
    char *dir;
 
2425
 
 
2426
    DEBUGTRACE;
 
2427
    dir = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS);
 
2428
    if (dir == NULL) {
 
2429
        DEBUGMSGTL(("get_mib_directory", "no mib directories set\n"));
 
2430
 
 
2431
        /** Check if the environment variable is set */
 
2432
        dir = getenv("MIBDIRS");
 
2433
        if (dir == NULL) {
 
2434
            DEBUGMSGTL(("get_mib_directory", "no mib directories set by environment\n"));
 
2435
            /** Not set use hard coded path */
 
2436
            if (confmibdir == NULL) {
 
2437
                DEBUGMSGTL(("get_mib_directory", "no mib directories set by config\n"));
 
2438
                netsnmp_set_mib_directory(DEFAULT_MIBDIRS);
 
2439
            }
 
2440
            else if (*confmibdir == '+') {
 
2441
                DEBUGMSGTL(("get_mib_directory", "mib directories set by config (but added)\n"));
 
2442
                netsnmp_set_mib_directory(DEFAULT_MIBDIRS);
 
2443
                netsnmp_set_mib_directory(confmibdir);
 
2444
            }
 
2445
            else {
 
2446
                DEBUGMSGTL(("get_mib_directory", "mib directories set by config\n"));
 
2447
                netsnmp_set_mib_directory(confmibdir);
 
2448
            }
 
2449
        } else if (*dir == '+') {
 
2450
            DEBUGMSGTL(("get_mib_directory", "mib directories set by environment (but added)\n"));
 
2451
            netsnmp_set_mib_directory(DEFAULT_MIBDIRS);
 
2452
            netsnmp_set_mib_directory(dir);
 
2453
        } else {
 
2454
            DEBUGMSGTL(("get_mib_directory", "mib directories set by environment\n"));
 
2455
            netsnmp_set_mib_directory(dir);
 
2456
        }
 
2457
        dir = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS);
 
2458
    }
 
2459
    DEBUGMSGTL(("get_mib_directory", "mib directories set '%s'\n", dir));
 
2460
    return(dir);
 
2461
}
 
2462
 
 
2463
/*
 
2464
 * function : netsnmp_fixup_mib_directory
 
2465
 * arguments: -
 
2466
 * returns  : -
 
2467
 */
 
2468
void
 
2469
netsnmp_fixup_mib_directory(void)
 
2470
{
 
2471
    char *homepath = getenv("HOME");
 
2472
    char *mibpath = netsnmp_get_mib_directory();
 
2473
    char *oldmibpath = NULL;
 
2474
    char *ptr_home;
 
2475
    char *new_mibpath;
 
2476
 
 
2477
    DEBUGTRACE;
 
2478
    if (homepath && mibpath) {
 
2479
        DEBUGMSGTL(("fixup_mib_directory", "mib directories '%s'\n", mibpath));
 
2480
        while ((ptr_home = strstr(mibpath, "$HOME"))) {
 
2481
            new_mibpath = (char *)malloc(strlen(mibpath) - strlen("$HOME") +
 
2482
                                         strlen(homepath)+1);
 
2483
            if (new_mibpath) {
 
2484
                *ptr_home = 0; /* null out the spot where we stop copying */
 
2485
                sprintf(new_mibpath, "%s%s%s", mibpath, homepath,
 
2486
                        ptr_home + strlen("$HOME"));
 
2487
                /** swap in the new value and repeat */
 
2488
                mibpath = new_mibpath;
 
2489
                if (oldmibpath != NULL) {
 
2490
                    SNMP_FREE(oldmibpath);
 
2491
                }
 
2492
                oldmibpath = new_mibpath;
 
2493
            } else {
 
2494
                break;
 
2495
            }
 
2496
        }
 
2497
 
 
2498
        netsnmp_set_mib_directory(mibpath);
 
2499
        
 
2500
        /*  The above copies the mibpath for us, so...  */
 
2501
 
 
2502
        if (oldmibpath != NULL) {
 
2503
            SNMP_FREE(oldmibpath);
 
2504
        }
 
2505
 
 
2506
    }
 
2507
 
 
2508
}
 
2509
 
 
2510
/**
 
2511
 * Initialises the mib reader.
 
2512
 *
 
2513
 * Reads in all settings from the environment.
 
2514
 */
 
2515
void
 
2516
init_mib(void)
 
2517
{
 
2518
    const char     *prefix;
 
2519
    char           *env_var, *entry;
 
2520
    PrefixListPtr   pp = &mib_prefixes[0];
 
2521
 
 
2522
    if (Mib)
 
2523
        return;
 
2524
    init_mib_internals();
 
2525
 
 
2526
    /*
 
2527
     * Initialise the MIB directory/ies 
 
2528
     */
 
2529
    netsnmp_fixup_mib_directory();
 
2530
    env_var = strdup(netsnmp_get_mib_directory());
 
2531
 
 
2532
    DEBUGMSGTL(("init_mib",
 
2533
                "Seen MIBDIRS: Looking in '%s' for mib dirs ...\n",
 
2534
                env_var));
 
2535
 
 
2536
    entry = strtok(env_var, ENV_SEPARATOR);
 
2537
    while (entry) {
 
2538
        add_mibdir(entry);
 
2539
        entry = strtok(NULL, ENV_SEPARATOR);
 
2540
    }
 
2541
    SNMP_FREE(env_var);
 
2542
 
 
2543
    init_mib_internals();
 
2544
 
 
2545
    /*
 
2546
     * Read in any modules or mibs requested 
 
2547
     */
 
2548
 
 
2549
    env_var = getenv("MIBS");
 
2550
    if (env_var == NULL) {
 
2551
        if (confmibs != NULL)
 
2552
            env_var = strdup(confmibs);
 
2553
        else
 
2554
            env_var = strdup(DEFAULT_MIBS);
 
2555
    } else {
 
2556
        env_var = strdup(env_var);
 
2557
    }
 
2558
    if (env_var && *env_var == '+') {
 
2559
        entry =
 
2560
            (char *) malloc(strlen(DEFAULT_MIBS) + strlen(env_var) + 2);
 
2561
        if (!entry) {
 
2562
            DEBUGMSGTL(("init_mib", "env mibs malloc failed"));
 
2563
            return;
 
2564
        } else
 
2565
            sprintf(entry, "%s%c%s", DEFAULT_MIBS, ENV_SEPARATOR_CHAR,
 
2566
                env_var + 1);
 
2567
        SNMP_FREE(env_var);
 
2568
        env_var = entry;
 
2569
    }
 
2570
 
 
2571
    DEBUGMSGTL(("init_mib",
 
2572
                "Seen MIBS: Looking in '%s' for mib files ...\n",
 
2573
                env_var));
 
2574
    entry = strtok(env_var, ENV_SEPARATOR);
 
2575
    while (entry) {
 
2576
        if (strcasecmp(entry, DEBUG_ALWAYS_TOKEN) == 0) {
 
2577
            read_all_mibs();
 
2578
        } else if (strstr(entry, "/") != 0) {
 
2579
            read_mib(entry);
 
2580
        } else {
 
2581
            read_module(entry);
 
2582
        }
 
2583
        entry = strtok(NULL, ENV_SEPARATOR);
 
2584
    }
 
2585
    adopt_orphans();
 
2586
    SNMP_FREE(env_var);
 
2587
 
 
2588
    env_var = getenv("MIBFILES");
 
2589
    if (env_var != NULL) {
 
2590
        if (*env_var == '+') {
 
2591
#ifdef DEFAULT_MIBFILES
 
2592
            entry =
 
2593
                (char *) malloc(strlen(DEFAULT_MIBFILES) +
 
2594
                                strlen(env_var) + 2);
 
2595
            if (!entry) {
 
2596
                DEBUGMSGTL(("init_mib", "env mibfiles malloc failed"));
 
2597
            } else
 
2598
                sprintf(entry, "%s%c%s", DEFAULT_MIBFILES, ENV_SEPARATOR_CHAR,
 
2599
                    env_var + 1);
 
2600
            SNMP_FREE(env_var);
 
2601
            env_var = entry;
 
2602
#else
 
2603
            env_var = strdup(env_var + 1);
 
2604
#endif
 
2605
        } else {
 
2606
            env_var = strdup(env_var);
 
2607
        }
 
2608
    } else {
 
2609
#ifdef DEFAULT_MIBFILES
 
2610
        env_var = strdup(DEFAULT_MIBFILES);
 
2611
#endif
 
2612
    }
 
2613
 
 
2614
    if (env_var != 0) {
 
2615
        DEBUGMSGTL(("init_mib",
 
2616
                    "Seen MIBFILES: Looking in '%s' for mib files ...\n",
 
2617
                    env_var));
 
2618
        entry = strtok(env_var, ENV_SEPARATOR);
 
2619
        while (entry) {
 
2620
            read_mib(entry);
 
2621
            entry = strtok(NULL, ENV_SEPARATOR);
 
2622
        }
 
2623
        SNMP_FREE(env_var);
 
2624
    }
 
2625
 
 
2626
    prefix = getenv("PREFIX");
 
2627
 
 
2628
    if (!prefix)
 
2629
        prefix = Standard_Prefix;
 
2630
 
 
2631
    Prefix = (char *) malloc(strlen(prefix) + 2);
 
2632
    if (!Prefix)
 
2633
        DEBUGMSGTL(("init_mib", "Prefix malloc failed"));
 
2634
    else
 
2635
        strcpy(Prefix, prefix);
 
2636
 
 
2637
    DEBUGMSGTL(("init_mib",
 
2638
                "Seen PREFIX: Looking in '%s' for prefix ...\n", Prefix));
 
2639
 
 
2640
    /*
 
2641
     * remove trailing dot 
 
2642
     */
 
2643
    if (Prefix) {
 
2644
        env_var = &Prefix[strlen(Prefix) - 1];
 
2645
        if (*env_var == '.')
 
2646
            *env_var = '\0';
 
2647
    }
 
2648
 
 
2649
    pp->str = Prefix;           /* fixup first mib_prefix entry */
 
2650
    /*
 
2651
     * now that the list of prefixes is built, save each string length. 
 
2652
     */
 
2653
    while (pp->str) {
 
2654
        pp->len = strlen(pp->str);
 
2655
        pp++;
 
2656
    }
 
2657
 
 
2658
    Mib = tree_head;            /* Backwards compatibility */
 
2659
    tree_top = (struct tree *) calloc(1, sizeof(struct tree));
 
2660
    /*
 
2661
     * XX error check ? 
 
2662
     */
 
2663
    if (tree_top) {
 
2664
        tree_top->label = strdup("(top)");
 
2665
        tree_top->child_list = tree_head;
 
2666
    }
 
2667
}
 
2668
 
 
2669
/**
 
2670
 * Unloads all mibs.
 
2671
 */
 
2672
void
 
2673
shutdown_mib(void)
 
2674
{
 
2675
    unload_all_mibs();
 
2676
    if (tree_top) {
 
2677
        if (tree_top->label)
 
2678
            SNMP_FREE(tree_top->label);
 
2679
        SNMP_FREE(tree_top);
 
2680
        tree_top = NULL;
 
2681
    }
 
2682
    tree_head = NULL;
 
2683
    Mib = NULL;
 
2684
    if (Prefix != NULL && Prefix != &Standard_Prefix[0])
 
2685
        SNMP_FREE(Prefix);
 
2686
    if (Prefix)
 
2687
        Prefix = NULL;
 
2688
}
 
2689
 
 
2690
/**
 
2691
 * Prints the MIBs to the file fp.
 
2692
 *
 
2693
 * @param fp   The file descriptor to print to.
 
2694
 */
 
2695
void
 
2696
print_mib(FILE * fp)
 
2697
{
 
2698
    print_subtree(fp, tree_head, 0);
 
2699
}
 
2700
 
 
2701
void
 
2702
print_ascii_dump(FILE * fp)
 
2703
{
 
2704
    fprintf(fp, "dump DEFINITIONS ::= BEGIN\n");
 
2705
    print_ascii_dump_tree(fp, tree_head, 0);
 
2706
    fprintf(fp, "END\n");
 
2707
}
 
2708
 
 
2709
 
 
2710
/**
 
2711
 * Set's the printing function printomat in a subtree according
 
2712
 * it's type
 
2713
 *
 
2714
 * @param subtree    The subtree to set.
 
2715
 */
 
2716
void
 
2717
set_function(struct tree *subtree)
 
2718
{
 
2719
    subtree->printer = NULL;
 
2720
    switch (subtree->type) {
 
2721
    case TYPE_OBJID:
 
2722
        subtree->printomat = sprint_realloc_object_identifier;
 
2723
        break;
 
2724
    case TYPE_OCTETSTR:
 
2725
        subtree->printomat = sprint_realloc_octet_string;
 
2726
        break;
 
2727
    case TYPE_INTEGER:
 
2728
        subtree->printomat = sprint_realloc_integer;
 
2729
        break;
 
2730
    case TYPE_INTEGER32:
 
2731
        subtree->printomat = sprint_realloc_integer;
 
2732
        break;
 
2733
    case TYPE_NETADDR:
 
2734
        subtree->printomat = sprint_realloc_networkaddress;
 
2735
        break;
 
2736
    case TYPE_IPADDR:
 
2737
        subtree->printomat = sprint_realloc_ipaddress;
 
2738
        break;
 
2739
    case TYPE_COUNTER:
 
2740
        subtree->printomat = sprint_realloc_counter;
 
2741
        break;
 
2742
    case TYPE_GAUGE:
 
2743
        subtree->printomat = sprint_realloc_gauge;
 
2744
        break;
 
2745
    case TYPE_TIMETICKS:
 
2746
        subtree->printomat = sprint_realloc_timeticks;
 
2747
        break;
 
2748
    case TYPE_OPAQUE:
 
2749
        subtree->printomat = sprint_realloc_opaque;
 
2750
        break;
 
2751
    case TYPE_NULL:
 
2752
        subtree->printomat = sprint_realloc_null;
 
2753
        break;
 
2754
    case TYPE_BITSTRING:
 
2755
        subtree->printomat = sprint_realloc_bitstring;
 
2756
        break;
 
2757
    case TYPE_NSAPADDRESS:
 
2758
        subtree->printomat = sprint_realloc_nsapaddress;
 
2759
        break;
 
2760
    case TYPE_COUNTER64:
 
2761
        subtree->printomat = sprint_realloc_counter64;
 
2762
        break;
 
2763
    case TYPE_UINTEGER:
 
2764
        subtree->printomat = sprint_realloc_uinteger;
 
2765
        break;
 
2766
    case TYPE_UNSIGNED32:
 
2767
        subtree->printomat = sprint_realloc_gauge;
 
2768
        break;
 
2769
    case TYPE_OTHER:
 
2770
    default:
 
2771
        subtree->printomat = sprint_realloc_by_type;
 
2772
        break;
 
2773
    }
 
2774
}
 
2775
 
 
2776
#endif /* DISABLE_MIB_LOADING */
 
2777
 
 
2778
/**
 
2779
 * Reads an object identifier from an input string into internal OID form.
 
2780
 * 
 
2781
 * When called, out_len must hold the maximum length of the output array.
 
2782
 *
 
2783
 * @param input     the input string.
 
2784
 * @param output    the oid wirte.
 
2785
 * @param out_len   number of subid's in output.
 
2786
 * 
 
2787
 * @return 1 if successful.
 
2788
 * 
 
2789
 * If an error occurs, this function returns 0 and MAY set snmp_errno.
 
2790
 * snmp_errno is NOT set if SET_SNMP_ERROR evaluates to nothing.
 
2791
 * This can make multi-threaded use a tiny bit more robust.
 
2792
 */
 
2793
int
 
2794
read_objid(const char *input, oid * output, size_t * out_len)
 
2795
{                               /* number of subid's in "output" */
 
2796
#ifndef DISABLE_MIB_LOADING
 
2797
    struct tree    *root = tree_top;
 
2798
#endif /* DISABLE_MIB_LOADING */
 
2799
    char            buf[SPRINT_MAX_LEN];
 
2800
    int             ret, max_out_len;
 
2801
    char           *name, ch;
 
2802
    const char     *cp;
 
2803
 
 
2804
    cp = input;
 
2805
    while ((ch = *cp)) {
 
2806
        if (('0' <= ch && ch <= '9')
 
2807
            || ('a' <= ch && ch <= 'z')
 
2808
            || ('A' <= ch && ch <= 'Z')
 
2809
            || ch == '-')
 
2810
            cp++;
 
2811
        else
 
2812
            break;
 
2813
    }
 
2814
#ifndef DISABLE_MIB_LOADING
 
2815
    if (ch == ':')
 
2816
        return get_node(input, output, out_len);
 
2817
#endif /* DISABLE_MIB_LOADING */
 
2818
 
 
2819
    if (*input == '.')
 
2820
        input++;
 
2821
#ifndef DISABLE_MIB_LOADING
 
2822
    else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID)) {
 
2823
        /*
 
2824
         * get past leading '.', append '.' to Prefix. 
 
2825
         */
 
2826
        if (*Prefix == '.')
 
2827
            strncpy(buf, Prefix + 1, sizeof(buf)-1);
 
2828
        else
 
2829
            strncpy(buf, Prefix, sizeof(buf)-1);
 
2830
        buf[ sizeof(buf)-1 ] = 0;
 
2831
        strcat(buf, ".");
 
2832
        buf[ sizeof(buf)-1 ] = 0;
 
2833
        strncat(buf, input, sizeof(buf)-strlen(buf));
 
2834
        buf[ sizeof(buf)-1 ] = 0;
 
2835
        input = buf;
 
2836
    }
 
2837
#endif /* DISABLE_MIB_LOADING */
 
2838
 
 
2839
#ifndef DISABLE_MIB_LOADING
 
2840
    if (root == NULL) {
 
2841
        SET_SNMP_ERROR(SNMPERR_NOMIB);
 
2842
        *out_len = 0;
 
2843
        return 0;
 
2844
    }
 
2845
#endif /* DISABLE_MIB_LOADING */
 
2846
    name = strdup(input);
 
2847
    max_out_len = *out_len;
 
2848
    *out_len = 0;
 
2849
#ifndef DISABLE_MIB_LOADING
 
2850
    if ((ret =
 
2851
         _add_strings_to_oid(root, name, output, out_len,
 
2852
                             max_out_len)) <= 0)
 
2853
#else
 
2854
    if ((ret =
 
2855
         _add_strings_to_oid(NULL, name, output, out_len,
 
2856
                             max_out_len)) <= 0)
 
2857
#endif /* DISABLE_MIB_LOADING */
 
2858
    {
 
2859
        if (ret == 0)
 
2860
            ret = SNMPERR_UNKNOWN_OBJID;
 
2861
        SET_SNMP_ERROR(ret);
 
2862
        SNMP_FREE(name);
 
2863
        return 0;
 
2864
    }
 
2865
    SNMP_FREE(name);
 
2866
 
 
2867
    return 1;
 
2868
}
 
2869
 
 
2870
/**
 
2871
 * 
 
2872
 */
 
2873
void
 
2874
netsnmp_sprint_realloc_objid(u_char ** buf, size_t * buf_len,
 
2875
                             size_t * out_len, int allow_realloc,
 
2876
                             int *buf_overflow,
 
2877
                             const oid * objid, size_t objidlen)
 
2878
{
 
2879
    u_char         *tbuf = NULL, *cp = NULL;
 
2880
    size_t          tbuf_len = 256, tout_len = 0;
 
2881
    int             tbuf_overflow = 0;
 
2882
    int             output_format;
 
2883
 
 
2884
    if ((tbuf = (u_char *) calloc(tbuf_len, 1)) == NULL) {
 
2885
        tbuf_overflow = 1;
 
2886
    } else {
 
2887
        *tbuf = '.';
 
2888
        tout_len = 1;
 
2889
    }
 
2890
 
 
2891
    _oid_finish_printing(objid, objidlen,
 
2892
                         &tbuf, &tbuf_len, &tout_len,
 
2893
                         allow_realloc, &tbuf_overflow);
 
2894
 
 
2895
    if (tbuf_overflow) {
 
2896
        if (!*buf_overflow) {
 
2897
            snmp_strcat(buf, buf_len, out_len, allow_realloc, tbuf);
 
2898
            *buf_overflow = 1;
 
2899
        }
 
2900
        SNMP_FREE(tbuf);
 
2901
        return;
 
2902
    }
 
2903
 
 
2904
    output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 
2905
    if (0 == output_format) {
 
2906
        output_format = NETSNMP_OID_OUTPUT_NUMERIC;
 
2907
    }
 
2908
    switch (output_format) {
 
2909
    case NETSNMP_OID_OUTPUT_FULL:
 
2910
    case NETSNMP_OID_OUTPUT_NUMERIC:
 
2911
    case NETSNMP_OID_OUTPUT_SUFFIX:
 
2912
    case NETSNMP_OID_OUTPUT_MODULE:
 
2913
        cp = tbuf;
 
2914
        break;
 
2915
 
 
2916
    case NETSNMP_OID_OUTPUT_NONE:
 
2917
    default:
 
2918
        cp = NULL;
 
2919
    }
 
2920
 
 
2921
    if (!*buf_overflow &&
 
2922
        !snmp_strcat(buf, buf_len, out_len, allow_realloc, cp)) {
 
2923
        *buf_overflow = 1;
 
2924
    }
 
2925
    SNMP_FREE(tbuf);
 
2926
}
 
2927
 
 
2928
/**
 
2929
 * 
 
2930
 */
 
2931
#ifdef DISABLE_MIB_LOADING
 
2932
void
 
2933
netsnmp_sprint_realloc_objid_tree(u_char ** buf, size_t * buf_len,
 
2934
                                  size_t * out_len, int allow_realloc,
 
2935
                                  int *buf_overflow,
 
2936
                                  const oid * objid, size_t objidlen)
 
2937
{
 
2938
    netsnmp_sprint_realloc_objid(buf, buf_len, out_len, allow_realloc,
 
2939
                                 buf_overflow, objid, objidlen);
 
2940
}
 
2941
#else
 
2942
struct tree    *
 
2943
netsnmp_sprint_realloc_objid_tree(u_char ** buf, size_t * buf_len,
 
2944
                                  size_t * out_len, int allow_realloc,
 
2945
                                  int *buf_overflow,
 
2946
                                  const oid * objid, size_t objidlen)
 
2947
{
 
2948
    u_char         *tbuf = NULL, *cp = NULL;
 
2949
    size_t          tbuf_len = 256, tout_len = 0;
 
2950
    struct tree    *subtree = tree_head;
 
2951
    size_t          midpoint_offset = 0;
 
2952
    int             tbuf_overflow = 0;
 
2953
    int             output_format;
 
2954
 
 
2955
    if ((tbuf = (u_char *) calloc(tbuf_len, 1)) == NULL) {
 
2956
        tbuf_overflow = 1;
 
2957
    } else {
 
2958
        *tbuf = '.';
 
2959
        tout_len = 1;
 
2960
    }
 
2961
 
 
2962
    subtree = _get_realloc_symbol(objid, objidlen, subtree,
 
2963
                                  &tbuf, &tbuf_len, &tout_len,
 
2964
                                  allow_realloc, &tbuf_overflow, NULL,
 
2965
                                  &midpoint_offset);
 
2966
 
 
2967
    if (tbuf_overflow) {
 
2968
        if (!*buf_overflow) {
 
2969
            snmp_strcat(buf, buf_len, out_len, allow_realloc, tbuf);
 
2970
            *buf_overflow = 1;
 
2971
        }
 
2972
        SNMP_FREE(tbuf);
 
2973
        return subtree;
 
2974
    }
 
2975
 
 
2976
    output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 
2977
    if (0 == output_format) {
 
2978
        output_format = NETSNMP_OID_OUTPUT_MODULE;
 
2979
    }
 
2980
    switch (output_format) {
 
2981
    case NETSNMP_OID_OUTPUT_FULL:
 
2982
    case NETSNMP_OID_OUTPUT_NUMERIC:
 
2983
        cp = tbuf;
 
2984
        break;
 
2985
 
 
2986
    case NETSNMP_OID_OUTPUT_SUFFIX:
 
2987
    case NETSNMP_OID_OUTPUT_MODULE:
 
2988
        for (cp = tbuf; *cp; cp++);
 
2989
 
 
2990
        if (midpoint_offset != 0) {
 
2991
            cp = tbuf + midpoint_offset - 2;    /*  beyond the '.'  */
 
2992
        } else {
 
2993
            while (cp >= tbuf) {
 
2994
                if (isalpha(*cp)) {
 
2995
                    break;
 
2996
                }
 
2997
                cp--;
 
2998
            }
 
2999
        }
 
3000
 
 
3001
        while (cp >= tbuf) {
 
3002
            if (*cp == '.') {
 
3003
                break;
 
3004
            }
 
3005
            cp--;
 
3006
        }
 
3007
 
 
3008
        cp++;
 
3009
 
 
3010
        if ((NETSNMP_OID_OUTPUT_MODULE == output_format)
 
3011
            && cp > tbuf) {
 
3012
            char            modbuf[256] = { 0 }, *mod =
 
3013
                module_name(subtree->modid, modbuf);
 
3014
 
 
3015
            /*
 
3016
             * Don't add the module ID if it's just numeric (i.e. we couldn't look
 
3017
             * it up properly.  
 
3018
             */
 
3019
 
 
3020
            if (!*buf_overflow && modbuf[0] != '#') {
 
3021
                if (!snmp_strcat
 
3022
                    (buf, buf_len, out_len, allow_realloc,
 
3023
                     (const u_char *) mod)
 
3024
                    || !snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
3025
                                    (const u_char *) "::")) {
 
3026
                    *buf_overflow = 1;
 
3027
                }
 
3028
            }
 
3029
        }
 
3030
        break;
 
3031
 
 
3032
    case NETSNMP_OID_OUTPUT_UCD:
 
3033
    {
 
3034
        PrefixListPtr   pp = &mib_prefixes[0];
 
3035
        size_t          ilen, tlen;
 
3036
        const char     *testcp;
 
3037
 
 
3038
        cp = tbuf;
 
3039
        tlen = strlen((char *) tbuf);
 
3040
 
 
3041
        while (pp->str) {
 
3042
            ilen = pp->len;
 
3043
            testcp = pp->str;
 
3044
 
 
3045
            if ((tlen > ilen) && memcmp(tbuf, testcp, ilen) == 0) {
 
3046
                cp += (ilen + 1);
 
3047
                break;
 
3048
            }
 
3049
            pp++;
 
3050
        }
 
3051
        break;
 
3052
    }
 
3053
 
 
3054
    case NETSNMP_OID_OUTPUT_NONE:
 
3055
    default:
 
3056
        cp = NULL;
 
3057
    }
 
3058
 
 
3059
    if (!*buf_overflow &&
 
3060
        !snmp_strcat(buf, buf_len, out_len, allow_realloc, cp)) {
 
3061
        *buf_overflow = 1;
 
3062
    }
 
3063
    SNMP_FREE(tbuf);
 
3064
    return subtree;
 
3065
}
 
3066
#endif /* DISABLE_MIB_LOADING */
 
3067
 
 
3068
int
 
3069
sprint_realloc_objid(u_char ** buf, size_t * buf_len,
 
3070
                     size_t * out_len, int allow_realloc,
 
3071
                     const oid * objid, size_t objidlen)
 
3072
{
 
3073
    int             buf_overflow = 0;
 
3074
 
 
3075
    netsnmp_sprint_realloc_objid_tree(buf, buf_len, out_len, allow_realloc,
 
3076
                                      &buf_overflow, objid, objidlen);
 
3077
    return !buf_overflow;
 
3078
}
 
3079
 
 
3080
int
 
3081
snprint_objid(char *buf, size_t buf_len,
 
3082
              const oid * objid, size_t objidlen)
 
3083
{
 
3084
    size_t          out_len = 0;
 
3085
 
 
3086
    if (sprint_realloc_objid((u_char **) & buf, &buf_len, &out_len, 0,
 
3087
                             objid, objidlen)) {
 
3088
        return (int) out_len;
 
3089
    } else {
 
3090
        return -1;
 
3091
    }
 
3092
}
 
3093
 
 
3094
/**
 
3095
 * Prints an oid to stdout.
 
3096
 *
 
3097
 * @param objid      The oid to print
 
3098
 * @param objidlen   The length of oidid.
 
3099
 */
 
3100
void
 
3101
print_objid(const oid * objid, size_t objidlen)
 
3102
{                               /* number of subidentifiers */
 
3103
    fprint_objid(stdout, objid, objidlen);
 
3104
}
 
3105
 
 
3106
 
 
3107
/**
 
3108
 * Prints an oid to a file descriptor.
 
3109
 *
 
3110
 * @param f          The file descriptor to print to.
 
3111
 * @param objid      The oid to print
 
3112
 * @param objidlen   The length of oidid.
 
3113
 */
 
3114
void
 
3115
fprint_objid(FILE * f, const oid * objid, size_t objidlen)
 
3116
{                               /* number of subidentifiers */
 
3117
    u_char         *buf = NULL;
 
3118
    size_t          buf_len = 256, out_len = 0;
 
3119
    int             buf_overflow = 0;
 
3120
 
 
3121
    if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
 
3122
        fprintf(f, "[TRUNCATED]\n");
 
3123
        return;
 
3124
    } else {
 
3125
        netsnmp_sprint_realloc_objid_tree(&buf, &buf_len, &out_len, 1,
 
3126
                                          &buf_overflow, objid, objidlen);
 
3127
        if (buf_overflow) {
 
3128
            fprintf(f, "%s [TRUNCATED]\n", buf);
 
3129
        } else {
 
3130
            fprintf(f, "%s\n", buf);
 
3131
        }
 
3132
    }
 
3133
 
 
3134
    SNMP_FREE(buf);
 
3135
}
 
3136
 
 
3137
int
 
3138
sprint_realloc_variable(u_char ** buf, size_t * buf_len,
 
3139
                        size_t * out_len, int allow_realloc,
 
3140
                        const oid * objid, size_t objidlen,
 
3141
                        const netsnmp_variable_list * variable)
 
3142
{
 
3143
    int             buf_overflow = 0;
 
3144
 
 
3145
#ifndef DISABLE_MIB_LOADING
 
3146
    struct tree    *subtree = tree_head;
 
3147
 
 
3148
    subtree =
 
3149
#endif /* DISABLE_MIB_LOADING */
 
3150
        netsnmp_sprint_realloc_objid_tree(buf, buf_len, out_len,
 
3151
                                          allow_realloc, &buf_overflow,
 
3152
                                          objid, objidlen);
 
3153
 
 
3154
    if (buf_overflow) {
 
3155
        return 0;
 
3156
    }
 
3157
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE)) {
 
3158
        if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
 
3159
            if (!snmp_strcat
 
3160
                (buf, buf_len, out_len, allow_realloc,
 
3161
                 (const u_char *) " = ")) {
 
3162
                return 0;
 
3163
            }
 
3164
        } else {
 
3165
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
 
3166
                if (!snmp_strcat
 
3167
                    (buf, buf_len, out_len, allow_realloc,
 
3168
                     (const u_char *) " ")) {
 
3169
                    return 0;
 
3170
                }
 
3171
            } else {
 
3172
                if (!snmp_strcat
 
3173
                    (buf, buf_len, out_len, allow_realloc,
 
3174
                     (const u_char *) " = ")) {
 
3175
                    return 0;
 
3176
                }
 
3177
            }                   /* end if-else NETSNMP_DS_LIB_QUICK_PRINT */
 
3178
        }                       /* end if-else NETSNMP_DS_LIB_QUICKE_PRINT */
 
3179
    } else {
 
3180
        *out_len = 0;
 
3181
    }
 
3182
 
 
3183
    if (variable->type == SNMP_NOSUCHOBJECT) {
 
3184
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
3185
                           (const u_char *)
 
3186
                           "No Such Object available on this agent at this OID");
 
3187
    } else if (variable->type == SNMP_NOSUCHINSTANCE) {
 
3188
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
3189
                           (const u_char *)
 
3190
                           "No Such Instance currently exists at this OID");
 
3191
    } else if (variable->type == SNMP_ENDOFMIBVIEW) {
 
3192
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
3193
                           (const u_char *)
 
3194
                           "No more variables left in this MIB View (It is past the end of the MIB tree)");
 
3195
#ifndef DISABLE_MIB_LOADING
 
3196
    } else if (subtree) {
 
3197
        const char *units = NULL;
 
3198
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
 
3199
                                    NETSNMP_DS_LIB_DONT_PRINT_UNITS)) {
 
3200
            units = subtree->units;
 
3201
        }
 
3202
        if (subtree->printomat) {
 
3203
            return (*subtree->printomat) (buf, buf_len, out_len,
 
3204
                                          allow_realloc, variable,
 
3205
                                          subtree->enums, subtree->hint,
 
3206
                                          units);
 
3207
        } else {
 
3208
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
3209
                                          allow_realloc, variable,
 
3210
                                          subtree->enums, subtree->hint,
 
3211
                                          units);
 
3212
        }
 
3213
#endif /* DISABLE_MIB_LOADING */
 
3214
    } else {
 
3215
        /*
 
3216
         * Handle rare case where tree is empty.  
 
3217
         */
 
3218
        return sprint_realloc_by_type(buf, buf_len, out_len, allow_realloc,
 
3219
                                      variable, 0, 0, 0);
 
3220
    }
 
3221
}
 
3222
 
 
3223
int
 
3224
snprint_variable(char *buf, size_t buf_len,
 
3225
                 const oid * objid, size_t objidlen,
 
3226
                 const netsnmp_variable_list * variable)
 
3227
{
 
3228
    size_t          out_len = 0;
 
3229
 
 
3230
    if (sprint_realloc_variable((u_char **) & buf, &buf_len, &out_len, 0,
 
3231
                                objid, objidlen, variable)) {
 
3232
        return (int) out_len;
 
3233
    } else {
 
3234
        return -1;
 
3235
    }
 
3236
}
 
3237
 
 
3238
/**
 
3239
 * Prints a variable to stdout.
 
3240
 *
 
3241
 * @param objid     The object id.
 
3242
 * @param objidlen  The length of teh object id.
 
3243
 * @param variable  The variable to print.
 
3244
 */
 
3245
void
 
3246
print_variable(const oid * objid,
 
3247
               size_t objidlen, const netsnmp_variable_list * variable)
 
3248
{
 
3249
    fprint_variable(stdout, objid, objidlen, variable);
 
3250
}
 
3251
 
 
3252
 
 
3253
/**
 
3254
 * Prints a variable to a file descriptor.
 
3255
 *
 
3256
 * @param f         The file descriptor to print to.
 
3257
 * @param objid     The object id.
 
3258
 * @param objidlen  The length of teh object id.
 
3259
 * @param variable  The variable to print.
 
3260
 */
 
3261
void
 
3262
fprint_variable(FILE * f,
 
3263
                const oid * objid,
 
3264
                size_t objidlen, const netsnmp_variable_list * variable)
 
3265
{
 
3266
    u_char         *buf = NULL;
 
3267
    size_t          buf_len = 256, out_len = 0;
 
3268
 
 
3269
    if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
 
3270
        fprintf(f, "[TRUNCATED]\n");
 
3271
        return;
 
3272
    } else {
 
3273
        if (sprint_realloc_variable(&buf, &buf_len, &out_len, 1,
 
3274
                                    objid, objidlen, variable)) {
 
3275
            fprintf(f, "%s\n", buf);
 
3276
        } else {
 
3277
            fprintf(f, "%s [TRUNCATED]\n", buf);
 
3278
        }
 
3279
    }
 
3280
 
 
3281
    SNMP_FREE(buf);
 
3282
}
 
3283
 
 
3284
int
 
3285
sprint_realloc_value(u_char ** buf, size_t * buf_len,
 
3286
                     size_t * out_len, int allow_realloc,
 
3287
                     const oid * objid, size_t objidlen,
 
3288
                     const netsnmp_variable_list * variable)
 
3289
{
 
3290
#ifndef DISABLE_MIB_LOADING
 
3291
    struct tree    *subtree = tree_head;
 
3292
#endif /* DISABLE_MIB_LOADING */
 
3293
 
 
3294
    if (variable->type == SNMP_NOSUCHOBJECT) {
 
3295
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
3296
                           (const u_char *)
 
3297
                           "No Such Object available on this agent at this OID");
 
3298
    } else if (variable->type == SNMP_NOSUCHINSTANCE) {
 
3299
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
3300
                           (const u_char *)
 
3301
                           "No Such Instance currently exists at this OID");
 
3302
    } else if (variable->type == SNMP_ENDOFMIBVIEW) {
 
3303
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
3304
                           (const u_char *)
 
3305
                           "No more variables left in this MIB View (It is past the end of the MIB tree)");
 
3306
    } else {
 
3307
#ifndef DISABLE_MIB_LOADING
 
3308
        const char *units = NULL;
 
3309
        subtree = get_tree(objid, objidlen, subtree);
 
3310
        if (subtree && !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
 
3311
                                            NETSNMP_DS_LIB_DONT_PRINT_UNITS)) {
 
3312
            units = subtree->units;
 
3313
        }
 
3314
        if (subtree && subtree->printomat) {
 
3315
            return (*subtree->printomat) (buf, buf_len, out_len,
 
3316
                                          allow_realloc, variable,
 
3317
                                          subtree->enums, subtree->hint,
 
3318
                                          units);
 
3319
        } else {
 
3320
            return sprint_realloc_by_type(buf, buf_len, out_len,
 
3321
                                          allow_realloc, variable,
 
3322
                                          subtree->enums, subtree->hint,
 
3323
                                          units);
 
3324
        }
 
3325
#else
 
3326
        return sprint_realloc_by_type(buf, buf_len, out_len,
 
3327
                                      allow_realloc, variable,
 
3328
                                      NULL, NULL, NULL);
 
3329
#endif /* DISABLE_MIB_LOADING */
 
3330
    }
 
3331
}
 
3332
 
 
3333
int
 
3334
snprint_value(char *buf, size_t buf_len,
 
3335
              const oid * objid, size_t objidlen,
 
3336
              const netsnmp_variable_list * variable)
 
3337
{
 
3338
    size_t          out_len = 0;
 
3339
 
 
3340
    if (sprint_realloc_value((u_char **) & buf, &buf_len, &out_len, 0,
 
3341
                             objid, objidlen, variable)) {
 
3342
        return (int) out_len;
 
3343
    } else {
 
3344
        return -1;
 
3345
    }
 
3346
}
 
3347
 
 
3348
void
 
3349
print_value(const oid * objid,
 
3350
            size_t objidlen, const netsnmp_variable_list * variable)
 
3351
{
 
3352
    fprint_value(stdout, objid, objidlen, variable);
 
3353
}
 
3354
 
 
3355
void
 
3356
fprint_value(FILE * f,
 
3357
             const oid * objid,
 
3358
             size_t objidlen, const netsnmp_variable_list * variable)
 
3359
{
 
3360
    u_char         *buf = NULL;
 
3361
    size_t          buf_len = 256, out_len = 0;
 
3362
 
 
3363
    if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
 
3364
        fprintf(f, "[TRUNCATED]\n");
 
3365
        return;
 
3366
    } else {
 
3367
        if (sprint_realloc_value(&buf, &buf_len, &out_len, 1,
 
3368
                                 objid, objidlen, variable)) {
 
3369
            fprintf(f, "%s\n", buf);
 
3370
        } else {
 
3371
            fprintf(f, "%s [TRUNCATED]\n", buf);
 
3372
        }
 
3373
    }
 
3374
 
 
3375
    SNMP_FREE(buf);
 
3376
}
 
3377
 
 
3378
 
 
3379
/**
 
3380
 * Takes the value in VAR and turns it into an OID segment in var->name.
 
3381
 *  
 
3382
 * @param var    The variable.
 
3383
 *
 
3384
 * @return SNMPERR_SUCCESS or SNMPERR_GENERR 
 
3385
 */
 
3386
int
 
3387
build_oid_segment(netsnmp_variable_list * var)
 
3388
{
 
3389
    int             i;
 
3390
 
 
3391
    if (var->name && var->name != var->name_loc)
 
3392
        SNMP_FREE(var->name);
 
3393
    switch (var->type) {
 
3394
    case ASN_INTEGER:
 
3395
    case ASN_COUNTER:
 
3396
    case ASN_GAUGE:
 
3397
    case ASN_TIMETICKS:
 
3398
        var->name_length = 1;
 
3399
        var->name = var->name_loc;
 
3400
        var->name[0] = *(var->val.integer);
 
3401
        break;
 
3402
 
 
3403
    case ASN_IPADDRESS:
 
3404
        var->name_length = 4;
 
3405
        var->name = var->name_loc;
 
3406
        var->name[0] =
 
3407
            (((unsigned int) *(var->val.integer)) & 0xff000000) >> 24;
 
3408
        var->name[1] =
 
3409
            (((unsigned int) *(var->val.integer)) & 0x00ff0000) >> 16;
 
3410
        var->name[2] =
 
3411
            (((unsigned int) *(var->val.integer)) & 0x0000ff00) >> 8;
 
3412
        var->name[3] =
 
3413
            (((unsigned int) *(var->val.integer)) & 0x000000ff);
 
3414
        break;
 
3415
        
 
3416
    case ASN_PRIV_IMPLIED_OBJECT_ID:
 
3417
        var->name_length = var->val_len / sizeof(oid);
 
3418
        if (var->name_length > (sizeof(var->name_loc) / sizeof(oid)))
 
3419
            var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
 
3420
        else
 
3421
            var->name = var->name_loc;
 
3422
        if (var->name == NULL)
 
3423
            return SNMPERR_GENERR;
 
3424
 
 
3425
        for (i = 0; i < (int) var->name_length; i++)
 
3426
            var->name[i] = var->val.objid[i];
 
3427
        break;
 
3428
 
 
3429
    case ASN_OBJECT_ID:
 
3430
        var->name_length = var->val_len / sizeof(oid) + 1;
 
3431
        if (var->name_length > (sizeof(var->name_loc) / sizeof(oid)))
 
3432
            var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
 
3433
        else
 
3434
            var->name = var->name_loc;
 
3435
        if (var->name == NULL)
 
3436
            return SNMPERR_GENERR;
 
3437
 
 
3438
        var->name[0] = var->name_length - 1;
 
3439
        for (i = 0; i < (int) var->name_length - 1; i++)
 
3440
            var->name[i + 1] = var->val.objid[i];
 
3441
        break;
 
3442
 
 
3443
    case ASN_PRIV_IMPLIED_OCTET_STR:
 
3444
        var->name_length = var->val_len;
 
3445
        if (var->name_length > (sizeof(var->name_loc) / sizeof(oid)))
 
3446
            var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
 
3447
        else
 
3448
            var->name = var->name_loc;
 
3449
        if (var->name == NULL)
 
3450
            return SNMPERR_GENERR;
 
3451
 
 
3452
        for (i = 0; i < (int) var->val_len; i++)
 
3453
            var->name[i] = (oid) var->val.string[i];
 
3454
        break;
 
3455
 
 
3456
    case ASN_OPAQUE:
 
3457
    case ASN_OCTET_STR:
 
3458
        var->name_length = var->val_len + 1;
 
3459
        if (var->name_length > (sizeof(var->name_loc) / sizeof(oid)))
 
3460
            var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
 
3461
        else
 
3462
            var->name = var->name_loc;
 
3463
        if (var->name == NULL)
 
3464
            return SNMPERR_GENERR;
 
3465
 
 
3466
        var->name[0] = (oid) var->val_len;
 
3467
        for (i = 0; i < (int) var->val_len; i++)
 
3468
            var->name[i + 1] = (oid) var->val.string[i];
 
3469
        break;
 
3470
 
 
3471
    default:
 
3472
        DEBUGMSGTL(("build_oid_segment",
 
3473
                    "invalid asn type: %d\n", var->type));
 
3474
        return SNMPERR_GENERR;
 
3475
    }
 
3476
 
 
3477
    if (var->name_length > MAX_OID_LEN) {
 
3478
        DEBUGMSGTL(("build_oid_segment",
 
3479
                    "Something terribly wrong, namelen = %d\n",
 
3480
                    var->name_length));
 
3481
        return SNMPERR_GENERR;
 
3482
    }
 
3483
 
 
3484
    return SNMPERR_SUCCESS;
 
3485
}
 
3486
 
 
3487
 
 
3488
int
 
3489
build_oid_noalloc(oid * in, size_t in_len, size_t * out_len,
 
3490
                  oid * prefix, size_t prefix_len,
 
3491
                  netsnmp_variable_list * indexes)
 
3492
{
 
3493
    netsnmp_variable_list *var;
 
3494
 
 
3495
    if (prefix) {
 
3496
        if (in_len < prefix_len)
 
3497
            return SNMPERR_GENERR;
 
3498
        memcpy(in, prefix, prefix_len * sizeof(oid));
 
3499
        *out_len = prefix_len;
 
3500
    } else {
 
3501
        *out_len = 0;
 
3502
    }
 
3503
 
 
3504
    for (var = indexes; var != NULL; var = var->next_variable) {
 
3505
        if (build_oid_segment(var) != SNMPERR_SUCCESS)
 
3506
            return SNMPERR_GENERR;
 
3507
        if (var->name_length + *out_len < in_len) {
 
3508
            memcpy(&(in[*out_len]), var->name,
 
3509
                   sizeof(oid) * var->name_length);
 
3510
            *out_len += var->name_length;
 
3511
        } else {
 
3512
            return SNMPERR_GENERR;
 
3513
        }
 
3514
    }
 
3515
 
 
3516
    DEBUGMSGTL(("build_oid_noalloc", "generated: "));
 
3517
    DEBUGMSGOID(("build_oid_noalloc", in, *out_len));
 
3518
    DEBUGMSG(("build_oid_noalloc", "\n"));
 
3519
    return SNMPERR_SUCCESS;
 
3520
}
 
3521
 
 
3522
int
 
3523
build_oid(oid ** out, size_t * out_len,
 
3524
          oid * prefix, size_t prefix_len, netsnmp_variable_list * indexes)
 
3525
{
 
3526
    oid             tmpout[MAX_OID_LEN];
 
3527
 
 
3528
    /*
 
3529
     * xxx-rks: inefficent. try only building segments to find index len:
 
3530
     *   for (var = indexes; var != NULL; var = var->next_variable) {
 
3531
     *      if (build_oid_segment(var) != SNMPERR_SUCCESS)
 
3532
     *         return SNMPERR_GENERR;
 
3533
     *      *out_len += var->name_length;
 
3534
     *
 
3535
     * then see if it fits in existing buffer, or realloc buffer.
 
3536
     */
 
3537
    if (build_oid_noalloc(tmpout, sizeof(tmpout), out_len,
 
3538
                          prefix, prefix_len, indexes) != SNMPERR_SUCCESS)
 
3539
        return SNMPERR_GENERR;
 
3540
 
 
3541
    /** xxx-rks: should free previous value? */
 
3542
    snmp_clone_mem((void **) out, (void *) tmpout, *out_len * sizeof(oid));
 
3543
 
 
3544
    return SNMPERR_SUCCESS;
 
3545
}
 
3546
 
 
3547
/*
 
3548
 * vblist_out must contain a pre-allocated string of variables into
 
3549
 * which indexes can be extracted based on the previously existing
 
3550
 * types in the variable chain
 
3551
 * returns:
 
3552
 * SNMPERR_GENERR  on error
 
3553
 * SNMPERR_SUCCESS on success
 
3554
 */
 
3555
 
 
3556
int
 
3557
parse_oid_indexes(oid * oidIndex, size_t oidLen,
 
3558
                  netsnmp_variable_list * data)
 
3559
{
 
3560
    netsnmp_variable_list *var = data;
 
3561
 
 
3562
    while (var && oidLen > 0) {
 
3563
 
 
3564
        if (parse_one_oid_index(&oidIndex, &oidLen, var, 0) !=
 
3565
            SNMPERR_SUCCESS)
 
3566
            break;
 
3567
 
 
3568
        var = var->next_variable;
 
3569
    }
 
3570
 
 
3571
    if (var != NULL || oidLen != 0)
 
3572
        return SNMPERR_GENERR;
 
3573
    return SNMPERR_SUCCESS;
 
3574
}
 
3575
 
 
3576
 
 
3577
int
 
3578
parse_one_oid_index(oid ** oidStart, size_t * oidLen,
 
3579
                    netsnmp_variable_list * data, int complete)
 
3580
{
 
3581
    netsnmp_variable_list *var = data;
 
3582
    oid             tmpout[MAX_OID_LEN];
 
3583
    unsigned int    i;
 
3584
    unsigned int    uitmp = 0;
 
3585
 
 
3586
    oid            *oidIndex = *oidStart;
 
3587
 
 
3588
    if (var == NULL || ((*oidLen == 0) && (complete == 0)))
 
3589
        return SNMPERR_GENERR;
 
3590
    else {
 
3591
        switch (var->type) {
 
3592
        case ASN_INTEGER:
 
3593
        case ASN_COUNTER:
 
3594
        case ASN_GAUGE:
 
3595
        case ASN_TIMETICKS:
 
3596
            if (*oidLen) {
 
3597
                snmp_set_var_value(var, (u_char *) oidIndex++,
 
3598
                                   sizeof(long));
 
3599
                --(*oidLen);
 
3600
            } else {
 
3601
                snmp_set_var_value(var, (u_char *) oidLen, sizeof(long));
 
3602
            }
 
3603
            DEBUGMSGTL(("parse_oid_indexes",
 
3604
                        "Parsed int(%d): %d\n", var->type,
 
3605
                        *var->val.integer));
 
3606
            break;
 
3607
 
 
3608
        case ASN_IPADDRESS:
 
3609
            if ((4 > *oidLen) && (complete == 0))
 
3610
                return SNMPERR_GENERR;
 
3611
            
 
3612
            for (i = 0; i < 4 && i < *oidLen; ++i) {
 
3613
                if (oidIndex[i] > 255) {
 
3614
                    DEBUGMSGTL(("parse_oid_indexes",
 
3615
                                "illegal oid in index: %d\n", oidIndex[0]));
 
3616
                        return SNMPERR_GENERR;  /* sub-identifier too large */
 
3617
                    }
 
3618
                    uitmp = uitmp + (oidIndex[i] << (8*(3-i)));
 
3619
                }
 
3620
            if (4 > (int) (*oidLen)) {
 
3621
                oidIndex += *oidLen;
 
3622
                (*oidLen) = 0;
 
3623
            } else {
 
3624
                oidIndex += 4;
 
3625
                (*oidLen) -= 4;
 
3626
            }
 
3627
            uitmp = 
 
3628
                snmp_set_var_value(var, (u_char *) &uitmp, 4);
 
3629
            DEBUGMSGTL(("parse_oid_indexes",
 
3630
                        "Parsed ipaddr(%d): %d.%d.%d.%d\n", var->type,
 
3631
                        var->val.string[0], var->val.string[1],
 
3632
                        var->val.string[2], var->val.string[3]));
 
3633
            break;
 
3634
 
 
3635
        case ASN_OBJECT_ID:
 
3636
        case ASN_PRIV_IMPLIED_OBJECT_ID:
 
3637
            if (var->type == ASN_PRIV_IMPLIED_OBJECT_ID) {
 
3638
                uitmp = *oidLen;
 
3639
            } else {
 
3640
                if (*oidLen) {
 
3641
                    uitmp = *oidIndex++;
 
3642
                    --(*oidLen);
 
3643
                } else {
 
3644
                    uitmp = 0;
 
3645
                }
 
3646
                if ((uitmp > *oidLen) && (complete == 0))
 
3647
                    return SNMPERR_GENERR;
 
3648
            }
 
3649
 
 
3650
            if (uitmp > MAX_OID_LEN)
 
3651
                return SNMPERR_GENERR;  /* too big and illegal */
 
3652
 
 
3653
            if (uitmp > *oidLen) {
 
3654
                memcpy(tmpout, oidIndex, sizeof(oid) * (*oidLen));
 
3655
                memset(&tmpout[*oidLen], 0x00,
 
3656
                       sizeof(oid) * (uitmp - *oidLen));
 
3657
                snmp_set_var_value(var, (u_char *) tmpout,
 
3658
                                   sizeof(oid) * uitmp);
 
3659
                oidIndex += *oidLen;
 
3660
                (*oidLen) = 0;
 
3661
            } else {
 
3662
                snmp_set_var_value(var, (u_char *) oidIndex,
 
3663
                                   sizeof(oid) * uitmp);
 
3664
                oidIndex += uitmp;
 
3665
                (*oidLen) -= uitmp;
 
3666
            }
 
3667
 
 
3668
            DEBUGMSGTL(("parse_oid_indexes", "Parsed oid: "));
 
3669
            DEBUGMSGOID(("parse_oid_indexes",
 
3670
                         var->val.objid, var->val_len / sizeof(oid)));
 
3671
            DEBUGMSG(("parse_oid_indexes", "\n"));
 
3672
            break;
 
3673
 
 
3674
        case ASN_OPAQUE:
 
3675
        case ASN_OCTET_STR:
 
3676
        case ASN_PRIV_IMPLIED_OCTET_STR:
 
3677
            if (var->type == ASN_PRIV_IMPLIED_OCTET_STR) {
 
3678
                uitmp = *oidLen;
 
3679
            } else {
 
3680
                if (*oidLen) {
 
3681
                    uitmp = *oidIndex++;
 
3682
                    --(*oidLen);
 
3683
                } else {
 
3684
                    uitmp = 0;
 
3685
                }
 
3686
                if ((uitmp > *oidLen) && (complete == 0))
 
3687
                    return SNMPERR_GENERR;
 
3688
            }
 
3689
 
 
3690
            /*
 
3691
             * we handle this one ourselves since we don't have
 
3692
             * pre-allocated memory to copy from using
 
3693
             * snmp_set_var_value() 
 
3694
             */
 
3695
 
 
3696
            if (uitmp == 0)
 
3697
                break;          /* zero length strings shouldn't malloc */
 
3698
 
 
3699
            if (uitmp > MAX_OID_LEN)
 
3700
                return SNMPERR_GENERR;  /* too big and illegal */
 
3701
 
 
3702
            /*
 
3703
             * malloc by size+1 to allow a null to be appended. 
 
3704
             */
 
3705
            var->val_len = uitmp;
 
3706
            var->val.string = (u_char *) calloc(1, uitmp + 1);
 
3707
            if (var->val.string == NULL)
 
3708
                return SNMPERR_GENERR;
 
3709
 
 
3710
            if (uitmp > (int) (*oidLen)) {
 
3711
                for (i = 0; i < *oidLen; ++i)
 
3712
                    var->val.string[i] = (u_char) * oidIndex++;
 
3713
                for (i = 0; i < uitmp; ++i)
 
3714
                    var->val.string[i] = '\0';
 
3715
                (*oidLen) = 0;
 
3716
            } else {
 
3717
                for (i = 0; i < uitmp; ++i)
 
3718
                    var->val.string[i] = (u_char) * oidIndex++;
 
3719
                (*oidLen) -= uitmp;
 
3720
            }
 
3721
            var->val.string[uitmp] = '\0';
 
3722
 
 
3723
            DEBUGMSGTL(("parse_oid_indexes",
 
3724
                        "Parsed str(%d): %s\n", var->type,
 
3725
                        var->val.string));
 
3726
            break;
 
3727
 
 
3728
        default:
 
3729
            DEBUGMSGTL(("parse_oid_indexes",
 
3730
                        "invalid asn type: %d\n", var->type));
 
3731
            return SNMPERR_GENERR;
 
3732
        }
 
3733
    }
 
3734
    (*oidStart) = oidIndex;
 
3735
    return SNMPERR_SUCCESS;
 
3736
}
 
3737
 
 
3738
int
 
3739
dump_realloc_oid_to_string(const oid * objid, size_t objidlen,
 
3740
                           u_char ** buf, size_t * buf_len,
 
3741
                           size_t * out_len, int allow_realloc,
 
3742
                           char quotechar)
 
3743
{
 
3744
    if (buf) {
 
3745
        int             i, alen;
 
3746
 
 
3747
        for (i = 0, alen = 0; i < (int) objidlen; i++) {
 
3748
            oid             tst = objid[i];
 
3749
            if ((tst > 254) || (!isprint(tst))) {
 
3750
                tst = (oid) '.';
 
3751
            }
 
3752
 
 
3753
            if (alen == 0) {
 
3754
                if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) {
 
3755
                    while ((*out_len + 2) >= *buf_len) {
 
3756
                        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
3757
                            return 0;
 
3758
                        }
 
3759
                    }
 
3760
                    *(*buf + *out_len) = '\\';
 
3761
                    (*out_len)++;
 
3762
                }
 
3763
                while ((*out_len + 2) >= *buf_len) {
 
3764
                    if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
3765
                        return 0;
 
3766
                    }
 
3767
                }
 
3768
                *(*buf + *out_len) = quotechar;
 
3769
                (*out_len)++;
 
3770
            }
 
3771
 
 
3772
            while ((*out_len + 2) >= *buf_len) {
 
3773
                if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
3774
                    return 0;
 
3775
                }
 
3776
            }
 
3777
            *(*buf + *out_len) = (char) tst;
 
3778
            (*out_len)++;
 
3779
            alen++;
 
3780
        }
 
3781
 
 
3782
        if (alen) {
 
3783
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) {
 
3784
                while ((*out_len + 2) >= *buf_len) {
 
3785
                    if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
3786
                        return 0;
 
3787
                    }
 
3788
                }
 
3789
                *(*buf + *out_len) = '\\';
 
3790
                (*out_len)++;
 
3791
            }
 
3792
            while ((*out_len + 2) >= *buf_len) {
 
3793
                if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
3794
                    return 0;
 
3795
                }
 
3796
            }
 
3797
            *(*buf + *out_len) = quotechar;
 
3798
            (*out_len)++;
 
3799
        }
 
3800
 
 
3801
        *(*buf + *out_len) = '\0';
 
3802
    }
 
3803
 
 
3804
    return 1;
 
3805
}
 
3806
 
 
3807
void
 
3808
_oid_finish_printing(const oid * objid, size_t objidlen,
 
3809
                     u_char ** buf, size_t * buf_len, size_t * out_len,
 
3810
                     int allow_realloc, int *buf_overflow) {
 
3811
    char            intbuf[64];
 
3812
    if (*buf != NULL && *(*buf + *out_len - 1) != '.') {
 
3813
        if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
3814
                                           allow_realloc,
 
3815
                                           (const u_char *) ".")) {
 
3816
            *buf_overflow = 1;
 
3817
        }
 
3818
    }
 
3819
 
 
3820
    while (objidlen-- > 0) {    /* output rest of name, uninterpreted */
 
3821
        sprintf(intbuf, "%lu.", *objid++);
 
3822
        if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
3823
                                           allow_realloc,
 
3824
                                           (const u_char *) intbuf)) {
 
3825
            *buf_overflow = 1;
 
3826
        }
 
3827
    }
 
3828
 
 
3829
    if (*buf != NULL) {
 
3830
        *(*buf + *out_len - 1) = '\0';  /* remove trailing dot */
 
3831
    }
 
3832
}
 
3833
 
 
3834
#ifndef DISABLE_MIB_LOADING
 
3835
static struct tree *
 
3836
_get_realloc_symbol(const oid * objid, size_t objidlen,
 
3837
                    struct tree *subtree,
 
3838
                    u_char ** buf, size_t * buf_len, size_t * out_len,
 
3839
                    int allow_realloc, int *buf_overflow,
 
3840
                    struct index_list *in_dices, size_t * end_of_known)
 
3841
{
 
3842
    struct tree    *return_tree = NULL;
 
3843
    int             extended_index =
 
3844
        netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX);
 
3845
    int             output_format =
 
3846
        netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
 
3847
    char            intbuf[64];
 
3848
 
 
3849
    if (!objid || !buf) {
 
3850
        return NULL;
 
3851
    }
 
3852
 
 
3853
    for (; subtree; subtree = subtree->next_peer) {
 
3854
        if (*objid == subtree->subid) {
 
3855
            while (subtree->next_peer && subtree->next_peer->subid == *objid)
 
3856
                subtree = subtree->next_peer;
 
3857
            if (subtree->indexes) {
 
3858
                in_dices = subtree->indexes;
 
3859
            } else if (subtree->augments) {
 
3860
                struct tree    *tp2 =
 
3861
                    find_tree_node(subtree->augments, -1);
 
3862
                if (tp2) {
 
3863
                    in_dices = tp2->indexes;
 
3864
                }
 
3865
            }
 
3866
 
 
3867
            if (!strncmp(subtree->label, ANON, ANON_LEN) ||
 
3868
                (NETSNMP_OID_OUTPUT_NUMERIC == output_format)) {
 
3869
                sprintf(intbuf, "%lu", subtree->subid);
 
3870
                if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
3871
                                                   allow_realloc,
 
3872
                                                   (const u_char *)
 
3873
                                                   intbuf)) {
 
3874
                    *buf_overflow = 1;
 
3875
                }
 
3876
            } else {
 
3877
                if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
3878
                                                   allow_realloc,
 
3879
                                                   (const u_char *)
 
3880
                                                   subtree->label)) {
 
3881
                    *buf_overflow = 1;
 
3882
                }
 
3883
            }
 
3884
 
 
3885
            if (objidlen > 1) {
 
3886
                if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
3887
                                                   allow_realloc,
 
3888
                                                   (const u_char *) ".")) {
 
3889
                    *buf_overflow = 1;
 
3890
                }
 
3891
 
 
3892
                return_tree = _get_realloc_symbol(objid + 1, objidlen - 1,
 
3893
                                                  subtree->child_list,
 
3894
                                                  buf, buf_len, out_len,
 
3895
                                                  allow_realloc,
 
3896
                                                  buf_overflow, in_dices,
 
3897
                                                  end_of_known);
 
3898
            }
 
3899
 
 
3900
            if (return_tree != NULL) {
 
3901
                return return_tree;
 
3902
            } else {
 
3903
                return subtree;
 
3904
            }
 
3905
        }
 
3906
    }
 
3907
 
 
3908
 
 
3909
    if (end_of_known) {
 
3910
        *end_of_known = *out_len;
 
3911
    }
 
3912
 
 
3913
    /*
 
3914
     * Subtree not found.  
 
3915
     */
 
3916
 
 
3917
    while (in_dices && (objidlen > 0) &&
 
3918
           (NETSNMP_OID_OUTPUT_NUMERIC != output_format) &&
 
3919
           !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS)) {
 
3920
        size_t          numids;
 
3921
        struct tree    *tp;
 
3922
 
 
3923
        tp = find_tree_node(in_dices->ilabel, -1);
 
3924
 
 
3925
        if (!tp) {
 
3926
            /*
 
3927
             * Can't find an index in the mib tree.  Bail.  
 
3928
             */
 
3929
            goto finish_it;
 
3930
        }
 
3931
 
 
3932
        if (extended_index) {
 
3933
            if (*buf != NULL && *(*buf + *out_len - 1) == '.') {
 
3934
                (*out_len)--;
 
3935
            }
 
3936
            if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
3937
                                               allow_realloc,
 
3938
                                               (const u_char *) "[")) {
 
3939
                *buf_overflow = 1;
 
3940
            }
 
3941
        }
 
3942
 
 
3943
        switch (tp->type) {
 
3944
        case TYPE_OCTETSTR:
 
3945
            if (extended_index && tp->hint) {
 
3946
                netsnmp_variable_list var;
 
3947
                u_char          buffer[1024];
 
3948
                int             i;
 
3949
 
 
3950
                memset(&var, 0, sizeof var);
 
3951
                if (in_dices->isimplied) {
 
3952
                    numids = objidlen;
 
3953
                    if (numids > objidlen)
 
3954
                        goto finish_it;
 
3955
                } else if (tp->ranges && !tp->ranges->next
 
3956
                           && tp->ranges->low == tp->ranges->high) {
 
3957
                    numids = tp->ranges->low;
 
3958
                    if (numids > objidlen)
 
3959
                        goto finish_it;
 
3960
                } else {
 
3961
                    numids = *objid;
 
3962
                    if (numids >= objidlen)
 
3963
                        goto finish_it;
 
3964
                    objid++;
 
3965
                    objidlen--;
 
3966
                }
 
3967
                if (numids > objidlen)
 
3968
                    goto finish_it;
 
3969
                for (i = 0; i < (int) numids; i++)
 
3970
                    buffer[i] = (u_char) objid[i];
 
3971
                var.type = ASN_OCTET_STR;
 
3972
                var.val.string = buffer;
 
3973
                var.val_len = numids;
 
3974
                if (!*buf_overflow) {
 
3975
                    if (!sprint_realloc_octet_string(buf, buf_len, out_len,
 
3976
                                                     allow_realloc, &var,
 
3977
                                                     NULL, tp->hint,
 
3978
                                                     NULL)) {
 
3979
                        *buf_overflow = 1;
 
3980
                    }
 
3981
                }
 
3982
            } else if (in_dices->isimplied) {
 
3983
                numids = objidlen;
 
3984
                if (numids > objidlen)
 
3985
                    goto finish_it;
 
3986
 
 
3987
                if (!*buf_overflow) {
 
3988
                    if (!dump_realloc_oid_to_string
 
3989
                        (objid, numids, buf, buf_len, out_len,
 
3990
                         allow_realloc, '\'')) {
 
3991
                        *buf_overflow = 1;
 
3992
                    }
 
3993
                }
 
3994
            } else if (tp->ranges && !tp->ranges->next
 
3995
                       && tp->ranges->low == tp->ranges->high) {
 
3996
                /*
 
3997
                 * a fixed-length object string 
 
3998
                 */
 
3999
                numids = tp->ranges->low;
 
4000
                if (numids > objidlen)
 
4001
                    goto finish_it;
 
4002
 
 
4003
                if (!*buf_overflow) {
 
4004
                    if (!dump_realloc_oid_to_string
 
4005
                        (objid, numids, buf, buf_len, out_len,
 
4006
                         allow_realloc, '\'')) {
 
4007
                        *buf_overflow = 1;
 
4008
                    }
 
4009
                }
 
4010
            } else {
 
4011
                numids = (size_t) * objid + 1;
 
4012
                if (numids > objidlen)
 
4013
                    goto finish_it;
 
4014
                if (numids == 1) {
 
4015
                    if (netsnmp_ds_get_boolean
 
4016
                        (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) {
 
4017
                        if (!*buf_overflow
 
4018
                            && !snmp_strcat(buf, buf_len, out_len,
 
4019
                                            allow_realloc,
 
4020
                                            (const u_char *) "\\")) {
 
4021
                            *buf_overflow = 1;
 
4022
                        }
 
4023
                    }
 
4024
                    if (!*buf_overflow
 
4025
                        && !snmp_strcat(buf, buf_len, out_len,
 
4026
                                        allow_realloc,
 
4027
                                        (const u_char *) "\"")) {
 
4028
                        *buf_overflow = 1;
 
4029
                    }
 
4030
                    if (netsnmp_ds_get_boolean
 
4031
                        (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) {
 
4032
                        if (!*buf_overflow
 
4033
                            && !snmp_strcat(buf, buf_len, out_len,
 
4034
                                            allow_realloc,
 
4035
                                            (const u_char *) "\\")) {
 
4036
                            *buf_overflow = 1;
 
4037
                        }
 
4038
                    }
 
4039
                    if (!*buf_overflow
 
4040
                        && !snmp_strcat(buf, buf_len, out_len,
 
4041
                                        allow_realloc,
 
4042
                                        (const u_char *) "\"")) {
 
4043
                        *buf_overflow = 1;
 
4044
                    }
 
4045
                } else {
 
4046
                    if (!*buf_overflow) {
 
4047
                        if (!dump_realloc_oid_to_string
 
4048
                            (objid + 1, numids - 1, buf, buf_len, out_len,
 
4049
                             allow_realloc, '"')) {
 
4050
                            *buf_overflow = 1;
 
4051
                        }
 
4052
                    }
 
4053
                }
 
4054
            }
 
4055
            objid += numids;
 
4056
            objidlen -= numids;
 
4057
            break;
 
4058
 
 
4059
        case TYPE_INTEGER32:
 
4060
        case TYPE_UINTEGER:
 
4061
        case TYPE_UNSIGNED32:
 
4062
        case TYPE_GAUGE:
 
4063
        case TYPE_INTEGER:
 
4064
            if (tp->enums) {
 
4065
                struct enum_list *ep = tp->enums;
 
4066
                while (ep && ep->value != (int) (*objid)) {
 
4067
                    ep = ep->next;
 
4068
                }
 
4069
                if (ep) {
 
4070
                    if (!*buf_overflow
 
4071
                        && !snmp_strcat(buf, buf_len, out_len,
 
4072
                                        allow_realloc,
 
4073
                                        (const u_char *) ep->label)) {
 
4074
                        *buf_overflow = 1;
 
4075
                    }
 
4076
                } else {
 
4077
                    sprintf(intbuf, "%lu", *objid);
 
4078
                    if (!*buf_overflow
 
4079
                        && !snmp_strcat(buf, buf_len, out_len,
 
4080
                                        allow_realloc,
 
4081
                                        (const u_char *) intbuf)) {
 
4082
                        *buf_overflow = 1;
 
4083
                    }
 
4084
                }
 
4085
            } else {
 
4086
                sprintf(intbuf, "%lu", *objid);
 
4087
                if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
4088
                                                   allow_realloc,
 
4089
                                                   (const u_char *)
 
4090
                                                   intbuf)) {
 
4091
                    *buf_overflow = 1;
 
4092
                }
 
4093
            }
 
4094
            objid++;
 
4095
            objidlen--;
 
4096
            break;
 
4097
 
 
4098
        case TYPE_OBJID:
 
4099
            if (in_dices->isimplied) {
 
4100
                numids = objidlen;
 
4101
            } else {
 
4102
                numids = (size_t) * objid + 1;
 
4103
            }
 
4104
            if (numids > objidlen)
 
4105
                goto finish_it;
 
4106
            if (extended_index) {
 
4107
                if (in_dices->isimplied) {
 
4108
                    if (!*buf_overflow
 
4109
                        && !netsnmp_sprint_realloc_objid_tree(buf, buf_len,
 
4110
                                                              out_len,
 
4111
                                                              allow_realloc,
 
4112
                                                              buf_overflow,
 
4113
                                                              objid,
 
4114
                                                              numids)) {
 
4115
                        *buf_overflow = 1;
 
4116
                    }
 
4117
                } else {
 
4118
                    if (!*buf_overflow
 
4119
                        && !netsnmp_sprint_realloc_objid_tree(buf, buf_len,
 
4120
                                                              out_len,
 
4121
                                                              allow_realloc,
 
4122
                                                              buf_overflow,
 
4123
                                                              objid + 1,
 
4124
                                                              numids -
 
4125
                                                              1)) {
 
4126
                        *buf_overflow = 1;
 
4127
                    }
 
4128
                }
 
4129
            } else {
 
4130
                _get_realloc_symbol(objid, numids, NULL, buf, buf_len,
 
4131
                                    out_len, allow_realloc, buf_overflow,
 
4132
                                    NULL, NULL);
 
4133
            }
 
4134
            objid += (numids);
 
4135
            objidlen -= (numids);
 
4136
            break;
 
4137
 
 
4138
        case TYPE_IPADDR:
 
4139
            if (objidlen < 4)
 
4140
                goto finish_it;
 
4141
            sprintf(intbuf, "%lu.%lu.%lu.%lu",
 
4142
                    objid[0], objid[1], objid[2], objid[3]);
 
4143
            objid += 4;
 
4144
            objidlen -= 4;
 
4145
            if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
4146
                                               allow_realloc,
 
4147
                                               (const u_char *) intbuf)) {
 
4148
                *buf_overflow = 1;
 
4149
            }
 
4150
            break;
 
4151
 
 
4152
        case TYPE_NETADDR:{
 
4153
                oid             ntype = *objid++;
 
4154
 
 
4155
                objidlen--;
 
4156
                sprintf(intbuf, "%lu.", ntype);
 
4157
                if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
4158
                                                   allow_realloc,
 
4159
                                                   (const u_char *)
 
4160
                                                   intbuf)) {
 
4161
                    *buf_overflow = 1;
 
4162
                }
 
4163
 
 
4164
                if (ntype == 1 && objidlen >= 4) {
 
4165
                    sprintf(intbuf, "%lu.%lu.%lu.%lu",
 
4166
                            objid[0], objid[1], objid[2], objid[3]);
 
4167
                    if (!*buf_overflow
 
4168
                        && !snmp_strcat(buf, buf_len, out_len,
 
4169
                                        allow_realloc,
 
4170
                                        (const u_char *) intbuf)) {
 
4171
                        *buf_overflow = 1;
 
4172
                    }
 
4173
                    objid += 4;
 
4174
                    objidlen -= 4;
 
4175
                } else {
 
4176
                    goto finish_it;
 
4177
                }
 
4178
            }
 
4179
            break;
 
4180
 
 
4181
        case TYPE_NSAPADDRESS:
 
4182
        default:
 
4183
            goto finish_it;
 
4184
            break;
 
4185
        }
 
4186
 
 
4187
        if (extended_index) {
 
4188
            if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
4189
                                               allow_realloc,
 
4190
                                               (const u_char *) "]")) {
 
4191
                *buf_overflow = 1;
 
4192
            }
 
4193
        } else {
 
4194
            if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
 
4195
                                               allow_realloc,
 
4196
                                               (const u_char *) ".")) {
 
4197
                *buf_overflow = 1;
 
4198
            }
 
4199
        }
 
4200
        in_dices = in_dices->next;
 
4201
    }
 
4202
 
 
4203
  finish_it:
 
4204
    _oid_finish_printing(objid, objidlen,
 
4205
                         buf, buf_len, out_len,
 
4206
                         allow_realloc, buf_overflow);
 
4207
    return NULL;
 
4208
}
 
4209
 
 
4210
/**
 
4211
 * Clone of get_symbol that doesn't take a buffer argument.
 
4212
 *
 
4213
 * @see get_symbol
 
4214
 */
 
4215
struct tree    *
 
4216
get_tree(const oid * objid, size_t objidlen, struct tree *subtree)
 
4217
{
 
4218
    struct tree    *return_tree = NULL;
 
4219
 
 
4220
    for (; subtree; subtree = subtree->next_peer) {
 
4221
        if (*objid == subtree->subid)
 
4222
            goto found;
 
4223
    }
 
4224
 
 
4225
    return NULL;
 
4226
 
 
4227
  found:
 
4228
    while (subtree->next_peer && subtree->next_peer->subid == *objid)
 
4229
        subtree = subtree->next_peer;
 
4230
    if (objidlen > 1)
 
4231
        return_tree =
 
4232
            get_tree(objid + 1, objidlen - 1, subtree->child_list);
 
4233
    if (return_tree != NULL)
 
4234
        return return_tree;
 
4235
    else
 
4236
        return subtree;
 
4237
}
 
4238
 
 
4239
/**
 
4240
 * Prints on oid description on stdout.
 
4241
 *
 
4242
 * @see fprint_description
 
4243
 */
 
4244
void
 
4245
print_description(oid * objid, size_t objidlen, /* number of subidentifiers */
 
4246
                  int width)
 
4247
{
 
4248
    fprint_description(stdout, objid, objidlen, width);
 
4249
}
 
4250
 
 
4251
 
 
4252
/**
 
4253
 * Prints on oid description into a file descriptor.
 
4254
 * 
 
4255
 * @param f         The file descriptor to print to.
 
4256
 * @param objid     The object identifier.
 
4257
 * @param objidlen  The object id length.
 
4258
 * @param width     Number of subidentifiers.
 
4259
 */
 
4260
void
 
4261
fprint_description(FILE * f, oid * objid, size_t objidlen,
 
4262
                   int width)
 
4263
{
 
4264
    u_char         *buf = NULL;
 
4265
    size_t          buf_len = 256, out_len = 0;
 
4266
 
 
4267
    if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
 
4268
        fprintf(f, "[TRUNCATED]\n");
 
4269
        return;
 
4270
    } else {
 
4271
        if (!sprint_realloc_description(&buf, &buf_len, &out_len, 1,
 
4272
                                   objid, objidlen, width)) {
 
4273
            fprintf(f, "%s [TRUNCATED]\n", buf);
 
4274
        } else {
 
4275
            fprintf(f, "%s\n", buf);
 
4276
        }
 
4277
    }
 
4278
 
 
4279
    SNMP_FREE(buf);
 
4280
}
 
4281
 
 
4282
int
 
4283
snprint_description(char *buf, size_t buf_len,
 
4284
                    oid * objid, size_t objidlen, int width)
 
4285
{
 
4286
    size_t          out_len = 0;
 
4287
 
 
4288
    if (sprint_realloc_description((u_char **) & buf, &buf_len, &out_len, 0,
 
4289
                                    objid, objidlen, width)) {
 
4290
        return (int) out_len;
 
4291
    } else {
 
4292
        return -1;
 
4293
    }
 
4294
}
 
4295
 
 
4296
int
 
4297
sprint_realloc_description(u_char ** buf, size_t * buf_len,
 
4298
                     size_t * out_len, int allow_realloc,
 
4299
                     oid * objid, size_t objidlen, int width)
 
4300
{
 
4301
    struct tree    *tp = get_tree(objid, objidlen, tree_head);
 
4302
    struct tree    *subtree = tree_head;
 
4303
    int             pos, len;
 
4304
    char            tmpbuf[128];
 
4305
    const char     *cp;
 
4306
 
 
4307
    if (tp->type <= TYPE_SIMPLE_LAST)
 
4308
        cp = " OBJECT-TYPE";
 
4309
    else
 
4310
        switch (tp->type) {
 
4311
        case TYPE_TRAPTYPE:
 
4312
            cp = " TRAP-TYPE";
 
4313
            break;
 
4314
        case TYPE_NOTIFTYPE:
 
4315
            cp = " NOTIFICATION-TYPE";
 
4316
            break;
 
4317
        case TYPE_OBJGROUP:
 
4318
            cp = " OBJECT-GROUP";
 
4319
            break;
 
4320
        case TYPE_AGENTCAP:
 
4321
            cp = " AGENT-CAPABILITIES";
 
4322
            break;
 
4323
        case TYPE_MODID:
 
4324
            cp = " MODULE-IDENTITY";
 
4325
            break;
 
4326
        case TYPE_MODCOMP:
 
4327
            cp = " MODULE-COMPLIANCE";
 
4328
            break;
 
4329
        default:
 
4330
            sprintf(tmpbuf, " type_%d", tp->type);
 
4331
            cp = tmpbuf;
 
4332
        }
 
4333
 
 
4334
    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, tp->label) ||
 
4335
        !snmp_strcat(buf, buf_len, out_len, allow_realloc, cp) ||
 
4336
        !snmp_strcat(buf, buf_len, out_len, allow_realloc, "\n")) {
 
4337
        return 0;
 
4338
    }
 
4339
    if (!print_tree_node(buf, buf_len, out_len, allow_realloc, tp, width))
 
4340
        return 0;
 
4341
    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, "::= {"))
 
4342
        return 0;
 
4343
    pos = 5;
 
4344
    while (objidlen > 1) {
 
4345
        for (; subtree; subtree = subtree->next_peer) {
 
4346
            if (*objid == subtree->subid) {
 
4347
                while (subtree->next_peer && subtree->next_peer->subid == *objid)
 
4348
                    subtree = subtree->next_peer;
 
4349
                if (strncmp(subtree->label, ANON, ANON_LEN)) {
 
4350
                    snprintf(tmpbuf, sizeof(tmpbuf), " %s(%lu)", subtree->label, subtree->subid);
 
4351
                    tmpbuf[ sizeof(tmpbuf)-1 ] = 0;
 
4352
                } else
 
4353
                    sprintf(tmpbuf, " %lu", subtree->subid);
 
4354
                len = strlen(tmpbuf);
 
4355
                if (pos + len + 2 > width) {
 
4356
                    if (!snmp_strcat(buf, buf_len, out_len,
 
4357
                                     allow_realloc, "\n     "))
 
4358
                        return 0;
 
4359
                    pos = 5;
 
4360
                }
 
4361
                if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, tmpbuf))
 
4362
                    return 0;
 
4363
                pos += len;
 
4364
                objid++;
 
4365
                objidlen--;
 
4366
                break;
 
4367
            }
 
4368
        }
 
4369
        if (subtree)
 
4370
            subtree = subtree->child_list;
 
4371
        else
 
4372
            break;
 
4373
    }
 
4374
    while (objidlen > 1) {
 
4375
        sprintf(tmpbuf, " %lu", *objid);
 
4376
        len = strlen(tmpbuf);
 
4377
        if (pos + len + 2 > width) {
 
4378
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, "\n     "))
 
4379
                return 0;
 
4380
            pos = 5;
 
4381
        }
 
4382
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, tmpbuf))
 
4383
            return 0;
 
4384
        pos += len;
 
4385
        objid++;
 
4386
        objidlen--;
 
4387
    }
 
4388
    sprintf(tmpbuf, " %lu }", *objid);
 
4389
    len = strlen(tmpbuf);
 
4390
    if (pos + len + 2 > width) {
 
4391
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, "\n     "))
 
4392
            return 0;
 
4393
        pos = 5;
 
4394
    }
 
4395
    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, tmpbuf))
 
4396
        return 0;
 
4397
    return 1;
 
4398
}
 
4399
 
 
4400
static int
 
4401
print_tree_node(u_char ** buf, size_t * buf_len,
 
4402
                     size_t * out_len, int allow_realloc,
 
4403
                     struct tree *tp, int width)
 
4404
{
 
4405
    const char     *cp;
 
4406
    char            str[MAXTOKEN];
 
4407
    int             i, prevmod, pos, len;
 
4408
 
 
4409
    if (tp) {
 
4410
        module_name(tp->modid, str);
 
4411
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, "  -- FROM\t") ||
 
4412
            !snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
 
4413
            return 0;
 
4414
        pos = 16+strlen(str);
 
4415
        for (i = 1, prevmod = tp->modid; i < tp->number_modules; i++) {
 
4416
            if (prevmod != tp->module_list[i]) {
 
4417
                module_name(tp->module_list[i], str);
 
4418
                len = strlen(str);
 
4419
                if (pos + len + 2 > width) {
 
4420
                    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4421
                                     ",\n  --\t\t"))
 
4422
                        return 0;
 
4423
                    pos = 16;
 
4424
                }
 
4425
                else {
 
4426
                    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, ", "))
 
4427
                        return 0;
 
4428
                    pos += 2;
 
4429
                }
 
4430
                if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
 
4431
                    return 0;
 
4432
                pos += len;
 
4433
            }
 
4434
            prevmod = tp->module_list[i];
 
4435
        }
 
4436
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, "\n"))
 
4437
            return 0;
 
4438
        if (tp->tc_index != -1) {
 
4439
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4440
                             "  -- TEXTUAL CONVENTION ") ||
 
4441
                !snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4442
                             get_tc_descriptor(tp->tc_index)) ||
 
4443
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, "\n"))
 
4444
                return 0;
 
4445
        }
 
4446
        switch (tp->type) {
 
4447
        case TYPE_OBJID:
 
4448
            cp = "OBJECT IDENTIFIER";
 
4449
            break;
 
4450
        case TYPE_OCTETSTR:
 
4451
            cp = "OCTET STRING";
 
4452
            break;
 
4453
        case TYPE_INTEGER:
 
4454
            cp = "INTEGER";
 
4455
            break;
 
4456
        case TYPE_NETADDR:
 
4457
            cp = "NetworkAddress";
 
4458
            break;
 
4459
        case TYPE_IPADDR:
 
4460
            cp = "IpAddress";
 
4461
            break;
 
4462
        case TYPE_COUNTER:
 
4463
            cp = "Counter32";
 
4464
            break;
 
4465
        case TYPE_GAUGE:
 
4466
            cp = "Gauge32";
 
4467
            break;
 
4468
        case TYPE_TIMETICKS:
 
4469
            cp = "TimeTicks";
 
4470
            break;
 
4471
        case TYPE_OPAQUE:
 
4472
            cp = "Opaque";
 
4473
            break;
 
4474
        case TYPE_NULL:
 
4475
            cp = "NULL";
 
4476
            break;
 
4477
        case TYPE_COUNTER64:
 
4478
            cp = "Counter64";
 
4479
            break;
 
4480
        case TYPE_BITSTRING:
 
4481
            cp = "BITS";
 
4482
            break;
 
4483
        case TYPE_NSAPADDRESS:
 
4484
            cp = "NsapAddress";
 
4485
            break;
 
4486
        case TYPE_UINTEGER:
 
4487
            cp = "UInteger32";
 
4488
            break;
 
4489
        case TYPE_UNSIGNED32:
 
4490
            cp = "Unsigned32";
 
4491
            break;
 
4492
        case TYPE_INTEGER32:
 
4493
            cp = "Integer32";
 
4494
            break;
 
4495
        default:
 
4496
            cp = NULL;
 
4497
            break;
 
4498
        }
 
4499
#if SNMP_TESTING_CODE
 
4500
        if (!cp && (tp->ranges || tp->enums)) { /* ranges without type ? */
 
4501
            sprintf(str, "?0 with %s %s ?",
 
4502
                    tp->ranges ? "Range" : "", tp->enums ? "Enum" : "");
 
4503
            cp = str;
 
4504
        }
 
4505
#endif                          /* SNMP_TESTING_CODE */
 
4506
        if (cp)
 
4507
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4508
                             "  SYNTAX\t") ||
 
4509
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, cp))
 
4510
                return 0;
 
4511
        if (tp->ranges) {
 
4512
            struct range_list *rp = tp->ranges;
 
4513
            int             first = 1;
 
4514
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, " ("))
 
4515
                return 0;
 
4516
            while (rp) {
 
4517
                if (rp->low == rp->high)
 
4518
                    sprintf(str, "%s%d", (first ? "" : " | "), rp->low );
 
4519
                else
 
4520
                    sprintf(str, "%s%d..%d", (first ? "" : " | "),
 
4521
                                              rp->low, rp->high);
 
4522
                if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
 
4523
                    return 0;
 
4524
                if (first)
 
4525
                    first = 0;
 
4526
                rp = rp->next;
 
4527
            }
 
4528
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, ") "))
 
4529
                return 0;
 
4530
        }
 
4531
        if (tp->enums) {
 
4532
            struct enum_list *ep = tp->enums;
 
4533
            int             first = 1;
 
4534
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, " {"))
 
4535
                return 0;
 
4536
            pos = 16 + strlen(cp) + 2;
 
4537
            while (ep) {
 
4538
                if (first)
 
4539
                    first = 0;
 
4540
                else
 
4541
                    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, ", "))
 
4542
                        return 0;
 
4543
                snprintf(str, sizeof(str), "%s(%d)", ep->label, ep->value);
 
4544
                str[ sizeof(str)-1 ] = 0;
 
4545
                len = strlen(str);
 
4546
                if (pos + len + 2 > width) {
 
4547
                    if (!snmp_strcat(buf, buf_len, out_len,
 
4548
                                     allow_realloc, "\n\t\t  "))
 
4549
                        return 0;
 
4550
                    pos = 18;
 
4551
                }
 
4552
                if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
 
4553
                    return 0;
 
4554
                pos += len + 2;
 
4555
                ep = ep->next;
 
4556
            }
 
4557
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, "} "))
 
4558
                return 0;
 
4559
        }
 
4560
        if (cp)
 
4561
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, "\n"))
 
4562
                return 0;
 
4563
        if (tp->hint)
 
4564
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4565
                             "  DISPLAY-HINT\t\"") ||
 
4566
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, tp->hint) ||
 
4567
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, "\"\n"))
 
4568
                return 0;
 
4569
        if (tp->units)
 
4570
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4571
                             "  UNITS\t\"") ||
 
4572
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, tp->hint) ||
 
4573
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, "\"\n"))
 
4574
                return 0;
 
4575
        switch (tp->access) {
 
4576
        case MIB_ACCESS_READONLY:
 
4577
            cp = "read-only";
 
4578
            break;
 
4579
        case MIB_ACCESS_READWRITE:
 
4580
            cp = "read-write";
 
4581
            break;
 
4582
        case MIB_ACCESS_WRITEONLY:
 
4583
            cp = "write-only";
 
4584
            break;
 
4585
        case MIB_ACCESS_NOACCESS:
 
4586
            cp = "not-accessible";
 
4587
            break;
 
4588
        case MIB_ACCESS_NOTIFY:
 
4589
            cp = "accessible-for-notify";
 
4590
            break;
 
4591
        case MIB_ACCESS_CREATE:
 
4592
            cp = "read-create";
 
4593
            break;
 
4594
        case 0:
 
4595
            cp = NULL;
 
4596
            break;
 
4597
        default:
 
4598
            sprintf(str, "access_%d", tp->access);
 
4599
            cp = str;
 
4600
        }
 
4601
        if (cp)
 
4602
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4603
                             "  MAX-ACCESS\t") ||
 
4604
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, cp) ||
 
4605
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, "\n"))
 
4606
                return 0;
 
4607
        switch (tp->status) {
 
4608
        case MIB_STATUS_MANDATORY:
 
4609
            cp = "mandatory";
 
4610
            break;
 
4611
        case MIB_STATUS_OPTIONAL:
 
4612
            cp = "optional";
 
4613
            break;
 
4614
        case MIB_STATUS_OBSOLETE:
 
4615
            cp = "obsolete";
 
4616
            break;
 
4617
        case MIB_STATUS_DEPRECATED:
 
4618
            cp = "deprecated";
 
4619
            break;
 
4620
        case MIB_STATUS_CURRENT:
 
4621
            cp = "current";
 
4622
            break;
 
4623
        case 0:
 
4624
            cp = NULL;
 
4625
            break;
 
4626
        default:
 
4627
            sprintf(str, "status_%d", tp->status);
 
4628
            cp = str;
 
4629
        }
 
4630
#if SNMP_TESTING_CODE
 
4631
        if (!cp && (tp->indexes)) {     /* index without status ? */
 
4632
            sprintf(str, "?0 with %s ?", tp->indexes ? "Index" : "");
 
4633
            cp = str;
 
4634
        }
 
4635
#endif                          /* SNMP_TESTING_CODE */
 
4636
        if (cp)
 
4637
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4638
                             "  STATUS\t") ||
 
4639
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, cp) ||
 
4640
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, "\n"))
 
4641
                return 0;
 
4642
        if (tp->augments)
 
4643
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4644
                             "  AUGMENTS\t{ ") ||
 
4645
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, tp->augments) ||
 
4646
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, " }\n"))
 
4647
                return 0;
 
4648
        if (tp->indexes) {
 
4649
            struct index_list *ip = tp->indexes;
 
4650
            int             first = 1;
 
4651
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4652
                             "  INDEX\t\t{ "))
 
4653
                return 0;
 
4654
            pos = 16 + 2;
 
4655
            while (ip) {
 
4656
                if (first)
 
4657
                    first = 0;
 
4658
                else
 
4659
                    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, ", "))
 
4660
                        return 0;
 
4661
                snprintf(str, sizeof(str), "%s%s",
 
4662
                        ip->isimplied ? "IMPLIED " : "",
 
4663
                        ip->ilabel);
 
4664
                str[ sizeof(str)-1 ] = 0;
 
4665
                len = strlen(str);
 
4666
                if (pos + len + 2 > width) {
 
4667
                    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, "\n\t\t  "))
 
4668
                        return 0;
 
4669
                    pos = 16 + 2;
 
4670
                }
 
4671
                if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
 
4672
                    return 0;
 
4673
                pos += len + 2;
 
4674
                ip = ip->next;
 
4675
            }
 
4676
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, " }\n"))
 
4677
                return 0;
 
4678
        }
 
4679
        if (tp->varbinds) {
 
4680
            struct varbind_list *vp = tp->varbinds;
 
4681
            int             first = 1;
 
4682
 
 
4683
            if (tp->type == TYPE_TRAPTYPE) {
 
4684
                if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4685
                    "  VARIABLES\t{ "))
 
4686
                    return 0;
 
4687
            } else {
 
4688
                if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4689
                    "  OBJECTS\t{ "))
 
4690
                    return 0;
 
4691
            }
 
4692
            pos = 16 + 2;
 
4693
            while (vp) {
 
4694
                if (first)
 
4695
                    first = 0;
 
4696
                else
 
4697
                    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, ", "))
 
4698
                        return 0;
 
4699
                snprintf(str, sizeof(str), "%s", vp->vblabel);
 
4700
                str[ sizeof(str)-1 ] = 0;
 
4701
                len = strlen(str);
 
4702
                if (pos + len + 2 > width) {
 
4703
                    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4704
                                    "\n\t\t  "))
 
4705
                        return 0;
 
4706
                    pos = 16 + 2;
 
4707
                }
 
4708
                if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
 
4709
                    return 0;
 
4710
                pos += len + 2;
 
4711
                vp = vp->next;
 
4712
            }
 
4713
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, " }\n"))
 
4714
                return 0;
 
4715
        }
 
4716
        if (tp->description)
 
4717
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4718
                             "  DESCRIPTION\t\"") ||
 
4719
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, tp->description) ||
 
4720
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, "\"\n"))
 
4721
                return 0;
 
4722
        if (tp->defaultValue)
 
4723
            if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
 
4724
                             "  DEFVAL\t{ ") ||
 
4725
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, tp->defaultValue) ||
 
4726
                !snmp_strcat(buf, buf_len, out_len, allow_realloc, " }\n"))
 
4727
                return 0;
 
4728
    } else
 
4729
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, "No description\n"))
 
4730
            return 0;
 
4731
    return 1;
 
4732
}
 
4733
 
 
4734
int
 
4735
get_module_node(const char *fname,
 
4736
                const char *module, oid * objid, size_t * objidlen)
 
4737
{
 
4738
    int             modid, rc = 0;
 
4739
    struct tree    *tp;
 
4740
    char           *name, *cp;
 
4741
 
 
4742
    if (!strcmp(module, "ANY"))
 
4743
        modid = -1;
 
4744
    else {
 
4745
        read_module(module);
 
4746
        modid = which_module(module);
 
4747
        if (modid == -1)
 
4748
            return 0;
 
4749
    }
 
4750
 
 
4751
    /*
 
4752
     * Isolate the first component of the name ... 
 
4753
     */
 
4754
    name = strdup(fname);
 
4755
    cp = strchr(name, '.');
 
4756
    if (cp != NULL) {
 
4757
        *cp = '\0';
 
4758
        cp++;
 
4759
    }
 
4760
    /*
 
4761
     * ... and locate it in the tree. 
 
4762
     */
 
4763
    tp = find_tree_node(name, modid);
 
4764
    if (tp) {
 
4765
        size_t          maxlen = *objidlen;
 
4766
 
 
4767
        /*
 
4768
         * Set the first element of the object ID 
 
4769
         */
 
4770
        if (node_to_oid(tp, objid, objidlen)) {
 
4771
            rc = 1;
 
4772
 
 
4773
            /*
 
4774
             * If the name requested was more than one element,
 
4775
             * tag on the rest of the components 
 
4776
             */
 
4777
            if (cp != NULL)
 
4778
                rc = _add_strings_to_oid(tp, cp, objid, objidlen, maxlen);
 
4779
        }
 
4780
    }
 
4781
 
 
4782
    SNMP_FREE(name);
 
4783
    return (rc);
 
4784
}
 
4785
 
 
4786
 
 
4787
/**
 
4788
 * @internal
 
4789
 *
 
4790
 * Populates the object identifier from a node in the MIB hierarchy.
 
4791
 * Builds up the object ID, working backwards,
 
4792
 * starting from the end of the objid buffer.
 
4793
 * When the top of the MIB tree is reached, the buffer is adjusted.
 
4794
 *
 
4795
 * The buffer length is set to the number of subidentifiers
 
4796
 * for the object identifier associated with the MIB node.
 
4797
 * 
 
4798
 * @return the number of subidentifiers copied.
 
4799
 *
 
4800
 * If 0 is returned, the objid buffer is too small,
 
4801
 * and the buffer contents are indeterminate.
 
4802
 * The buffer length can be used to create a larger buffer.
 
4803
 */
 
4804
static int
 
4805
node_to_oid(struct tree *tp, oid * objid, size_t * objidlen)
 
4806
{
 
4807
    int             numids, lenids;
 
4808
    oid            *op;
 
4809
 
 
4810
    if (!tp || !objid || !objidlen)
 
4811
        return 0;
 
4812
 
 
4813
    lenids = (int) *objidlen;
 
4814
    op = objid + lenids;        /* points after the last element */
 
4815
 
 
4816
    for (numids = 0; tp; tp = tp->parent, numids++) {
 
4817
        if (numids >= lenids)
 
4818
            continue;
 
4819
        --op;
 
4820
        *op = tp->subid;
 
4821
    }
 
4822
 
 
4823
    *objidlen = (size_t) numids;
 
4824
    if (numids > lenids) {
 
4825
        return 0;
 
4826
    }
 
4827
 
 
4828
    if (numids < lenids)
 
4829
        memmove(objid, op, numids * sizeof(oid));
 
4830
 
 
4831
    return (numids);
 
4832
}
 
4833
#endif /* DISABLE_MIB_LOADING */
 
4834
 
 
4835
/*
 
4836
 * Replace \x with x stop at eos_marker
 
4837
 * return NULL if eos_marker not found
 
4838
 */
 
4839
static char *_apply_escapes(char *src, char eos_marker)
 
4840
{
 
4841
    char *dst;
 
4842
    int backslash = 0;
 
4843
    
 
4844
    dst = src;
 
4845
    while (*src) {
 
4846
        if (backslash) {
 
4847
            backslash = 0;
 
4848
            *dst++ = *src;
 
4849
        } else {
 
4850
            if (eos_marker == *src) break;
 
4851
            if ('\\' == *src) {
 
4852
                backslash = 1;
 
4853
            } else {
 
4854
                *dst++ = *src;
 
4855
            }
 
4856
        }
 
4857
        src++;
 
4858
    }
 
4859
    if (!*src) {
 
4860
        /* never found eos_marker */
 
4861
        return NULL;
 
4862
    } else {
 
4863
        *dst = 0;
 
4864
        return src;
 
4865
    }
 
4866
}
 
4867
 
 
4868
static int
 
4869
#ifndef DISABLE_MIB_LOADING
 
4870
_add_strings_to_oid(struct tree *tp, char *cp,
 
4871
                    oid * objid, size_t * objidlen, size_t maxlen)
 
4872
#else
 
4873
_add_strings_to_oid(void *tp, char *cp,
 
4874
                    oid * objid, size_t * objidlen, size_t maxlen)
 
4875
#endif /* DISABLE_MIB_LOADING */
 
4876
{
 
4877
    oid             subid;
 
4878
    int             len_index = 1000000;
 
4879
#ifndef DISABLE_MIB_LOADING
 
4880
    struct tree    *tp2 = NULL;
 
4881
    struct index_list *in_dices = NULL;
 
4882
#endif /* DISABLE_MIB_LOADING */
 
4883
    char           *fcp, *ecp, *cp2 = NULL;
 
4884
    char            doingquote;
 
4885
    int             len = -1, pos = -1;
 
4886
#ifndef DISABLE_MIB_LOADING
 
4887
    int             check =
 
4888
        !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE);
 
4889
    int             do_hint = !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT);
 
4890
 
 
4891
    while (cp && tp && tp->child_list) {
 
4892
        fcp = cp;
 
4893
        tp2 = tp->child_list;
 
4894
        /*
 
4895
         * Isolate the next entry 
 
4896
         */
 
4897
        cp2 = strchr(cp, '.');
 
4898
        if (cp2)
 
4899
            *cp2++ = '\0';
 
4900
 
 
4901
        /*
 
4902
         * Search for the appropriate child 
 
4903
         */
 
4904
        if (isdigit(*cp)) {
 
4905
            subid = strtoul(cp, &ecp, 0);
 
4906
            if (*ecp)
 
4907
                goto bad_id;
 
4908
            while (tp2 && tp2->subid != subid)
 
4909
                tp2 = tp2->next_peer;
 
4910
        } else {
 
4911
            while (tp2 && strcmp(tp2->label, fcp))
 
4912
                tp2 = tp2->next_peer;
 
4913
            if (!tp2)
 
4914
                goto bad_id;
 
4915
            subid = tp2->subid;
 
4916
        }
 
4917
        if (*objidlen >= maxlen)
 
4918
            goto bad_id;
 
4919
        while (tp2 && tp2->next_peer && tp2->next_peer->subid == subid)
 
4920
            tp2 = tp2->next_peer;
 
4921
        objid[*objidlen] = subid;
 
4922
        (*objidlen)++;
 
4923
 
 
4924
        cp = cp2;
 
4925
        if (!tp2)
 
4926
            break;
 
4927
        tp = tp2;
 
4928
    }
 
4929
 
 
4930
    if (tp && !tp->child_list) {
 
4931
        if ((tp2 = tp->parent)) {
 
4932
            if (tp2->indexes)
 
4933
                in_dices = tp2->indexes;
 
4934
            else if (tp2->augments) {
 
4935
                tp2 = find_tree_node(tp2->augments, -1);
 
4936
                if (tp2)
 
4937
                    in_dices = tp2->indexes;
 
4938
            }
 
4939
        }
 
4940
        tp = NULL;
 
4941
    }
 
4942
 
 
4943
    while (cp && in_dices) {
 
4944
        fcp = cp;
 
4945
 
 
4946
        tp = find_tree_node(in_dices->ilabel, -1);
 
4947
        if (!tp)
 
4948
            break;
 
4949
        switch (tp->type) {
 
4950
        case TYPE_INTEGER:
 
4951
        case TYPE_INTEGER32:
 
4952
        case TYPE_UINTEGER:
 
4953
        case TYPE_UNSIGNED32:
 
4954
        case TYPE_TIMETICKS:
 
4955
            /*
 
4956
             * Isolate the next entry 
 
4957
             */
 
4958
            cp2 = strchr(cp, '.');
 
4959
            if (cp2)
 
4960
                *cp2++ = '\0';
 
4961
            if (isdigit(*cp)) {
 
4962
                subid = strtoul(cp, &ecp, 0);
 
4963
                if (*ecp)
 
4964
                    goto bad_id;
 
4965
            } else {
 
4966
                if (tp->enums) {
 
4967
                    struct enum_list *ep = tp->enums;
 
4968
                    while (ep && strcmp(ep->label, cp))
 
4969
                        ep = ep->next;
 
4970
                    if (!ep)
 
4971
                        goto bad_id;
 
4972
                    subid = ep->value;
 
4973
                } else
 
4974
                    goto bad_id;
 
4975
            }
 
4976
            if (check && tp->ranges) {
 
4977
                struct range_list *rp = tp->ranges;
 
4978
                int             ok = 0;
 
4979
                while (!ok && rp)
 
4980
                    if ((rp->low <= (int) subid)
 
4981
                        && ((int) subid <= rp->high))
 
4982
                        ok = 1;
 
4983
                    else
 
4984
                        rp = rp->next;
 
4985
                if (!ok)
 
4986
                    goto bad_id;
 
4987
            }
 
4988
            if (*objidlen >= maxlen)
 
4989
                goto bad_id;
 
4990
            objid[*objidlen] = subid;
 
4991
            (*objidlen)++;
 
4992
            break;
 
4993
        case TYPE_IPADDR:
 
4994
            if (*objidlen + 4 > maxlen)
 
4995
                goto bad_id;
 
4996
            for (subid = 0; cp && subid < 4; subid++) {
 
4997
                fcp = cp;
 
4998
                cp2 = strchr(cp, '.');
 
4999
                if (cp2)
 
5000
                    *cp2++ = 0;
 
5001
                objid[*objidlen] = strtoul(cp, &ecp, 0);
 
5002
                if (*ecp)
 
5003
                    goto bad_id;
 
5004
                if (check && objid[*objidlen] > 255)
 
5005
                    goto bad_id;
 
5006
                (*objidlen)++;
 
5007
                cp = cp2;
 
5008
            }
 
5009
            break;
 
5010
        case TYPE_OCTETSTR:
 
5011
            if (tp->ranges && !tp->ranges->next
 
5012
                && tp->ranges->low == tp->ranges->high)
 
5013
                len = tp->ranges->low;
 
5014
            else
 
5015
                len = -1;
 
5016
            pos = 0;
 
5017
            if (*cp == '"' || *cp == '\'') {
 
5018
                doingquote = *cp++;
 
5019
                /*
 
5020
                 * insert length if requested 
 
5021
                 */
 
5022
                if (!in_dices->isimplied && len == -1) {
 
5023
                    if (doingquote == '\'') {
 
5024
                        snmp_set_detail
 
5025
                            ("'-quote is for fixed length strings");
 
5026
                        return 0;
 
5027
                    }
 
5028
                    if (*objidlen >= maxlen)
 
5029
                        goto bad_id;
 
5030
                    len_index = *objidlen;
 
5031
                    (*objidlen)++;
 
5032
                } else if (doingquote == '"') {
 
5033
                    snmp_set_detail
 
5034
                        ("\"-quote is for variable length strings");
 
5035
                    return 0;
 
5036
                }
 
5037
 
 
5038
                cp2 = _apply_escapes(cp, doingquote);
 
5039
                if (!cp2) goto bad_id;
 
5040
                else {
 
5041
                    unsigned char *new_val;
 
5042
                    int new_val_len;
 
5043
                    int parsed_hint = 0;
 
5044
                    const char *parsed_value;
 
5045
 
 
5046
                    if (do_hint && tp->hint) {
 
5047
                        parsed_value = parse_octet_hint(tp->hint, cp,
 
5048
                                                        &new_val, &new_val_len);
 
5049
                        parsed_hint = parsed_value == NULL;
 
5050
                    }
 
5051
                    if (parsed_hint) {
 
5052
                        int i;
 
5053
                        for (i = 0; i < new_val_len; i++) {
 
5054
                            if (*objidlen >= maxlen) goto bad_id;
 
5055
                            objid[ *objidlen ] = new_val[i];
 
5056
                            (*objidlen)++;
 
5057
                            pos++;
 
5058
                        }
 
5059
                        SNMP_FREE(new_val);
 
5060
                    } else {
 
5061
                        while(*cp) {
 
5062
                            if (*objidlen >= maxlen) goto bad_id;
 
5063
                            objid[ *objidlen ] = *cp++;
 
5064
                            (*objidlen)++;
 
5065
                            pos++;
 
5066
                        }
 
5067
                    }
 
5068
                }
 
5069
                
 
5070
                cp2++;
 
5071
                if (!*cp2)
 
5072
                    cp2 = NULL;
 
5073
                else if (*cp2 != '.')
 
5074
                    goto bad_id;
 
5075
                else
 
5076
                    cp2++;
 
5077
                if (check) {
 
5078
                    if (len == -1) {
 
5079
                        struct range_list *rp = tp->ranges;
 
5080
                        int             ok = 0;
 
5081
                        while (rp && !ok)
 
5082
                            if (rp->low <= pos && pos <= rp->high)
 
5083
                                ok = 1;
 
5084
                            else
 
5085
                                rp = rp->next;
 
5086
                        if (!ok)
 
5087
                            goto bad_id;
 
5088
                        if (!in_dices->isimplied)
 
5089
                            objid[len_index] = pos;
 
5090
                    } else if (pos != len)
 
5091
                        goto bad_id;
 
5092
                }
 
5093
                else if (len == -1 && !in_dices->isimplied)
 
5094
                    objid[len_index] = pos;
 
5095
            } else {
 
5096
                if (!in_dices->isimplied && len == -1) {
 
5097
                    fcp = cp;
 
5098
                    cp2 = strchr(cp, '.');
 
5099
                    if (cp2)
 
5100
                        *cp2++ = 0;
 
5101
                    len = strtoul(cp, &ecp, 0);
 
5102
                    if (*ecp)
 
5103
                        goto bad_id;
 
5104
                    if (*objidlen + len + 1 >= maxlen)
 
5105
                        goto bad_id;
 
5106
                    objid[*objidlen] = len;
 
5107
                    (*objidlen)++;
 
5108
                    cp = cp2;
 
5109
                }
 
5110
                while (len && cp) {
 
5111
                    fcp = cp;
 
5112
                    cp2 = strchr(cp, '.');
 
5113
                    if (cp2)
 
5114
                        *cp2++ = 0;
 
5115
                    objid[*objidlen] = strtoul(cp, &ecp, 0);
 
5116
                    if (*ecp)
 
5117
                        goto bad_id;
 
5118
                    if (check && objid[*objidlen] > 255)
 
5119
                        goto bad_id;
 
5120
                    (*objidlen)++;
 
5121
                    len--;
 
5122
                    cp = cp2;
 
5123
                }
 
5124
            }
 
5125
            break;
 
5126
        case TYPE_OBJID:
 
5127
            in_dices = NULL;
 
5128
            cp2 = cp;
 
5129
            break;
 
5130
        case TYPE_NETADDR:
 
5131
            fcp = cp;
 
5132
            cp2 = strchr(cp, '.');
 
5133
            if (cp2)
 
5134
                *cp2++ = 0;
 
5135
            subid = strtoul(cp, &ecp, 0);
 
5136
            if (*ecp)
 
5137
                goto bad_id;
 
5138
            if (*objidlen + 1 >= maxlen)
 
5139
                goto bad_id;
 
5140
            objid[*objidlen] = subid;
 
5141
            (*objidlen)++;
 
5142
            cp = cp2;
 
5143
            if (subid == 1) {
 
5144
                for (len = 0; len < 4; len++) {
 
5145
                    fcp = cp;
 
5146
                    cp2 = strchr(cp, '.');
 
5147
                    if (cp2)
 
5148
                        *cp2++ = 0;
 
5149
                    subid = strtoul(cp, &ecp, 0);
 
5150
                    if (*ecp)
 
5151
                        goto bad_id;
 
5152
                    if (*objidlen + 1 >= maxlen)
 
5153
                        goto bad_id;
 
5154
                    if (subid > 255)
 
5155
                        goto bad_id;
 
5156
                    objid[*objidlen++] = subid;
 
5157
                    cp = cp2;
 
5158
                    if (!cp)
 
5159
                        goto bad_id;
 
5160
                }
 
5161
            }
 
5162
            else {
 
5163
                in_dices = NULL;
 
5164
            }
 
5165
            break;
 
5166
        default:
 
5167
            snmp_log(LOG_ERR, "Unexpected index type: %d %s %s\n",
 
5168
                     tp->type, in_dices->ilabel, cp);
 
5169
            in_dices = NULL;
 
5170
            cp2 = cp;
 
5171
            break;
 
5172
        }
 
5173
        cp = cp2;
 
5174
        if (in_dices)
 
5175
            in_dices = in_dices->next;
 
5176
    }
 
5177
 
 
5178
#endif /* DISABLE_MIB_LOADING */
 
5179
    while (cp) {
 
5180
        fcp = cp;
 
5181
        switch (*cp) {
 
5182
        case '0':
 
5183
        case '1':
 
5184
        case '2':
 
5185
        case '3':
 
5186
        case '4':
 
5187
        case '5':
 
5188
        case '6':
 
5189
        case '7':
 
5190
        case '8':
 
5191
        case '9':
 
5192
            cp2 = strchr(cp, '.');
 
5193
            if (cp2)
 
5194
                *cp2++ = 0;
 
5195
            subid = strtoul(cp, &ecp, 0);
 
5196
            if (*ecp)
 
5197
                goto bad_id;
 
5198
            if (*objidlen >= maxlen)
 
5199
                goto bad_id;
 
5200
            objid[*objidlen] = subid;
 
5201
            (*objidlen)++;
 
5202
            break;
 
5203
        case '"':
 
5204
        case '\'':
 
5205
            doingquote = *cp++;
 
5206
            /*
 
5207
             * insert length if requested 
 
5208
             */
 
5209
            if (doingquote == '"') {
 
5210
                if (*objidlen >= maxlen)
 
5211
                    goto bad_id;
 
5212
                objid[*objidlen] = len = strchr(cp, doingquote) - cp;
 
5213
                (*objidlen)++;
 
5214
            }
 
5215
 
 
5216
            while (*cp && *cp != doingquote) {
 
5217
                if (*objidlen >= maxlen)
 
5218
                    goto bad_id;
 
5219
                objid[*objidlen] = *cp++;
 
5220
                (*objidlen)++;
 
5221
            }
 
5222
            if (!cp)
 
5223
                goto bad_id;
 
5224
            cp2 = cp + 1;
 
5225
            if (!*cp2)
 
5226
                cp2 = NULL;
 
5227
            else if (*cp2 == '.')
 
5228
                cp2++;
 
5229
            else
 
5230
                goto bad_id;
 
5231
            break;
 
5232
        default:
 
5233
            goto bad_id;
 
5234
        }
 
5235
        cp = cp2;
 
5236
    }
 
5237
    return 1;
 
5238
 
 
5239
  bad_id:
 
5240
    {
 
5241
        char            buf[256];
 
5242
#ifndef DISABLE_MIB_LOADING
 
5243
        if (in_dices)
 
5244
            snprintf(buf, sizeof(buf), "Index out of range: %s (%s)",
 
5245
                    fcp, in_dices->ilabel);
 
5246
        else if (tp)
 
5247
            snprintf(buf, sizeof(buf), "Sub-id not found: %s -> %s", tp->label, fcp);
 
5248
        else
 
5249
#endif /* DISABLE_MIB_LOADING */
 
5250
            snprintf(buf, sizeof(buf), "%s", fcp);
 
5251
        buf[ sizeof(buf)-1 ] = 0;
 
5252
 
 
5253
        snmp_set_detail(buf);
 
5254
    }
 
5255
    return 0;
 
5256
}
 
5257
 
 
5258
 
 
5259
#ifndef DISABLE_MIB_LOADING
 
5260
/**
 
5261
 * @see comments on find_best_tree_node for usage after first time.
 
5262
 */
 
5263
int
 
5264
get_wild_node(const char *name, oid * objid, size_t * objidlen)
 
5265
{
 
5266
    struct tree    *tp = find_best_tree_node(name, tree_head, NULL);
 
5267
    if (!tp)
 
5268
        return 0;
 
5269
    return get_node(tp->label, objid, objidlen);
 
5270
}
 
5271
 
 
5272
int
 
5273
get_node(const char *name, oid * objid, size_t * objidlen)
 
5274
{
 
5275
    const char     *cp;
 
5276
    char            ch;
 
5277
    int             res;
 
5278
 
 
5279
    cp = name;
 
5280
    while ((ch = *cp))
 
5281
        if (('0' <= ch && ch <= '9')
 
5282
            || ('a' <= ch && ch <= 'z')
 
5283
            || ('A' <= ch && ch <= 'Z')
 
5284
            || ch == '-')
 
5285
            cp++;
 
5286
        else
 
5287
            break;
 
5288
    if (ch != ':')
 
5289
        if (*name == '.')
 
5290
            res = get_module_node(name + 1, "ANY", objid, objidlen);
 
5291
        else
 
5292
            res = get_module_node(name, "ANY", objid, objidlen);
 
5293
    else {
 
5294
        char           *module;
 
5295
        /*
 
5296
         *  requested name is of the form
 
5297
         *      "module:subidentifier"
 
5298
         */
 
5299
        module = (char *) malloc((size_t) (cp - name + 1));
 
5300
        if (!module)
 
5301
            return SNMPERR_GENERR;
 
5302
        memcpy(module, name, (size_t) (cp - name));
 
5303
        module[cp - name] = 0;
 
5304
        cp++;                   /* cp now point to the subidentifier */
 
5305
        if (*cp == ':')
 
5306
            cp++;
 
5307
 
 
5308
        /*
 
5309
         * 'cp' and 'name' *do* go that way round! 
 
5310
         */
 
5311
        res = get_module_node(cp, module, objid, objidlen);
 
5312
        SNMP_FREE(module);
 
5313
    }
 
5314
    if (res == 0) {
 
5315
        SET_SNMP_ERROR(SNMPERR_UNKNOWN_OBJID);
 
5316
    }
 
5317
 
 
5318
    return res;
 
5319
}
 
5320
#endif /* DISABLE_MIB_LOADING */
 
5321
 
 
5322
#ifdef testing
 
5323
 
 
5324
main(int argc, char *argv[])
 
5325
{
 
5326
    oid             objid[MAX_OID_LEN];
 
5327
    int             objidlen = MAX_OID_LEN;
 
5328
    int             count;
 
5329
    netsnmp_variable_list variable;
 
5330
 
 
5331
    init_mib();
 
5332
    if (argc < 2)
 
5333
        print_subtree(stdout, tree_head, 0);
 
5334
    variable.type = ASN_INTEGER;
 
5335
    variable.val.integer = 3;
 
5336
    variable.val_len = 4;
 
5337
    for (argc--; argc; argc--, argv++) {
 
5338
        objidlen = MAX_OID_LEN;
 
5339
        printf("read_objid(%s) = %d\n",
 
5340
               argv[1], read_objid(argv[1], objid, &objidlen));
 
5341
        for (count = 0; count < objidlen; count++)
 
5342
            printf("%d.", objid[count]);
 
5343
        printf("\n");
 
5344
        print_variable(objid, objidlen, &variable);
 
5345
    }
 
5346
}
 
5347
 
 
5348
#endif                          /* testing */
 
5349
 
 
5350
#ifndef DISABLE_MIB_LOADING
 
5351
/*
 
5352
 * initialize: no peers included in the report. 
 
5353
 */
 
5354
void
 
5355
clear_tree_flags(register struct tree *tp)
 
5356
{
 
5357
    for (; tp; tp = tp->next_peer) {
 
5358
        tp->reported = 0;
 
5359
        if (tp->child_list)
 
5360
            clear_tree_flags(tp->child_list);
 
5361
     /*RECURSE*/}
 
5362
}
 
5363
 
 
5364
/*
 
5365
 * Update: 1998-07-17 <jhy@gsu.edu>
 
5366
 * Added print_oid_report* functions.
 
5367
 */
 
5368
static int      print_subtree_oid_report_labeledoid = 0;
 
5369
static int      print_subtree_oid_report_oid = 0;
 
5370
static int      print_subtree_oid_report_symbolic = 0;
 
5371
static int      print_subtree_oid_report_suffix = 0;
 
5372
 
 
5373
/*
 
5374
 * These methods recurse. 
 
5375
 */
 
5376
static void     print_parent_labeledoid(FILE *, struct tree *);
 
5377
static void     print_parent_oid(FILE *, struct tree *);
 
5378
static void     print_parent_label(FILE *, struct tree *);
 
5379
static void     print_subtree_oid_report(FILE *, struct tree *, int);
 
5380
 
 
5381
 
 
5382
void
 
5383
print_oid_report(FILE * fp)
 
5384
{
 
5385
    struct tree    *tp;
 
5386
    clear_tree_flags(tree_head);
 
5387
    for (tp = tree_head; tp; tp = tp->next_peer)
 
5388
        print_subtree_oid_report(fp, tp, 0);
 
5389
}
 
5390
 
 
5391
void
 
5392
print_oid_report_enable_labeledoid(void)
 
5393
{
 
5394
    print_subtree_oid_report_labeledoid = 1;
 
5395
}
 
5396
 
 
5397
void
 
5398
print_oid_report_enable_oid(void)
 
5399
{
 
5400
    print_subtree_oid_report_oid = 1;
 
5401
}
 
5402
 
 
5403
void
 
5404
print_oid_report_enable_suffix(void)
 
5405
{
 
5406
    print_subtree_oid_report_suffix = 1;
 
5407
}
 
5408
 
 
5409
void
 
5410
print_oid_report_enable_symbolic(void)
 
5411
{
 
5412
    print_subtree_oid_report_symbolic = 1;
 
5413
}
 
5414
 
 
5415
/*
 
5416
 * helper methods for print_subtree_oid_report()
 
5417
 * each one traverses back up the node tree
 
5418
 * until there is no parent.  Then, the label combination
 
5419
 * is output, such that the parent is displayed first.
 
5420
 *
 
5421
 * Warning: these methods are all recursive.
 
5422
 */
 
5423
 
 
5424
static void
 
5425
print_parent_labeledoid(FILE * f, struct tree *tp)
 
5426
{
 
5427
    if (tp) {
 
5428
        if (tp->parent) {
 
5429
            print_parent_labeledoid(f, tp->parent);
 
5430
         /*RECURSE*/}
 
5431
        fprintf(f, ".%s(%lu)", tp->label, tp->subid);
 
5432
    }
 
5433
}
 
5434
 
 
5435
static void
 
5436
print_parent_oid(FILE * f, struct tree *tp)
 
5437
{
 
5438
    if (tp) {
 
5439
        if (tp->parent) {
 
5440
            print_parent_oid(f, tp->parent);
 
5441
         /*RECURSE*/}
 
5442
        fprintf(f, ".%lu", tp->subid);
 
5443
    }
 
5444
}
 
5445
 
 
5446
static void
 
5447
print_parent_label(FILE * f, struct tree *tp)
 
5448
{
 
5449
    if (tp) {
 
5450
        if (tp->parent) {
 
5451
            print_parent_label(f, tp->parent);
 
5452
         /*RECURSE*/}
 
5453
        fprintf(f, ".%s", tp->label);
 
5454
    }
 
5455
}
 
5456
 
 
5457
/**
 
5458
 * @internal
 
5459
 * This methods generates variations on the original print_subtree() report.
 
5460
 * Traverse the tree depth first, from least to greatest sub-identifier.
 
5461
 * Warning: this methods recurses and calls methods that recurse.
 
5462
 *
 
5463
 * @param f       File descriptor to print to.
 
5464
 * @param tree    ???
 
5465
 * @param count   ???
 
5466
 */
 
5467
 
 
5468
static void
 
5469
print_subtree_oid_report(FILE * f, struct tree *tree, int count)
 
5470
{
 
5471
    struct tree    *tp;
 
5472
 
 
5473
    count++;
 
5474
 
 
5475
    /*
 
5476
     * sanity check 
 
5477
     */
 
5478
    if (!tree) {
 
5479
        return;
 
5480
    }
 
5481
 
 
5482
    /*
 
5483
     * find the not reported peer with the lowest sub-identifier.
 
5484
     * if no more, break the loop and cleanup.
 
5485
     * set "reported" flag, and create report for this peer.
 
5486
     * recurse using the children of this peer, if any.
 
5487
     */
 
5488
    while (1) {
 
5489
        register struct tree *ntp;
 
5490
 
 
5491
        tp = 0;
 
5492
        for (ntp = tree->child_list; ntp; ntp = ntp->next_peer) {
 
5493
            if (ntp->reported)
 
5494
                continue;
 
5495
 
 
5496
            if (!tp || (tp->subid > ntp->subid))
 
5497
                tp = ntp;
 
5498
        }
 
5499
        if (!tp)
 
5500
            break;
 
5501
 
 
5502
        tp->reported = 1;
 
5503
 
 
5504
        if (print_subtree_oid_report_labeledoid) {
 
5505
            print_parent_labeledoid(f, tp);
 
5506
            fprintf(f, "\n");
 
5507
        }
 
5508
        if (print_subtree_oid_report_oid) {
 
5509
            print_parent_oid(f, tp);
 
5510
            fprintf(f, "\n");
 
5511
        }
 
5512
        if (print_subtree_oid_report_symbolic) {
 
5513
            print_parent_label(f, tp);
 
5514
            fprintf(f, "\n");
 
5515
        }
 
5516
        if (print_subtree_oid_report_suffix) {
 
5517
            int             i;
 
5518
            for (i = 0; i < count; i++)
 
5519
                fprintf(f, "  ");
 
5520
            fprintf(f, "%s(%ld) type=%d", tp->label, tp->subid, tp->type);
 
5521
            if (tp->tc_index != -1)
 
5522
                fprintf(f, " tc=%d", tp->tc_index);
 
5523
            if (tp->hint)
 
5524
                fprintf(f, " hint=%s", tp->hint);
 
5525
            if (tp->units)
 
5526
                fprintf(f, " units=%s", tp->units);
 
5527
 
 
5528
            fprintf(f, "\n");
 
5529
        }
 
5530
        print_subtree_oid_report(f, tp, count);
 
5531
     /*RECURSE*/}
 
5532
}
 
5533
#endif /* DISABLE_MIB_LOADING */
 
5534
 
 
5535
 
 
5536
/**
 
5537
 * Converts timeticks to hours, minutes, seconds string.
 
5538
 * CMU compatible does not show centiseconds.
 
5539
 *
 
5540
 * @param timeticks    The timeticks to convert.
 
5541
 * @param buf          Buffer to write to, has to be at 
 
5542
 *                     least 40 Bytes large.
 
5543
 *       
 
5544
 * @return The buffer
 
5545
 *
 
5546
 * @see uptimeString
 
5547
 */
 
5548
char           *
 
5549
uptime_string(u_long timeticks, char *buf)
 
5550
{
 
5551
    uptimeString(timeticks, buf);
 
5552
#ifdef CMU_COMPATIBLE
 
5553
    {
 
5554
    char *cp = strrchr(buf, '.');
 
5555
    if (cp)
 
5556
        *cp = '\0';
 
5557
    }
 
5558
#endif
 
5559
    return buf;
 
5560
}
 
5561
 
 
5562
/**
 
5563
 * Given a string, parses an oid out of it (if possible).
 
5564
 * It will try to parse it based on predetermined configuration if
 
5565
 * present or by every method possible otherwise.
 
5566
 * If a suffix has been registered using NETSNMP_DS_LIB_OIDSUFFIX, it
 
5567
 * will be appended to the input string before processing.
 
5568
 *
 
5569
 * @param argv    The OID to string parse
 
5570
 * @param root    An OID array where the results are stored.
 
5571
 * @param rootlen The max length of the array going in and the data
 
5572
 *                length coming out.
 
5573
 *
 
5574
 * @return        The root oid pointer if successful, or NULL otherwise.
 
5575
 */
 
5576
 
 
5577
oid            *
 
5578
snmp_parse_oid(const char *argv, oid * root, size_t * rootlen)
 
5579
{
 
5580
    size_t          savlen = *rootlen;
 
5581
    static size_t   tmpbuf_len = 0;
 
5582
    static char    *tmpbuf;
 
5583
    const char     *suffix, *prefix;
 
5584
 
 
5585
    suffix = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
 
5586
                                   NETSNMP_DS_LIB_OIDSUFFIX);
 
5587
    prefix = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
 
5588
                                   NETSNMP_DS_LIB_OIDPREFIX);
 
5589
    if ((suffix && suffix[0]) || (prefix && prefix[0])) {
 
5590
        if (!suffix)
 
5591
            suffix = "";
 
5592
        if (!prefix)
 
5593
            prefix = "";
 
5594
        if ((strlen(suffix) + strlen(prefix) + strlen(argv) + 2) > tmpbuf_len) {
 
5595
            tmpbuf_len = strlen(suffix) + strlen(argv) + strlen(prefix) + 2;
 
5596
            tmpbuf = realloc(tmpbuf, tmpbuf_len);
 
5597
        }
 
5598
        snprintf(tmpbuf, tmpbuf_len, "%s%s%s%s", prefix, argv,
 
5599
                 ((suffix[0] == '.' || suffix[0] == '\0') ? "" : "."),
 
5600
                 suffix);
 
5601
        argv = tmpbuf;
 
5602
        DEBUGMSGTL(("snmp_parse_oid","Parsing: %s\n",argv));
 
5603
    }
 
5604
 
 
5605
#ifndef DISABLE_MIB_LOADING
 
5606
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS)
 
5607
        || strchr(argv, ':')) {
 
5608
        if (get_node(argv, root, rootlen)) {
 
5609
            return root;
 
5610
        }
 
5611
    } else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REGEX_ACCESS)) {
 
5612
        clear_tree_flags(tree_head);
 
5613
        if (get_wild_node(argv, root, rootlen)) {
 
5614
            return root;
 
5615
        }
 
5616
    } else {
 
5617
#endif /* DISABLE_MIB_LOADING */
 
5618
        if (read_objid(argv, root, rootlen)) {
 
5619
            return root;
 
5620
        }
 
5621
#ifndef DISABLE_MIB_LOADING
 
5622
        *rootlen = savlen;
 
5623
        if (get_node(argv, root, rootlen)) {
 
5624
            return root;
 
5625
        }
 
5626
        *rootlen = savlen;
 
5627
        DEBUGMSGTL(("parse_oid", "wildly parsing\n"));
 
5628
        clear_tree_flags(tree_head);
 
5629
        if (get_wild_node(argv, root, rootlen)) {
 
5630
            return root;
 
5631
        }
 
5632
    }
 
5633
#endif /* DISABLE_MIB_LOADING */
 
5634
    return NULL;
 
5635
}
 
5636
 
 
5637
#ifndef DISABLE_MIB_LOADING
 
5638
/*
 
5639
 * Use DISPLAY-HINT to parse a value into an octet string.
 
5640
 *
 
5641
 * note that "1d1d", "11" could have come from an octet string that
 
5642
 * looked like { 1, 1 } or an octet string that looked like { 11 }
 
5643
 * because of this, it's doubtful that anyone would use such a display
 
5644
 * string. Therefore, the parser ignores this case.
 
5645
 */
 
5646
 
 
5647
struct parse_hints {
 
5648
    int length;
 
5649
    int repeat;
 
5650
    int format;
 
5651
    int separator;
 
5652
    int terminator;
 
5653
    unsigned char *result;
 
5654
    int result_max;
 
5655
    int result_len;
 
5656
};
 
5657
 
 
5658
static void parse_hints_reset(struct parse_hints *ph)
 
5659
{
 
5660
    ph->length = 0;
 
5661
    ph->repeat = 0;
 
5662
    ph->format = 0;
 
5663
    ph->separator = 0;
 
5664
    ph->terminator = 0;
 
5665
}
 
5666
 
 
5667
static void parse_hints_ctor(struct parse_hints *ph)
 
5668
{
 
5669
    parse_hints_reset(ph);
 
5670
    ph->result = NULL;
 
5671
    ph->result_max = 0;
 
5672
    ph->result_len = 0;
 
5673
}
 
5674
 
 
5675
static int parse_hints_add_result_octet(struct parse_hints *ph, unsigned char octet)
 
5676
{
 
5677
    if (!(ph->result_len < ph->result_max)) {
 
5678
        ph->result_max = ph->result_len + 32;
 
5679
        if (!ph->result) {
 
5680
            ph->result = (unsigned char *)malloc(ph->result_max);
 
5681
        } else {
 
5682
            ph->result = (unsigned char *)realloc(ph->result, ph->result_max);
 
5683
        }
 
5684
    }
 
5685
    
 
5686
    if (!ph->result) {
 
5687
        return 0;               /* failed */
 
5688
    }
 
5689
 
 
5690
    ph->result[ph->result_len++] = octet;
 
5691
    return 1;                   /* success */
 
5692
}
 
5693
 
 
5694
static int parse_hints_parse(struct parse_hints *ph, const char **v_in_out)
 
5695
{
 
5696
    const char *v = *v_in_out;
 
5697
    char *nv;
 
5698
    int base;
 
5699
    int repeats = 0;
 
5700
    int repeat_fixup = ph->result_len;
 
5701
    
 
5702
    if (ph->repeat) {
 
5703
        if (!parse_hints_add_result_octet(ph, 0)) {
 
5704
            return 0;
 
5705
        }
 
5706
    }
 
5707
    do {
 
5708
        base = 0;
 
5709
        switch (ph->format) {
 
5710
        case 'x': base += 6;    /* fall through */
 
5711
        case 'd': base += 2;    /* fall through */
 
5712
        case 'o': base += 8;    /* fall through */
 
5713
            {
 
5714
                int i;
 
5715
                unsigned long number = strtol(v, &nv, base);
 
5716
                if (nv == v) return 0;
 
5717
                v = nv;
 
5718
                for (i = 0; i < ph->length; i++) {
 
5719
                    int shift = 8 * (ph->length - 1 - i);
 
5720
                    if (!parse_hints_add_result_octet(ph, (u_char)(number >> shift) )) {
 
5721
                        return 0; /* failed */
 
5722
                    }
 
5723
                }
 
5724
            }
 
5725
            break;
 
5726
 
 
5727
        case 'a':
 
5728
            {
 
5729
                int i;
 
5730
                    
 
5731
                for (i = 0; i < ph->length && *v; i++) {
 
5732
                    if (!parse_hints_add_result_octet(ph, *v++)) {
 
5733
                        return 0;       /* failed */
 
5734
                    }
 
5735
                }
 
5736
            }
 
5737
            break;
 
5738
        }
 
5739
 
 
5740
        repeats++;
 
5741
 
 
5742
        if (ph->separator && *v) {
 
5743
            if (*v == ph->separator) {
 
5744
                v++;
 
5745
            } else {
 
5746
                return 0;               /* failed */
 
5747
            }
 
5748
        }
 
5749
 
 
5750
        if (ph->terminator) {
 
5751
            if (*v == ph->terminator) {
 
5752
                v++;
 
5753
                break;
 
5754
            }
 
5755
        }
 
5756
    } while (ph->repeat && *v);
 
5757
    if (ph->repeat) {
 
5758
        ph->result[repeat_fixup] = repeats;
 
5759
    }
 
5760
 
 
5761
    *v_in_out = v;
 
5762
    return 1;
 
5763
}
 
5764
 
 
5765
static void parse_hints_length_add_digit(struct parse_hints *ph, int digit)
 
5766
{
 
5767
    ph->length *= 10;
 
5768
    ph->length += digit - '0';
 
5769
}
 
5770
 
 
5771
const char *parse_octet_hint(const char *hint, const char *value, unsigned char **new_val, int *new_val_len)
 
5772
{
 
5773
    const char *h = hint;
 
5774
    const char *v = value;
 
5775
    struct parse_hints ph;
 
5776
    int retval = 1;
 
5777
    /* See RFC 1443 */
 
5778
    enum {
 
5779
        HINT_1_2,
 
5780
        HINT_2_3,
 
5781
        HINT_1_2_4,
 
5782
        HINT_1_2_5,
 
5783
    } state = HINT_1_2;
 
5784
 
 
5785
    parse_hints_ctor(&ph);
 
5786
    while (*h && *v && retval) {
 
5787
        switch (state) {
 
5788
        case HINT_1_2:
 
5789
            if ('*' == *h) {
 
5790
                ph.repeat = 1;
 
5791
                state = HINT_2_3;
 
5792
            } else if (isdigit(*h)) {
 
5793
                parse_hints_length_add_digit(&ph, *h);
 
5794
                state = HINT_2_3;
 
5795
            } else {
 
5796
                return v;       /* failed */
 
5797
            }
 
5798
            break;
 
5799
 
 
5800
        case HINT_2_3:
 
5801
            if (isdigit(*h)) {
 
5802
                parse_hints_length_add_digit(&ph, *h);
 
5803
                /* state = HINT_2_3 */
 
5804
            } else if ('x' == *h || 'd' == *h || 'o' == *h || 'a' == *h) {
 
5805
                ph.format = *h;
 
5806
                state = HINT_1_2_4;
 
5807
            } else {
 
5808
                return v;       /* failed */
 
5809
            }
 
5810
            break;
 
5811
 
 
5812
        case HINT_1_2_4:
 
5813
            if ('*' == *h) {
 
5814
                retval = parse_hints_parse(&ph, &v);
 
5815
                parse_hints_reset(&ph);
 
5816
                
 
5817
                ph.repeat = 1;
 
5818
                state = HINT_2_3;
 
5819
            } else if (isdigit(*h)) {
 
5820
                retval = parse_hints_parse(&ph, &v);
 
5821
                parse_hints_reset(&ph);
 
5822
                
 
5823
                parse_hints_length_add_digit(&ph, *h);
 
5824
                state = HINT_2_3;
 
5825
            } else {
 
5826
                ph.separator = *h;
 
5827
                state = HINT_1_2_5;
 
5828
            }
 
5829
            break;
 
5830
 
 
5831
        case HINT_1_2_5:
 
5832
            if ('*' == *h) {
 
5833
                retval = parse_hints_parse(&ph, &v);
 
5834
                parse_hints_reset(&ph);
 
5835
                
 
5836
                ph.repeat = 1;
 
5837
                state = HINT_2_3;
 
5838
            } else if (isdigit(*h)) {
 
5839
                retval = parse_hints_parse(&ph, &v);
 
5840
                parse_hints_reset(&ph);
 
5841
                
 
5842
                parse_hints_length_add_digit(&ph, *h);
 
5843
                state = HINT_2_3;
 
5844
            } else {
 
5845
                ph.terminator = *h;
 
5846
 
 
5847
                retval = parse_hints_parse(&ph, &v);
 
5848
                parse_hints_reset(&ph);
 
5849
 
 
5850
                state = HINT_1_2;
 
5851
            }
 
5852
            break;
 
5853
        }
 
5854
        h++;
 
5855
    }
 
5856
    while (*v && retval) {
 
5857
        retval = parse_hints_parse(&ph, &v);
 
5858
    }
 
5859
    if (retval) {
 
5860
        *new_val = ph.result;
 
5861
        *new_val_len = ph.result_len;
 
5862
    } else {
 
5863
        if (ph.result) {
 
5864
            SNMP_FREE(ph.result);
 
5865
        }
 
5866
        *new_val = NULL;
 
5867
        *new_val_len = 0;
 
5868
    }
 
5869
    return retval ? NULL : v;
 
5870
}
 
5871
#endif /* DISABLE_MIB_LOADING */
 
5872
 
 
5873
#ifdef test_display_hint
 
5874
 
 
5875
int main(int argc, const char **argv)
 
5876
{
 
5877
    const char *hint;
 
5878
    const char *value;
 
5879
    unsigned char *new_val;
 
5880
    int new_val_len;
 
5881
    char *r;
 
5882
    
 
5883
    if (argc < 3) {
 
5884
        fprintf(stderr, "usage: dh <hint> <value>\n");
 
5885
        exit(2);
 
5886
    }
 
5887
    hint = argv[1];
 
5888
    value = argv[2];
 
5889
    r = parse_octet_hint(hint, value, &new_val, &new_val_len);
 
5890
    printf("{\"%s\", \"%s\"}: \n\t", hint, value);
 
5891
    if (r) {
 
5892
        *r = 0;
 
5893
        printf("returned failed\n");
 
5894
        printf("value syntax error at: %s\n", value);
 
5895
    }
 
5896
    else {
 
5897
        int i;
 
5898
        printf("returned success\n");
 
5899
        for (i = 0; i < new_val_len; i++) {
 
5900
            int c = new_val[i] & 0xFF;
 
5901
            printf("%02X(%c) ", c, isprint(c) ? c : ' ');
 
5902
        }
 
5903
        SNMP_FREE(new_val);
 
5904
    }
 
5905
    printf("\n");
 
5906
    exit(0);
 
5907
}
 
5908
 
 
5909
#endif /* test_display_hint */
 
5910
 
 
5911
u_char
 
5912
mib_to_asn_type(int mib_type)
 
5913
{
 
5914
    switch (mib_type) {
 
5915
    case TYPE_OBJID:
 
5916
        return ASN_OBJECT_ID;
 
5917
 
 
5918
    case TYPE_OCTETSTR:
 
5919
        return ASN_OCTET_STR;
 
5920
 
 
5921
    case TYPE_NETADDR:
 
5922
    case TYPE_IPADDR:
 
5923
        return ASN_IPADDRESS;
 
5924
 
 
5925
    case TYPE_INTEGER32:
 
5926
    case TYPE_INTEGER:
 
5927
        return ASN_INTEGER;
 
5928
 
 
5929
    case TYPE_COUNTER:
 
5930
        return ASN_COUNTER;
 
5931
 
 
5932
    case TYPE_GAUGE:
 
5933
        return ASN_GAUGE;
 
5934
 
 
5935
    case TYPE_TIMETICKS:
 
5936
        return ASN_TIMETICKS;
 
5937
 
 
5938
    case TYPE_OPAQUE:
 
5939
        return ASN_OPAQUE;
 
5940
 
 
5941
    case TYPE_NULL:
 
5942
        return ASN_NULL;
 
5943
 
 
5944
    case TYPE_COUNTER64:
 
5945
        return ASN_COUNTER64;
 
5946
 
 
5947
    case TYPE_BITSTRING:
 
5948
        return ASN_BIT_STR;
 
5949
 
 
5950
    case TYPE_UINTEGER:
 
5951
    case TYPE_UNSIGNED32:
 
5952
        return ASN_UINTEGER;
 
5953
 
 
5954
    case TYPE_NSAPADDRESS:
 
5955
        return ASN_NSAP;
 
5956
 
 
5957
    }
 
5958
    return -1;
 
5959
}
 
5960
 
 
5961
/**
 
5962
 * Converts a string to its OID form.
 
5963
 * in example  "hello" = 5 . 'h' . 'e' . 'l' . 'l' . 'o'
 
5964
 *
 
5965
 * @param S   The string.
 
5966
 * @param O   The oid.
 
5967
 * @param L   The length of the oid.
 
5968
 *
 
5969
 * @return 0 on Sucess, 1 on failure.
 
5970
 */
 
5971
int
 
5972
netsnmp_str2oid(const char *S, oid * O, int L)
 
5973
{
 
5974
    const char     *c = S;
 
5975
    oid            *o = &O[1];
 
5976
 
 
5977
    --L;                        /* leave room for length prefix */
 
5978
 
 
5979
    for (; *c && L; --L, ++o, ++c)
 
5980
        *o = *c;
 
5981
 
 
5982
    /*
 
5983
     * make sure we got to the end of the string 
 
5984
     */
 
5985
    if (*c != 0)
 
5986
        return 1;
 
5987
 
 
5988
    /*
 
5989
     * set the length of the oid 
 
5990
     */
 
5991
    *O = c - S;
 
5992
 
 
5993
    return 0;
 
5994
}
 
5995
 
 
5996
/**
 
5997
 * Converts an OID to its character form.
 
5998
 * in example  5 . 1 . 2 . 3 . 4 . 5 = 12345
 
5999
 *
 
6000
 * @param C   The character buffer.
 
6001
 * @param L   The length of the buffer.
 
6002
 * @param O   The oid.
 
6003
 *
 
6004
 * @return 0 on Sucess, 1 on failure.
 
6005
 */
 
6006
int
 
6007
netsnmp_oid2chars(char *C, int L, const oid * O)
 
6008
{
 
6009
    char           *c = C;
 
6010
    const oid      *o = &O[1];
 
6011
 
 
6012
    if (L < (int)*O)
 
6013
        return 1;
 
6014
 
 
6015
    L = *O; /** length */
 
6016
    for (; L; --L, ++o, ++c) {
 
6017
        if (*o > 0xFF)
 
6018
            return 1;
 
6019
        *c = (char)*o;
 
6020
    }
 
6021
    return 0;
 
6022
}
 
6023
 
 
6024
/**
 
6025
 * Converts an OID to its string form.
 
6026
 * in example  5 . 'h' . 'e' . 'l' . 'l' . 'o' = "hello\0" (null terminated)
 
6027
 *
 
6028
 * @param S   The character string buffer.
 
6029
 * @param L   The length of the string buffer.
 
6030
 * @param O   The oid.
 
6031
 *
 
6032
 * @return 0 on Sucess, 1 on failure.
 
6033
 */
 
6034
int
 
6035
netsnmp_oid2str(char *S, int L, oid * O)
 
6036
{
 
6037
    int            rc;
 
6038
 
 
6039
    if (L <= (int)*O)
 
6040
        return 1;
 
6041
 
 
6042
    rc = netsnmp_oid2chars(S, L, O);
 
6043
    if (rc)
 
6044
        return 1;
 
6045
 
 
6046
    S[ *O ] = 0;
 
6047
 
 
6048
    return 0;
 
6049
}
 
6050
 
 
6051
int
 
6052
snprint_by_type(char *buf, size_t buf_len,
 
6053
                netsnmp_variable_list * var,
 
6054
                const struct enum_list *enums,
 
6055
                const char *hint, const char *units)
 
6056
{
 
6057
    size_t          out_len = 0;
 
6058
    if (sprint_realloc_by_type((u_char **) & buf, &buf_len, &out_len, 0,
 
6059
                               var, enums, hint, units))
 
6060
        return (int) out_len;
 
6061
    else
 
6062
        return -1;
 
6063
}
 
6064
 
 
6065
int
 
6066
snprint_hexstring(char *buf, size_t buf_len, const u_char * cp, size_t len)
 
6067
{
 
6068
    size_t          out_len = 0;
 
6069
    if (sprint_realloc_hexstring((u_char **) & buf, &buf_len, &out_len, 0,
 
6070
                                 cp, len))
 
6071
        return (int) out_len;
 
6072
    else
 
6073
        return -1;
 
6074
}
 
6075
 
 
6076
int
 
6077
snprint_asciistring(char *buf, size_t buf_len,
 
6078
                    const u_char * cp, size_t len)
 
6079
{
 
6080
    size_t          out_len = 0;
 
6081
    if (sprint_realloc_asciistring
 
6082
        ((u_char **) & buf, &buf_len, &out_len, 0, cp, len))
 
6083
        return (int) out_len;
 
6084
    else
 
6085
        return -1;
 
6086
}
 
6087
 
 
6088
int
 
6089
snprint_octet_string(char *buf, size_t buf_len,
 
6090
                     const netsnmp_variable_list * var, const struct enum_list *enums,
 
6091
                     const char *hint, const char *units)
 
6092
{
 
6093
    size_t          out_len = 0;
 
6094
    if (sprint_realloc_octet_string
 
6095
        ((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint,
 
6096
         units))
 
6097
        return (int) out_len;
 
6098
    else
 
6099
        return -1;
 
6100
}
 
6101
 
 
6102
int
 
6103
snprint_opaque(char *buf, size_t buf_len,
 
6104
               const netsnmp_variable_list * var, const struct enum_list *enums,
 
6105
               const char *hint, const char *units)
 
6106
{
 
6107
    size_t          out_len = 0;
 
6108
    if (sprint_realloc_opaque((u_char **) & buf, &buf_len, &out_len, 0,
 
6109
                              var, enums, hint, units))
 
6110
        return (int) out_len;
 
6111
    else
 
6112
        return -1;
 
6113
}
 
6114
 
 
6115
int
 
6116
snprint_object_identifier(char *buf, size_t buf_len,
 
6117
                          const netsnmp_variable_list * var,
 
6118
                          const struct enum_list *enums, const char *hint,
 
6119
                          const char *units)
 
6120
{
 
6121
    size_t          out_len = 0;
 
6122
    if (sprint_realloc_object_identifier
 
6123
        ((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint,
 
6124
         units))
 
6125
        return (int) out_len;
 
6126
    else
 
6127
        return -1;
 
6128
}
 
6129
 
 
6130
int
 
6131
snprint_timeticks(char *buf, size_t buf_len,
 
6132
                  const netsnmp_variable_list * var, const struct enum_list *enums,
 
6133
                  const char *hint, const char *units)
 
6134
{
 
6135
    size_t          out_len = 0;
 
6136
    if (sprint_realloc_timeticks((u_char **) & buf, &buf_len, &out_len, 0,
 
6137
                                 var, enums, hint, units))
 
6138
        return (int) out_len;
 
6139
    else
 
6140
        return -1;
 
6141
}
 
6142
 
 
6143
int
 
6144
snprint_hinted_integer(char *buf, size_t buf_len,
 
6145
                       long val, const char *hint, const char *units)
 
6146
{
 
6147
    size_t          out_len = 0;
 
6148
    if (sprint_realloc_hinted_integer
 
6149
        ((u_char **) & buf, &buf_len, &out_len, 0, val, 'd', hint, units))
 
6150
        return (int) out_len;
 
6151
    else
 
6152
        return -1;
 
6153
}
 
6154
 
 
6155
int
 
6156
snprint_integer(char *buf, size_t buf_len,
 
6157
                const netsnmp_variable_list * var, const struct enum_list *enums,
 
6158
                const char *hint, const char *units)
 
6159
{
 
6160
    size_t          out_len = 0;
 
6161
    if (sprint_realloc_integer((u_char **) & buf, &buf_len, &out_len, 0,
 
6162
                               var, enums, hint, units))
 
6163
        return (int) out_len;
 
6164
    else
 
6165
        return -1;
 
6166
}
 
6167
 
 
6168
int
 
6169
snprint_uinteger(char *buf, size_t buf_len,
 
6170
                 const netsnmp_variable_list * var, const struct enum_list *enums,
 
6171
                 const char *hint, const char *units)
 
6172
{
 
6173
    size_t          out_len = 0;
 
6174
    if (sprint_realloc_uinteger((u_char **) & buf, &buf_len, &out_len, 0,
 
6175
                                var, enums, hint, units))
 
6176
        return (int) out_len;
 
6177
    else
 
6178
        return -1;
 
6179
}
 
6180
 
 
6181
int
 
6182
snprint_gauge(char *buf, size_t buf_len,
 
6183
              const netsnmp_variable_list * var, const struct enum_list *enums,
 
6184
              const char *hint, const char *units)
 
6185
{
 
6186
    size_t          out_len = 0;
 
6187
    if (sprint_realloc_gauge((u_char **) & buf, &buf_len, &out_len, 0,
 
6188
                             var, enums, hint, units))
 
6189
        return (int) out_len;
 
6190
    else
 
6191
        return -1;
 
6192
}
 
6193
 
 
6194
int
 
6195
snprint_counter(char *buf, size_t buf_len,
 
6196
                const netsnmp_variable_list * var, const struct enum_list *enums,
 
6197
                const char *hint, const char *units)
 
6198
{
 
6199
    size_t          out_len = 0;
 
6200
    if (sprint_realloc_counter((u_char **) & buf, &buf_len, &out_len, 0,
 
6201
                               var, enums, hint, units))
 
6202
        return (int) out_len;
 
6203
    else
 
6204
        return -1;
 
6205
}
 
6206
 
 
6207
int
 
6208
snprint_networkaddress(char *buf, size_t buf_len,
 
6209
                       const netsnmp_variable_list * var,
 
6210
                       const struct enum_list *enums, const char *hint,
 
6211
                       const char *units)
 
6212
{
 
6213
    size_t          out_len = 0;
 
6214
    if (sprint_realloc_networkaddress
 
6215
        ((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint,
 
6216
         units))
 
6217
        return (int) out_len;
 
6218
    else
 
6219
        return -1;
 
6220
}
 
6221
 
 
6222
int
 
6223
snprint_ipaddress(char *buf, size_t buf_len,
 
6224
                  const netsnmp_variable_list * var, const struct enum_list *enums,
 
6225
                  const char *hint, const char *units)
 
6226
{
 
6227
    size_t          out_len = 0;
 
6228
    if (sprint_realloc_ipaddress((u_char **) & buf, &buf_len, &out_len, 0,
 
6229
                                 var, enums, hint, units))
 
6230
        return (int) out_len;
 
6231
    else
 
6232
        return -1;
 
6233
}
 
6234
 
 
6235
int
 
6236
snprint_null(char *buf, size_t buf_len,
 
6237
             const netsnmp_variable_list * var, const struct enum_list *enums,
 
6238
             const char *hint, const char *units)
 
6239
{
 
6240
    size_t          out_len = 0;
 
6241
    if (sprint_realloc_null((u_char **) & buf, &buf_len, &out_len, 0,
 
6242
                            var, enums, hint, units))
 
6243
        return (int) out_len;
 
6244
    else
 
6245
        return -1;
 
6246
}
 
6247
 
 
6248
int
 
6249
snprint_bitstring(char *buf, size_t buf_len,
 
6250
                  const netsnmp_variable_list * var, const struct enum_list *enums,
 
6251
                  const char *hint, const char *units)
 
6252
{
 
6253
    size_t          out_len = 0;
 
6254
    if (sprint_realloc_bitstring((u_char **) & buf, &buf_len, &out_len, 0,
 
6255
                                 var, enums, hint, units))
 
6256
        return (int) out_len;
 
6257
    else
 
6258
        return -1;
 
6259
}
 
6260
 
 
6261
int
 
6262
snprint_nsapaddress(char *buf, size_t buf_len,
 
6263
                    const netsnmp_variable_list * var, const struct enum_list *enums,
 
6264
                    const char *hint, const char *units)
 
6265
{
 
6266
    size_t          out_len = 0;
 
6267
    if (sprint_realloc_nsapaddress
 
6268
        ((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint,
 
6269
         units))
 
6270
        return (int) out_len;
 
6271
    else
 
6272
        return -1;
 
6273
}
 
6274
 
 
6275
int
 
6276
snprint_counter64(char *buf, size_t buf_len,
 
6277
                  const netsnmp_variable_list * var, const struct enum_list *enums,
 
6278
                  const char *hint, const char *units)
 
6279
{
 
6280
    size_t          out_len = 0;
 
6281
    if (sprint_realloc_counter64((u_char **) & buf, &buf_len, &out_len, 0,
 
6282
                                 var, enums, hint, units))
 
6283
        return (int) out_len;
 
6284
    else
 
6285
        return -1;
 
6286
}
 
6287
 
 
6288
int
 
6289
snprint_badtype(char *buf, size_t buf_len,
 
6290
                const netsnmp_variable_list * var, const struct enum_list *enums,
 
6291
                const char *hint, const char *units)
 
6292
{
 
6293
    size_t          out_len = 0;
 
6294
    if (sprint_realloc_badtype((u_char **) & buf, &buf_len, &out_len, 0,
 
6295
                               var, enums, hint, units))
 
6296
        return (int) out_len;
 
6297
    else
 
6298
        return -1;
 
6299
}
 
6300
 
 
6301
#ifdef OPAQUE_SPECIAL_TYPES
 
6302
int
 
6303
snprint_float(char *buf, size_t buf_len,
 
6304
              const netsnmp_variable_list * var, const struct enum_list *enums,
 
6305
              const char *hint, const char *units)
 
6306
{
 
6307
    size_t          out_len = 0;
 
6308
    if (sprint_realloc_float((u_char **) & buf, &buf_len, &out_len, 0,
 
6309
                             var, enums, hint, units))
 
6310
        return (int) out_len;
 
6311
    else
 
6312
        return -1;
 
6313
}
 
6314
 
 
6315
int
 
6316
snprint_double(char *buf, size_t buf_len,
 
6317
               const netsnmp_variable_list * var, const struct enum_list *enums,
 
6318
               const char *hint, const char *units)
 
6319
{
 
6320
    size_t          out_len = 0;
 
6321
    if (sprint_realloc_double((u_char **) & buf, &buf_len, &out_len, 0,
 
6322
                              var, enums, hint, units))
 
6323
        return (int) out_len;
 
6324
    else
 
6325
        return -1;
 
6326
}
 
6327
#endif