Coverage Report

Created: 2023-06-07 06:42

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