Coverage Report

Created: 2026-07-16 06:27

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