Coverage Report

Created: 2026-10-17 06:54

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