Coverage Report

Created: 2026-04-12 06:59

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