blob: e7908783112e73fbae3bdc6287625b42ea369773 [file] [log] [blame]
/*
* mib.c
*
* $Id$
*
* Update: 1998-07-17 <jhy@gsu.edu>
* Added print_oid_report* functions.
*
*/
/* Portions of this file are subject to the following copyrights. See
* the Net-SNMP's COPYING file for more details and other copyrights
* that may apply:
*/
/**********************************************************************
Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of CMU not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
/*
* Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms specified in the COPYING file
* distributed with the Net-SNMP package.
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-features.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#if HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_DMALLOC_H
#include <dmalloc.h>
#endif
#include <net-snmp/types.h>
#include <net-snmp/output_api.h>
#include <net-snmp/config_api.h>
#include <net-snmp/utilities.h>
#include <net-snmp/library/asn1.h>
#include <net-snmp/library/snmp_api.h>
#include <net-snmp/library/mib.h>
#include <net-snmp/library/parse.h>
#include <net-snmp/library/int64.h>
#include <net-snmp/library/snmp_client.h>
netsnmp_feature_child_of(mib_api, libnetsnmp)
netsnmp_feature_child_of(mib_strings_all, mib_api)
netsnmp_feature_child_of(mib_snprint, mib_strings_all)
netsnmp_feature_child_of(mib_snprint_description, mib_strings_all)
netsnmp_feature_child_of(mib_snprint_variable, mib_strings_all)
netsnmp_feature_child_of(mib_string_conversions, mib_strings_all)
netsnmp_feature_child_of(print_mib, mib_strings_all)
netsnmp_feature_child_of(snprint_objid, mib_strings_all)
netsnmp_feature_child_of(snprint_value, mib_strings_all)
netsnmp_feature_child_of(mib_to_asn_type, mib_api)
/** @defgroup mib_utilities mib parsing and datatype manipulation routines.
* @ingroup library
*
* @{
*/
static char *uptimeString(u_long, char *, size_t);
static struct tree *_get_realloc_symbol(const oid * objid, size_t objidlen,
struct tree *subtree,
u_char ** buf, size_t * buf_len,
size_t * out_len,
int allow_realloc,
int *buf_overflow,
struct index_list *in_dices,
size_t * end_of_known);
static int print_tree_node(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
struct tree *tp, int width);
static void handle_mibdirs_conf(const char *token, char *line);
static void handle_mibs_conf(const char *token, char *line);
static void handle_mibfile_conf(const char *token, char *line);
static void _oid_finish_printing(const oid * objid, size_t objidlen,
u_char ** buf, size_t * buf_len,
size_t * out_len,
int allow_realloc, int *buf_overflow);
/*
* helper functions for get_module_node
*/
static int node_to_oid(struct tree *, oid *, size_t *);
#ifndef NETSNMP_DISABLE_MIB_LOADING
static int _add_strings_to_oid(struct tree *, char *,
oid *, size_t *, size_t);
#else
static int _add_strings_to_oid(void *, char *,
oid *, size_t *, size_t);
#endif /* NETSNMP_DISABLE_MIB_LOADING */
#ifndef NETSNMP_DISABLE_MIB_LOADING
NETSNMP_IMPORT struct tree *tree_head;
static struct tree *tree_top;
NETSNMP_IMPORT struct tree *Mib;
struct tree *Mib; /* Backwards compatibility */
#endif /* NETSNMP_DISABLE_MIB_LOADING */
oid RFC1213_MIB[] = { 1, 3, 6, 1, 2, 1 };
static char Standard_Prefix[] = ".1.3.6.1.2.1";
/*
* Set default here as some uses of read_objid require valid pointer.
*/
static char *Prefix = &Standard_Prefix[0];
typedef struct _PrefixList {
const char *str;
int len;
} *PrefixListPtr, PrefixList;
/*
* Here are the prefix strings.
* Note that the first one finds the value of Prefix or Standard_Prefix.
* Any of these MAY start with period; all will NOT end with period.
* Period is added where needed. See use of Prefix in this module.
*/
PrefixList mib_prefixes[] = {
{&Standard_Prefix[0]}, /* placeholder for Prefix data */
{".iso.org.dod.internet.mgmt.mib-2"},
{".iso.org.dod.internet.experimental"},
{".iso.org.dod.internet.private"},
{".iso.org.dod.internet.snmpParties"},
{".iso.org.dod.internet.snmpSecrets"},
{NULL, 0} /* end of list */
};
enum inet_address_type {
IPV4 = 1,
IPV6 = 2,
IPV4Z = 3,
IPV6Z = 4,
DNS = 16
};
/**
* @internal
* Converts timeticks to hours, minutes, seconds string.
*
* @param timeticks The timeticks to convert.
* @param buf Buffer to write to, has to be at
* least 40 Bytes large.
*
* @return The buffer.
*/
static char *
uptimeString(u_long timeticks, char *buf, size_t buflen)
{
int centisecs, seconds, minutes, hours, days;
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS)) {
snprintf(buf, buflen, "%lu", timeticks);
return buf;
}
centisecs = timeticks % 100;
timeticks /= 100;
days = timeticks / (60 * 60 * 24);
timeticks %= (60 * 60 * 24);
hours = timeticks / (60 * 60);
timeticks %= (60 * 60);
minutes = timeticks / 60;
seconds = timeticks % 60;
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT))
snprintf(buf, buflen, "%d:%d:%02d:%02d.%02d",
days, hours, minutes, seconds, centisecs);
else {
if (days == 0) {
snprintf(buf, buflen, "%d:%02d:%02d.%02d",
hours, minutes, seconds, centisecs);
} else if (days == 1) {
snprintf(buf, buflen, "%d day, %d:%02d:%02d.%02d",
days, hours, minutes, seconds, centisecs);
} else {
snprintf(buf, buflen, "%d days, %d:%02d:%02d.%02d",
days, hours, minutes, seconds, centisecs);
}
}
return buf;
}
/**
* @internal
* Prints the character pointed to if in human-readable ASCII range,
* otherwise prints a dot.
*
* @param buf Buffer to print the character to.
* @param ch Character to print.
*/
static void
sprint_char(char *buf, const u_char ch)
{
if (isprint(ch) || isspace(ch)) {
sprintf(buf, "%c", (int) ch);
} else {
sprintf(buf, ".");
}
}
/**
* Prints a hexadecimal string into a buffer.
*
* The characters pointed by *cp are encoded as hexadecimal string.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf address of the buffer to print to.
* @param buf_len address to an integer containing the size of buf.
* @param out_len incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param cp the array of characters to encode.
* @param line_len the array length of cp.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
_sprint_hexstring_line(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc, const u_char * cp, size_t line_len)
{
const u_char *tp;
const u_char *cp2 = cp;
size_t lenleft = line_len;
/*
* Make sure there's enough room for the hex output....
*/
while ((*out_len + line_len*3+1) >= *buf_len) {
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
}
/*
* .... and display the hex values themselves....
*/
for (; lenleft >= 8; lenleft-=8) {
sprintf((char *) (*buf + *out_len),
"%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1],
cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
*out_len += strlen((char *) (*buf + *out_len));
cp += 8;
}
for (; lenleft > 0; lenleft--) {
sprintf((char *) (*buf + *out_len), "%02X ", *cp++);
*out_len += strlen((char *) (*buf + *out_len));
}
/*
* .... plus (optionally) do the same for the ASCII equivalent.
*/
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT)) {
while ((*out_len + line_len+5) >= *buf_len) {
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
}
sprintf((char *) (*buf + *out_len), " [");
*out_len += strlen((char *) (*buf + *out_len));
for (tp = cp2; tp < cp; tp++) {
sprint_char((char *) (*buf + *out_len), *tp);
(*out_len)++;
}
sprintf((char *) (*buf + *out_len), "]");
*out_len += strlen((char *) (*buf + *out_len));
}
return 1;
}
int
sprint_realloc_hexstring(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc, const u_char * cp, size_t len)
{
int line_len = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_HEX_OUTPUT_LENGTH);
if (!line_len)
line_len=len;
for (; (int)len > line_len; len -= line_len) {
if(!_sprint_hexstring_line(buf, buf_len, out_len, allow_realloc, cp, line_len))
return 0;
*(*buf + (*out_len)++) = '\n';
*(*buf + *out_len) = 0;
cp += line_len;
}
if(!_sprint_hexstring_line(buf, buf_len, out_len, allow_realloc, cp, len))
return 0;
*(*buf + *out_len) = 0;
return 1;
}
/**
* Prints an ascii string into a buffer.
*
* The characters pointed by *cp are encoded as an ascii string.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf address of the buffer to print to.
* @param buf_len address to an integer containing the size of buf.
* @param out_len incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param cp the array of characters to encode.
* @param len the array length of cp.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_asciistring(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
const u_char * cp, size_t len)
{
int i;
for (i = 0; i < (int) len; i++) {
if (isprint(*cp) || isspace(*cp)) {
if (*cp == '\\' || *cp == '"') {
if ((*out_len >= *buf_len) &&
!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
*(*buf + (*out_len)++) = '\\';
}
if ((*out_len >= *buf_len) &&
!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
*(*buf + (*out_len)++) = *cp++;
} else {
if ((*out_len >= *buf_len) &&
!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
*(*buf + (*out_len)++) = '.';
cp++;
}
}
if ((*out_len >= *buf_len) &&
!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
*(*buf + *out_len) = '\0';
return 1;
}
/**
* Prints an octet string into a buffer.
*
* The variable var is encoded as octet string.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_octet_string(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums, const char *hint,
const char *units)
{
size_t saved_out_len = *out_len;
const char *saved_hint = hint;
int hex = 0, x = 0;
u_char *cp;
int output_format, cnt;
if (var->type != ASN_OCTET_STR) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
const char str[] = "Wrong Type (should be OCTET STRING): ";
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (hint) {
int repeat, width = 1;
long value;
char code = 'd', separ = 0, term = 0, ch, intbuf[32];
#define HEX2DIGIT_NEED_INIT 3
char hex2digit = HEX2DIGIT_NEED_INIT;
u_char *ecp;
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "STRING: ")) {
return 0;
}
}
cp = var->val.string;
ecp = cp + var->val_len;
while (cp < ecp) {
repeat = 1;
if (*hint) {
if (*hint == '*') {
repeat = *cp++;
hint++;
}
width = 0;
while ('0' <= *hint && *hint <= '9')
width = (width * 10) + (*hint++ - '0');
code = *hint++;
if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9')
&& (width != 0
|| (ch != 'x' && ch != 'd' && ch != 'o')))
separ = *hint++;
else
separ = 0;
if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9')
&& (width != 0
|| (ch != 'x' && ch != 'd' && ch != 'o')))
term = *hint++;
else
term = 0;
if (width == 0) /* Handle malformed hint strings */
width = 1;
}
while (repeat && cp < ecp) {
value = 0;
if (code != 'a' && code != 't') {
for (x = 0; x < width; x++) {
value = value * 256 + *cp++;
}
}
switch (code) {
case 'x':
if (HEX2DIGIT_NEED_INIT == hex2digit)
hex2digit = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_2DIGIT_HEX_OUTPUT);
/*
* if value is < 16, it will be a single hex digit. If the
* width is 1 (we are outputting a byte at a time), pat it
* to 2 digits if NETSNMP_DS_LIB_2DIGIT_HEX_OUTPUT is set
* or all of the following are true:
* - we do not have a separation character
* - there is no hint left (or there never was a hint)
*
* e.g. for the data 0xAA01BB, would anyone really ever
* want the string "AA1BB"??
*/
if (((value < 16) && (1 == width)) &&
(hex2digit || ((0 == separ) && (0 == *hint)))) {
sprintf(intbuf, "0%lx", value);
} else {
sprintf(intbuf, "%lx", value);
}
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, intbuf)) {
return 0;
}
break;
case 'd':
sprintf(intbuf, "%ld", value);
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, intbuf)) {
return 0;
}
break;
case 'o':
sprintf(intbuf, "%lo", value);
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, intbuf)) {
return 0;
}
break;
case 't': /* new in rfc 3411 */
case 'a':
cnt = SNMP_MIN(width, ecp - cp);
if (!sprint_realloc_asciistring(buf, buf_len, out_len,
allow_realloc, cp, cnt))
return 0;
cp += cnt;
break;
default:
*out_len = saved_out_len;
if (snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
"(Bad hint ignored: ")
&& snmp_cstrcat(buf, buf_len, out_len,
allow_realloc, saved_hint)
&& snmp_cstrcat(buf, buf_len, out_len,
allow_realloc, ") ")) {
return sprint_realloc_octet_string(buf, buf_len,
out_len,
allow_realloc,
var, enums,
NULL, NULL);
} else {
return 0;
}
}
if (cp < ecp && separ) {
while ((*out_len + 1) >= *buf_len) {
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
}
*(*buf + *out_len) = separ;
(*out_len)++;
*(*buf + *out_len) = '\0';
}
repeat--;
}
if (term && cp < ecp) {
while ((*out_len + 1) >= *buf_len) {
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
}
*(*buf + *out_len) = term;
(*out_len)++;
*(*buf + *out_len) = '\0';
}
}
if (units) {
return (snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, " ")
&& snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units));
}
if ((*out_len >= *buf_len) &&
!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
*(*buf + *out_len) = '\0';
return 1;
}
output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT);
if (0 == output_format) {
output_format = NETSNMP_STRING_OUTPUT_GUESS;
}
switch (output_format) {
case NETSNMP_STRING_OUTPUT_GUESS:
hex = 0;
for (cp = var->val.string, x = 0; x < (int) var->val_len; x++, cp++) {
if (!isprint(*cp) && !isspace(*cp)) {
hex = 1;
}
}
break;
case NETSNMP_STRING_OUTPUT_ASCII:
hex = 0;
break;
case NETSNMP_STRING_OUTPUT_HEX:
hex = 1;
break;
}
if (var->val_len == 0) {
return snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\"");
}
if (hex) {
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"")) {
return 0;
}
} else {
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, "Hex-STRING: ")) {
return 0;
}
}
if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc,
var->val.string, var->val_len)) {
return 0;
}
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"")) {
return 0;
}
}
} else {
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
"STRING: ")) {
return 0;
}
}
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, "\"")) {
return 0;
}
if (!sprint_realloc_asciistring
(buf, buf_len, out_len, allow_realloc, var->val.string,
var->val_len)) {
return 0;
}
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"")) {
return 0;
}
}
if (units) {
return (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ")
&& snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units));
}
return 1;
}
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
/**
* Prints a float into a buffer.
*
* The variable var is encoded as a floating point value.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_float(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
if (var->type != ASN_OPAQUE_FLOAT) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be Float): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, "Opaque: Float: ")) {
return 0;
}
}
/*
* How much space needed for max. length float? 128 is overkill.
*/
while ((*out_len + 128 + 1) >= *buf_len) {
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
}
sprintf((char *) (*buf + *out_len), "%f", *var->val.floatVal);
*out_len += strlen((char *) (*buf + *out_len));
if (units) {
return (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ")
&& snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units));
}
return 1;
}
/**
* Prints a double into a buffer.
*
* The variable var is encoded as a double precision floating point value.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_double(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
if (var->type != ASN_OPAQUE_DOUBLE) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be Double): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, "Opaque: Float: ")) {
return 0;
}
}
/*
* How much space needed for max. length double? 128 is overkill.
*/
while ((*out_len + 128 + 1) >= *buf_len) {
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
}
sprintf((char *) (*buf + *out_len), "%f", *var->val.doubleVal);
*out_len += strlen((char *) (*buf + *out_len));
if (units) {
return (snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, " ")
&& snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units));
}
return 1;
}
#endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
/**
* Prints a counter into a buffer.
*
* The variable var is encoded as a counter value.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_counter64(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
char a64buf[I64CHARSZ + 1];
if (var->type != ASN_COUNTER64
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
&& var->type != ASN_OPAQUE_COUNTER64
&& var->type != ASN_OPAQUE_I64 && var->type != ASN_OPAQUE_U64
#endif
) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be Counter64): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
if (var->type != ASN_COUNTER64) {
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, "Opaque: ")) {
return 0;
}
}
#endif
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
switch (var->type) {
case ASN_OPAQUE_U64:
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, "UInt64: ")) {
return 0;
}
break;
case ASN_OPAQUE_I64:
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, "Int64: ")) {
return 0;
}
break;
case ASN_COUNTER64:
case ASN_OPAQUE_COUNTER64:
#endif
if (!snmp_cstrcat
(buf, buf_len, out_len, allow_realloc, "Counter64: ")) {
return 0;
}
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
}
#endif
}
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
if (var->type == ASN_OPAQUE_I64) {
printI64(a64buf, var->val.counter64);
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, a64buf)) {
return 0;
}
} else {
#endif
printU64(a64buf, var->val.counter64);
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, a64buf)) {
return 0;
}
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
}
#endif
if (units) {
return (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ")
&& snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units));
}
return 1;
}
/**
* Prints an object identifier into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_opaque(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
if (var->type != ASN_OPAQUE
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
&& var->type != ASN_OPAQUE_COUNTER64
&& var->type != ASN_OPAQUE_U64
&& var->type != ASN_OPAQUE_I64
&& var->type != ASN_OPAQUE_FLOAT && var->type != ASN_OPAQUE_DOUBLE
#endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be Opaque): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
switch (var->type) {
case ASN_OPAQUE_COUNTER64:
case ASN_OPAQUE_U64:
case ASN_OPAQUE_I64:
return sprint_realloc_counter64(buf, buf_len, out_len,
allow_realloc, var, enums, hint,
units);
break;
case ASN_OPAQUE_FLOAT:
return sprint_realloc_float(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
break;
case ASN_OPAQUE_DOUBLE:
return sprint_realloc_double(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
break;
case ASN_OPAQUE:
#endif
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
u_char str[] = "OPAQUE: ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
}
if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc,
var->val.string, var->val_len)) {
return 0;
}
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
}
#endif
if (units) {
return (snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) " ")
&& snmp_strcat(buf, buf_len, out_len, allow_realloc,
(const u_char *) units));
}
return 1;
}
/**
* Prints an object identifier into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_object_identifier(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
int buf_overflow = 0;
if (var->type != ASN_OBJECT_ID) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be OBJECT IDENTIFIER): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
u_char str[] = "OID: ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
}
netsnmp_sprint_realloc_objid_tree(buf, buf_len, out_len, allow_realloc,
&buf_overflow,
(oid *) (var->val.objid),
var->val_len / sizeof(oid));
if (buf_overflow) {
return 0;
}
if (units) {
return (snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) " ")
&& snmp_strcat(buf, buf_len, out_len, allow_realloc,
(const u_char *) units));
}
return 1;
}
/**
* Prints a timetick variable into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_timeticks(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
char timebuf[40];
if (var->type != ASN_TIMETICKS) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be Timeticks): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS)) {
char str[32];
sprintf(str, "%lu", *(u_long *) var->val.integer);
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
return 0;
}
return 1;
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
char str[32];
sprintf(str, "Timeticks: (%lu) ", *(u_long *) var->val.integer);
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
return 0;
}
}
uptimeString(*(u_long *) (var->val.integer), timebuf, sizeof(timebuf));
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc, (const u_char *) timebuf)) {
return 0;
}
if (units) {
return (snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) " ")
&& snmp_strcat(buf, buf_len, out_len, allow_realloc,
(const u_char *) units));
}
return 1;
}
/**
* Prints an integer according to the hint into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param val The variable to encode.
* @param decimaltype 'd' or 'u' depending on integer type
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may _NOT_ be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_hinted_integer(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
long val, const char decimaltype,
const char *hint, const char *units)
{
char fmt[10] = "%l@", tmp[256];
int shift = 0, len, negative = 0;
if (hint[0] == 'd') {
/*
* We might *actually* want a 'u' here.
*/
if (hint[1] == '-')
shift = atoi(hint + 2);
fmt[2] = decimaltype;
if (val < 0) {
negative = 1;
val = -val;
}
} else {
/*
* DISPLAY-HINT character is 'b', 'o', or 'x'.
*/
fmt[2] = hint[0];
}
if (hint[0] == 'b') {
unsigned long int bit = 0x80000000LU;
char *bp = tmp;
while (bit) {
*bp++ = val & bit ? '1' : '0';
bit >>= 1;
}
*bp = 0;
}
else
sprintf(tmp, fmt, val);
if (shift != 0) {
len = strlen(tmp);
if (shift <= len) {
tmp[len + 1] = 0;
while (shift--) {
tmp[len] = tmp[len - 1];
len--;
}
tmp[len] = '.';
} else {
tmp[shift + 1] = 0;
while (shift) {
if (len-- > 0) {
tmp[shift] = tmp[len];
} else {
tmp[shift] = '0';
}
shift--;
}
tmp[0] = '.';
}
}
if (negative) {
len = strlen(tmp)+1;
while (len) {
tmp[len] = tmp[len-1];
len--;
}
tmp[0] = '-';
}
return snmp_strcat(buf, buf_len, out_len, allow_realloc, (u_char *)tmp);
}
/**
* Prints an integer into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_integer(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
char *enum_string = NULL;
if (var->type != ASN_INTEGER) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be INTEGER): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
for (; enums; enums = enums->next) {
if (enums->value == *var->val.integer) {
enum_string = enums->label;
break;
}
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
(const u_char *) "INTEGER: ")) {
return 0;
}
}
if (enum_string == NULL ||
netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) {
if (hint) {
if (!(sprint_realloc_hinted_integer(buf, buf_len, out_len,
allow_realloc,
*var->val.integer, 'd',
hint, units))) {
return 0;
}
} else {
char str[32];
sprintf(str, "%ld", *var->val.integer);
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) str)) {
return 0;
}
}
} else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) enum_string)) {
return 0;
}
} else {
char str[32];
sprintf(str, "(%ld)", *var->val.integer);
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) enum_string)) {
return 0;
}
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
return 0;
}
}
if (units) {
return (snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) " ")
&& snmp_strcat(buf, buf_len, out_len, allow_realloc,
(const u_char *) units));
}
return 1;
}
/**
* Prints an unsigned integer into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_uinteger(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
char *enum_string = NULL;
if (var->type != ASN_UINTEGER) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be UInteger32): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
for (; enums; enums = enums->next) {
if (enums->value == *var->val.integer) {
enum_string = enums->label;
break;
}
}
if (enum_string == NULL ||
netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) {
if (hint) {
if (!(sprint_realloc_hinted_integer(buf, buf_len, out_len,
allow_realloc,
*var->val.integer, 'u',
hint, units))) {
return 0;
}
} else {
char str[32];
sprintf(str, "%lu", *var->val.integer);
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) str)) {
return 0;
}
}
} else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) enum_string)) {
return 0;
}
} else {
char str[32];
sprintf(str, "(%lu)", *var->val.integer);
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) enum_string)) {
return 0;
}
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc, (const u_char *) str)) {
return 0;
}
}
if (units) {
return (snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) " ")
&& snmp_strcat(buf, buf_len, out_len, allow_realloc,
(const u_char *) units));
}
return 1;
}
/**
* Prints a gauge value into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_gauge(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
char tmp[32];
if (var->type != ASN_GAUGE) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be Gauge32 or Unsigned32): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
u_char str[] = "Gauge32: ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
}
if (hint) {
if (!sprint_realloc_hinted_integer(buf, buf_len, out_len,
allow_realloc,
*var->val.integer, 'u', hint,
units)) {
return 0;
}
} else {
sprintf(tmp, "%u", (unsigned int)(*var->val.integer & 0xffffffff));
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc, (const u_char *) tmp)) {
return 0;
}
}
if (units) {
return (snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) " ")
&& snmp_strcat(buf, buf_len, out_len, allow_realloc,
(const u_char *) units));
}
return 1;
}
/**
* Prints a counter value into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_counter(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
char tmp[32];
if (var->type != ASN_COUNTER) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be Counter32): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
u_char str[] = "Counter32: ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
}
sprintf(tmp, "%u", (unsigned int)(*var->val.integer & 0xffffffff));
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc, (const u_char *) tmp)) {
return 0;
}
if (units) {
return (snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) " ")
&& snmp_strcat(buf, buf_len, out_len, allow_realloc,
(const u_char *) units));
}
return 1;
}
/**
* Prints a network address into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_networkaddress(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums, const char *hint,
const char *units)
{
size_t i;
if (var->type != ASN_IPADDRESS) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be NetworkAddress): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
u_char str[] = "Network Address: ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
}
while ((*out_len + (var->val_len * 3) + 2) >= *buf_len) {
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
}
for (i = 0; i < var->val_len; i++) {
sprintf((char *) (*buf + *out_len), "%02X", var->val.string[i]);
*out_len += 2;
if (i < var->val_len - 1) {
*(*buf + *out_len) = ':';
(*out_len)++;
}
}
return 1;
}
/**
* Prints an ip-address into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_ipaddress(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
u_char *ip = var->val.string;
if (var->type != ASN_IPADDRESS) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be IpAddress): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
u_char str[] = "IpAddress: ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
}
while ((*out_len + 17) >= *buf_len) {
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
return 0;
}
}
if (ip)
sprintf((char *) (*buf + *out_len), "%d.%d.%d.%d",
ip[0], ip[1], ip[2], ip[3]);
*out_len += strlen((char *) (*buf + *out_len));
return 1;
}
/**
* Prints a null value into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_null(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
u_char str[] = "NULL";
if (var->type != ASN_NULL) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be NULL): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
return snmp_strcat(buf, buf_len, out_len, allow_realloc, str);
}
/**
* Prints a bit string into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_bitstring(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
int len, bit;
u_char *cp;
char *enum_string;
if (var->type != ASN_BIT_STR && var->type != ASN_OCTET_STR) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be BITS): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
u_char str[] = "\"";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
} else {
u_char str[] = "BITS: ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
}
if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc,
var->val.bitstring, var->val_len)) {
return 0;
}
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
u_char str[] = "\"";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
} else {
cp = var->val.bitstring;
for (len = 0; len < (int) var->val_len; len++) {
for (bit = 0; bit < 8; bit++) {
if (*cp & (0x80 >> bit)) {
enum_string = NULL;
for (; enums; enums = enums->next) {
if (enums->value == (len * 8) + bit) {
enum_string = enums->label;
break;
}
}
if (enum_string == NULL ||
netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) {
char str[32];
sprintf(str, "%d ", (len * 8) + bit);
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) str)) {
return 0;
}
} else {
char str[32];
sprintf(str, "(%d) ", (len * 8) + bit);
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) enum_string)) {
return 0;
}
if (!snmp_strcat
(buf, buf_len, out_len, allow_realloc,
(const u_char *) str)) {
return 0;
}
}
}
}
cp++;
}
}
return 1;
}
int
sprint_realloc_nsapaddress(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums, const char *hint,
const char *units)
{
if (var->type != ASN_NSAP) {
if (!netsnmp_ds_get_boolean(
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
u_char str[] = "Wrong Type (should be NsapAddress): ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str))
return 0;
}
return sprint_realloc_by_type(buf, buf_len, out_len,
allow_realloc, var, NULL, NULL,
NULL);
}
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) {
u_char str[] = "NsapAddress: ";
if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) {
return 0;
}
}
return sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc,
var->val.string, var->val_len);
}
/**
* Fallback routine for a bad type, prints "Variable has bad type" into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_badtype(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
u_char str[] = "Variable has bad type";
return snmp_strcat(buf, buf_len, out_len, allow_realloc, str);
}
/**
* Universal print routine, prints a variable into a buffer according to the variable
* type.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param var The variable to encode.
* @param enums The enumeration ff this variable is enumerated. may be NULL.
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_by_type(u_char ** buf, size_t * buf_len, size_t * out_len,
int allow_realloc,
const netsnmp_variable_list * var,
const struct enum_list *enums,
const char *hint, const char *units)
{
DEBUGMSGTL(("output", "sprint_by_type, type %d\n", var->type));
switch (var->type) {
case ASN_INTEGER:
return sprint_realloc_integer(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
case ASN_OCTET_STR:
return sprint_realloc_octet_string(buf, buf_len, out_len,
allow_realloc, var, enums, hint,
units);
case ASN_BIT_STR:
return sprint_realloc_bitstring(buf, buf_len, out_len,
allow_realloc, var, enums, hint,
units);
case ASN_OPAQUE:
return sprint_realloc_opaque(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
case ASN_OBJECT_ID:
return sprint_realloc_object_identifier(buf, buf_len, out_len,
allow_realloc, var, enums,
hint, units);
case ASN_TIMETICKS:
return sprint_realloc_timeticks(buf, buf_len, out_len,
allow_realloc, var, enums, hint,
units);
case ASN_GAUGE:
return sprint_realloc_gauge(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
case ASN_COUNTER:
return sprint_realloc_counter(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
case ASN_IPADDRESS:
return sprint_realloc_ipaddress(buf, buf_len, out_len,
allow_realloc, var, enums, hint,
units);
case ASN_NULL:
return sprint_realloc_null(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
case ASN_UINTEGER:
return sprint_realloc_uinteger(buf, buf_len, out_len,
allow_realloc, var, enums, hint,
units);
case ASN_COUNTER64:
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
case ASN_OPAQUE_U64:
case ASN_OPAQUE_I64:
case ASN_OPAQUE_COUNTER64:
#endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
return sprint_realloc_counter64(buf, buf_len, out_len,
allow_realloc, var, enums, hint,
units);
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
case ASN_OPAQUE_FLOAT:
return sprint_realloc_float(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
case ASN_OPAQUE_DOUBLE:
return sprint_realloc_double(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
#endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
default:
DEBUGMSGTL(("sprint_by_type", "bad type: %d\n", var->type));
return sprint_realloc_badtype(buf, buf_len, out_len, allow_realloc,
var, enums, hint, units);
}
}
#ifndef NETSNMP_DISABLE_MIB_LOADING
/**
* Retrieves the tree head.
*
* @return the tree head.
*/
struct tree *
get_tree_head(void)
{
return (tree_head);
}
static char *confmibdir = NULL;
static char *confmibs = NULL;
static void
handle_mibdirs_conf(const char *token, char *line)
{
char *ctmp;
if (confmibdir) {
if ((*line == '+') || (*line == '-')) {
ctmp = (char *) malloc(strlen(confmibdir) + strlen(line) + 2);
if (!ctmp) {
DEBUGMSGTL(("read_config:initmib",
"mibdir conf malloc failed"));
return;
}
if(*line++ == '+')
sprintf(ctmp, "%s%c%s", confmibdir, ENV_SEPARATOR_CHAR, line);
else
sprintf(ctmp, "%s%c%s", line, ENV_SEPARATOR_CHAR, confmibdir);
} else {
ctmp = strdup(line);
if (!ctmp) {
DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed"));
return;
}
}
SNMP_FREE(confmibdir);
} else {
ctmp = strdup(line);
if (!ctmp) {
DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed"));
return;
}
}
confmibdir = ctmp;
DEBUGMSGTL(("read_config:initmib", "using mibdirs: %s\n", confmibdir));
}
static void
handle_mibs_conf(const char *token, char *line)
{
char *ctmp;
if (confmibs) {
if ((*line == '+') || (*line == '-')) {
ctmp = (char *) malloc(strlen(confmibs) + strlen(line) + 2);
if (!ctmp) {
DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed"));
return;
}
if(*line++ == '+')
sprintf(ctmp, "%s%c%s", confmibs, ENV_SEPARATOR_CHAR, line);
else
sprintf(ctmp, "%s%c%s", line, ENV_SEPARATOR_CHAR, confmibdir);
} else {
ctmp = strdup(line);
if (!ctmp) {
DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed"));
return;
}
}
SNMP_FREE(confmibs);
} else {
ctmp = strdup(line);
if (!ctmp) {
DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed"));
return;
}
}
confmibs = ctmp;
DEBUGMSGTL(("read_config:initmib", "using mibs: %s\n", confmibs));
}
static void
handle_mibfile_conf(const char *token, char *line)
{
DEBUGMSGTL(("read_config:initmib", "reading mibfile: %s\n", line));
read_mib(line);
}
#endif
static void
handle_print_numeric(const char *token, char *line)
{
const char *value;
char *st;
value = strtok_r(line, " \t\n", &st);
if (value && (
(strcasecmp(value, "yes") == 0) ||
(strcasecmp(value, "true") == 0) ||
(*value == '1') )) {
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
NETSNMP_OID_OUTPUT_NUMERIC);
}
}
char *
snmp_out_toggle_options(char *options)
{
while (*options) {
switch (*options++) {
case '0':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_2DIGIT_HEX_OUTPUT);
break;
case 'a':
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT,
NETSNMP_STRING_OUTPUT_ASCII);
break;
case 'b':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS);
break;
case 'e':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
break;
case 'E':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES);
break;
case 'f':
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
NETSNMP_OID_OUTPUT_FULL);
break;
case 'n':
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
NETSNMP_OID_OUTPUT_NUMERIC);
break;
case 'q':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
break;
case 'Q':
netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT, 1);
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
break;
case 's':
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
NETSNMP_OID_OUTPUT_SUFFIX);
break;
case 'S':
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
NETSNMP_OID_OUTPUT_MODULE);
break;
case 't':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS);
break;
case 'T':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT);
break;
case 'u':
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
NETSNMP_OID_OUTPUT_UCD);
break;
case 'U':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS);
break;
case 'v':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE);
break;
case 'x':
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT,
NETSNMP_STRING_OUTPUT_HEX);
break;
case 'X':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX);
break;
default:
return options - 1;
}
}
return NULL;
}
void
snmp_out_toggle_options_usage(const char *lead, FILE * outf)
{
fprintf(outf, "%s0: print leading 0 for single-digit hex characters\n", lead);
fprintf(outf, "%sa: print all strings in ascii format\n", lead);
fprintf(outf, "%sb: do not break OID indexes down\n", lead);
fprintf(outf, "%se: print enums numerically\n", lead);
fprintf(outf, "%sE: escape quotes in string indices\n", lead);
fprintf(outf, "%sf: print full OIDs on output\n", lead);
fprintf(outf, "%sn: print OIDs numerically\n", lead);
fprintf(outf, "%sq: quick print for easier parsing\n", lead);
fprintf(outf, "%sQ: quick print with equal-signs\n", lead); /* @@JDW */
fprintf(outf, "%ss: print only last symbolic element of OID\n", lead);
fprintf(outf, "%sS: print MIB module-id plus last element\n", lead);
fprintf(outf, "%st: print timeticks unparsed as numeric integers\n",
lead);
fprintf(outf,
"%sT: print human-readable text along with hex strings\n",
lead);
fprintf(outf, "%su: print OIDs using UCD-style prefix suppression\n",
lead);
fprintf(outf, "%sU: don't print units\n", lead);
fprintf(outf, "%sv: print values only (not OID = value)\n", lead);
fprintf(outf, "%sx: print all strings in hex format\n", lead);
fprintf(outf, "%sX: extended index format\n", lead);
}
char *
snmp_in_options(char *optarg, int argc, char *const *argv)
{
char *cp;
for (cp = optarg; *cp; cp++) {
switch (*cp) {
case 'b':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REGEX_ACCESS);
break;
case 'R':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS);
break;
case 'r':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE);
break;
case 'h':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT);
break;
case 'u':
netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID);
break;
case 's':
/* What if argc/argv are null ? */
if (!*(++cp))
cp = argv[optind++];
netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_OIDSUFFIX,
cp);
return NULL;
case 'S':
/* What if argc/argv are null ? */
if (!*(++cp))
cp = argv[optind++];
netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_OIDPREFIX,
cp);
return NULL;
default:
/*
* Here? Or in snmp_parse_args?
snmp_log(LOG_ERR, "Unknown input option passed to -I: %c.\n", *cp);
*/
return cp;
}
}
return NULL;
}
char *
snmp_in_toggle_options(char *options)
{
return snmp_in_options( options, 0, NULL );
}
/**
* Prints out a help usage for the in* toggle options.
*
* @param lead The lead to print for every line.
* @param outf The file descriptor to write to.
*
*/
void
snmp_in_toggle_options_usage(const char *lead, FILE * outf)
{
fprintf(outf, "%sb: do best/regex matching to find a MIB node\n", lead);
fprintf(outf, "%sh: don't apply DISPLAY-HINTs\n", lead);
fprintf(outf, "%sr: do not check values for range/type legality\n", lead);
fprintf(outf, "%sR: do random access to OID labels\n", lead);
fprintf(outf,
"%su: top-level OIDs must have '.' prefix (UCD-style)\n", lead);
fprintf(outf,
"%ss SUFFIX: Append all textual OIDs with SUFFIX before parsing\n",
lead);
fprintf(outf,
"%sS PREFIX: Prepend all textual OIDs with PREFIX before parsing\n",
lead);
}
/***
*
*/
void
register_mib_handlers(void)
{
#ifndef NETSNMP_DISABLE_MIB_LOADING
register_prenetsnmp_mib_handler("snmp", "mibdirs",
handle_mibdirs_conf, NULL,
"[mib-dirs|+mib-dirs|-mib-dirs]");
register_prenetsnmp_mib_handler("snmp", "mibs",
handle_mibs_conf, NULL,
"[mib-tokens|+mib-tokens]");
register_config_handler("snmp", "mibfile",
handle_mibfile_conf, NULL, "mibfile-to-read");
/*
* register the snmp.conf configuration handlers for default
* parsing behaviour
*/
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "showMibErrors",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_ERRORS);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "commentToEOL", /* Describes actual behaviour */
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_COMMENT_TERM);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "strictCommentTerm", /* Backward compatibility */
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_COMMENT_TERM);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "mibAllowUnderline",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_PARSE_LABEL);
netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "mibWarningLevel",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_WARNINGS);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "mibReplaceWithLatest",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_REPLACE);
#endif
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "printNumericEnums",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
register_prenetsnmp_mib_handler("snmp", "printNumericOids",
handle_print_numeric, NULL, "(1|yes|true|0|no|false)");
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "escapeQuotes",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "dontBreakdownOids",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "quickPrinting",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "numericTimeticks",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS);
netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "oidOutputFormat",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "suffixPrinting",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "extendedIndex",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "printHexText",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "printValueOnly",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE);
netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "dontPrintUnits",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS);
netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "hexOutputLength",
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_HEX_OUTPUT_LENGTH);
}
#ifndef NETSNMP_DISABLE_MIB_LOADING
/*
* function : netsnmp_set_mib_directory
* - This function sets the string of the directories
* from which the MIB modules will be searched or
* loaded.
* arguments: const char *dir, which are the directories
* from which the MIB modules will be searched or
* loaded.
* returns : -
*/
void
netsnmp_set_mib_directory(const char *dir)
{
const char *newdir;
char *olddir, *tmpdir = NULL;
DEBUGTRACE;
if (NULL == dir) {
return;
}
olddir = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_MIBDIRS);
if (olddir) {
if ((*dir == '+') || (*dir == '-')) {
/** New dir starts with '+', thus we add it. */
tmpdir = (char *)malloc(strlen(dir) + strlen(olddir) + 2);
if (!tmpdir) {
DEBUGMSGTL(("read_config:initmib", "set mibdir malloc failed"));
return;
}
if (*dir++ == '+')
sprintf(tmpdir, "%s%c%s", olddir, ENV_SEPARATOR_CHAR, dir);
else
sprintf(tmpdir, "%s%c%s", dir, ENV_SEPARATOR_CHAR, olddir);
newdir = tmpdir;
} else {
newdir = dir;
}
} else {
/** If dir starts with '+' skip '+' it. */
newdir = ((*dir == '+') ? ++dir : dir);
}
netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS,
newdir);
/** set_string calls strdup, so if we allocated memory, free it */
if (tmpdir == newdir) {
SNMP_FREE(tmpdir);
}
}
/*
* function : netsnmp_get_mib_directory
* - This function returns a string of the directories
* from which the MIB modules will be searched or
* loaded.
* If the value still does not exists, it will be made
* from the evironment variable 'MIBDIRS' and/or the
* default.
* arguments: -
* returns : char * of the directories in which the MIB modules
* will be searched/loaded.
*/
char *
netsnmp_get_mib_directory(void)
{
char *dir;
DEBUGTRACE;
dir = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS);
if (dir == NULL) {
DEBUGMSGTL(("get_mib_directory", "no mib directories set\n"));
/** Check if the environment variable is set */
dir = netsnmp_getenv("MIBDIRS");
if (dir == NULL) {
DEBUGMSGTL(("get_mib_directory", "no mib directories set by environment\n"));
/** Not set use hard coded path */
if (confmibdir == NULL) {
DEBUGMSGTL(("get_mib_directory", "no mib directories set by config\n"));
netsnmp_set_mib_directory(NETSNMP_DEFAULT_MIBDIRS);
}
else if ((*confmibdir == '+') || (*confmibdir == '-')) {
DEBUGMSGTL(("get_mib_directory", "mib directories set by config (but added)\n"));
netsnmp_set_mib_directory(NETSNMP_DEFAULT_MIBDIRS);
netsnmp_set_mib_directory(confmibdir);
}
else {
DEBUGMSGTL(("get_mib_directory", "mib directories set by config\n"));
netsnmp_set_mib_directory(confmibdir);
}
} else if ((*dir == '+') || (*dir == '-')) {
DEBUGMSGTL(("get_mib_directory", "mib directories set by environment (but added)\n"));
netsnmp_set_mib_directory(NETSNMP_DEFAULT_MIBDIRS);
netsnmp_set_mib_directory(dir);
} else {
DEBUGMSGTL(("get_mib_directory", "mib directories set by environment\n"));
netsnmp_set_mib_directory(dir);
}
dir = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS);
}
DEBUGMSGTL(("get_mib_directory", "mib directories set '%s'\n", dir));
return(dir);
}
/*
* function : netsnmp_fixup_mib_directory
* arguments: -
* returns : -
*/
void
netsnmp_fixup_mib_directory(void)
{
char *homepath = netsnmp_getenv("HOME");
char *mibpath = netsnmp_get_mib_directory();
char *oldmibpath = NULL;
char *ptr_home;
char *new_mibpath;
DEBUGTRACE;
if (homepath && mibpath) {
DEBUGMSGTL(("fixup_mib_directory", "mib directories '%s'\n", mibpath));
while ((ptr_home = strstr(mibpath, "$HOME"))) {
new_mibpath = (char *)malloc(strlen(mibpath) - strlen("$HOME") +
strlen(homepath)+1);
if (new_mibpath) {
*ptr_home = 0; /* null out the spot where we stop copying */
sprintf(new_mibpath, "%s%s%s", mibpath, homepath,
ptr_home + strlen("$HOME"));
/** swap in the new value and repeat */
mibpath = new_mibpath;
if (oldmibpath != NULL) {
SNMP_FREE(oldmibpath);
}
oldmibpath = new_mibpath;
} else {
break;
}
}
netsnmp_set_mib_directory(mibpath);
/* The above copies the mibpath for us, so... */
if (oldmibpath != NULL) {
SNMP_FREE(oldmibpath);
}
}
}
/**
* Initialises the mib reader.
*
* Reads in all settings from the environment.
*/
void
netsnmp_init_mib(void)
{
const char *prefix;
char *env_var, *entry;
PrefixListPtr pp = &mib_prefixes[0];
char *st = NULL;
if (Mib)
return;
netsnmp_init_mib_internals();
/*
* Initialise the MIB directory/ies
*/
netsnmp_fixup_mib_directory();
env_var = strdup(netsnmp_get_mib_directory());
netsnmp_mibindex_load();
DEBUGMSGTL(("init_mib",
"Seen MIBDIRS: Looking in '%s' for mib dirs ...\n",
env_var));
entry = strtok_r(env_var, ENV_SEPARATOR, &st);
while (entry) {
add_mibdir(entry);
entry = strtok_r(NULL, ENV_SEPARATOR, &st);
}
SNMP_FREE(env_var);
env_var = netsnmp_getenv("MIBFILES");
if (env_var != NULL) {
if (*env_var == '+')
entry = strtok_r(env_var+1, ENV_SEPARATOR, &st);
else
entry = strtok_r(env_var, ENV_SEPARATOR, &st);
while (entry) {
add_mibfile(entry, NULL, NULL);
entry = strtok_r(NULL, ENV_SEPARATOR, &st);
}
}
netsnmp_init_mib_internals();
/*
* Read in any modules or mibs requested
*/
env_var = netsnmp_getenv("MIBS");
if (env_var == NULL) {
if (confmibs != NULL)
env_var = strdup(confmibs);
else
env_var = strdup(NETSNMP_DEFAULT_MIBS);
} else {
env_var = strdup(env_var);
}
if (env_var && ((*env_var == '+') || (*env_var == '-'))) {
entry =
(char *) malloc(strlen(NETSNMP_DEFAULT_MIBS) + strlen(env_var) + 2);
if (!entry) {
DEBUGMSGTL(("init_mib", "env mibs malloc failed"));
SNMP_FREE(env_var);
return;
} else {
if (*env_var == '+')
sprintf(entry, "%s%c%s", NETSNMP_DEFAULT_MIBS, ENV_SEPARATOR_CHAR,
env_var+1);
else
sprintf(entry, "%s%c%s", env_var+1, ENV_SEPARATOR_CHAR,
NETSNMP_DEFAULT_MIBS );
}
SNMP_FREE(env_var);
env_var = entry;
}
DEBUGMSGTL(("init_mib",
"Seen MIBS: Looking in '%s' for mib files ...\n",
env_var));
entry = strtok_r(env_var, ENV_SEPARATOR, &st);
while (entry) {
if (strcasecmp(entry, DEBUG_ALWAYS_TOKEN) == 0) {
read_all_mibs();
} else if (strstr(entry, "/") != NULL) {
read_mib(entry);
} else {
netsnmp_read_module(entry);
}
entry = strtok_r(NULL, ENV_SEPARATOR, &st);
}
adopt_orphans();
SNMP_FREE(env_var);
env_var = netsnmp_getenv("MIBFILES");
if (env_var != NULL) {
if ((*env_var == '+') || (*env_var == '-')) {
#ifdef NETSNMP_DEFAULT_MIBFILES
entry =
(char *) malloc(strlen(NETSNMP_DEFAULT_MIBFILES) +
strlen(env_var) + 2);
if (!entry) {
DEBUGMSGTL(("init_mib", "env mibfiles malloc failed"));
} else {
if (*env_var++ == '+')
sprintf(entry, "%s%c%s", NETSNMP_DEFAULT_MIBFILES, ENV_SEPARATOR_CHAR,
env_var );
else
sprintf(entry, "%s%c%s", env_var, ENV_SEPARATOR_CHAR,
NETSNMP_DEFAULT_MIBFILES );
}
SNMP_FREE(env_var);
env_var = entry;
#else
env_var = strdup(env_var + 1);
#endif
} else {
env_var = strdup(env_var);
}
} else {
#ifdef NETSNMP_DEFAULT_MIBFILES
env_var = strdup(NETSNMP_DEFAULT_MIBFILES);
#endif
}
if (env_var != NULL) {
DEBUGMSGTL(("init_mib",
"Seen MIBFILES: Looking in '%s' for mib files ...\n",
env_var));
entry = strtok_r(env_var, ENV_SEPARATOR, &st);
while (entry) {
read_mib(entry);
entry = strtok_r(NULL, ENV_SEPARATOR, &st);
}
SNMP_FREE(env_var);
}
prefix = netsnmp_getenv("PREFIX");
if (!prefix)
prefix = Standard_Prefix;
Prefix = (char *) malloc(strlen(prefix) + 2);
if (!Prefix)
DEBUGMSGTL(("init_mib", "Prefix malloc failed"));
else
strcpy(Prefix, prefix);
DEBUGMSGTL(("init_mib",
"Seen PREFIX: Looking in '%s' for prefix ...\n", Prefix));
/*
* remove trailing dot
*/
if (Prefix) {
env_var = &Prefix[strlen(Prefix) - 1];
if (*env_var == '.')
*env_var = '\0';
}
pp->str = Prefix; /* fixup first mib_prefix entry */
/*
* now that the list of prefixes is built, save each string length.
*/
while (pp->str) {
pp->len = strlen(pp->str);
pp++;
}
Mib = tree_head; /* Backwards compatibility */
tree_top = (struct tree *) calloc(1, sizeof(struct tree));
/*
* XX error check ?
*/
if (tree_top) {
tree_top->label = strdup("(top)");
tree_top->child_list = tree_head;
}
}
#ifndef NETSNMP_NO_LEGACY_DEFINITIONS
void
init_mib(void)
{
netsnmp_init_mib();
}
#endif
/*
* Handle MIB indexes centrally
*/
static int _mibindex = 0; /* Last index in use */
static int _mibindex_max = 0; /* Size of index array */
char **_mibindexes = NULL;
int _mibindex_add( const char *dirname, int i );
void
netsnmp_mibindex_load( void )
{
DIR *dir;
struct dirent *file;
FILE *fp;
char tmpbuf[ 300];
char tmpbuf2[300];
int i;
char *cp;
/*
* Open the MIB index directory, or create it (empty)
*/
snprintf( tmpbuf, sizeof(tmpbuf), "%s/mib_indexes",
get_persistent_directory());
tmpbuf[sizeof(tmpbuf)-1] = 0;
dir = opendir( tmpbuf );
if ( dir == NULL ) {
DEBUGMSGTL(("mibindex", "load: (new)\n"));
mkdirhier( tmpbuf, NETSNMP_AGENT_DIRECTORY_MODE, 0);
return;
}
/*
* Create a list of which directory each file refers to
*/
while ((file = readdir( dir ))) {
if ( !isdigit((unsigned char)(file->d_name[0])))
continue;
i = atoi( file->d_name );
snprintf( tmpbuf, sizeof(tmpbuf), "%s/mib_indexes/%d",
get_persistent_directory(), i );
tmpbuf[sizeof(tmpbuf)-1] = 0;
fp = fopen( tmpbuf, "r" );
if (!fp)
continue;
cp = fgets( tmpbuf2, sizeof(tmpbuf2), fp );
if ( !cp ) {
DEBUGMSGTL(("mibindex", "Empty MIB index (%d)\n", i));
fclose(fp);
continue;
}
tmpbuf2[strlen(tmpbuf2)-1] = 0;
DEBUGMSGTL(("mibindex", "load: (%d) %s\n", i, tmpbuf2));
(void)_mibindex_add( tmpbuf2+4, i ); /* Skip 'DIR ' */
fclose( fp );
}
closedir( dir );
}
char *
netsnmp_mibindex_lookup( const char *dirname )
{
int i;
static char tmpbuf[300];
for (i=0; i<_mibindex; i++) {
if ( _mibindexes[i] &&
strcmp( _mibindexes[i], dirname ) == 0) {
snprintf(tmpbuf, sizeof(tmpbuf), "%s/mib_indexes/%d",
get_persistent_directory(), i);
tmpbuf[sizeof(tmpbuf)-1] = 0;
DEBUGMSGTL(("mibindex", "lookup: %s (%d) %s\n", dirname, i, tmpbuf ));
return tmpbuf;
}
}
DEBUGMSGTL(("mibindex", "lookup: (none)\n"));
return NULL;
}
int
_mibindex_add( const char *dirname, int i )
{
const int old_mibindex_max = _mibindex_max;
DEBUGMSGTL(("mibindex", "add: %s (%d)\n", dirname, i ));
if ( i == -1 )
i = _mibindex++;
if ( i >= _mibindex_max ) {
/*
* If the index array is full (or non-existent)
* then expand (or create) it
*/
_mibindex_max = i + 10;
_mibindexes = realloc(_mibindexes,
_mibindex_max * sizeof(_mibindexes[0]));
netsnmp_assert(_mibindexes);
memset(_mibindexes + old_mibindex_max, 0,
(_mibindex_max - old_mibindex_max) * sizeof(_mibindexes[0]));
}
_mibindexes[ i ] = strdup( dirname );
if ( i >= _mibindex )
_mibindex = i+1;
DEBUGMSGTL(("mibindex", "add: %d/%d/%d\n", i, _mibindex, _mibindex_max ));
return i;
}
FILE *
netsnmp_mibindex_new( const char *dirname )
{
FILE *fp;
char tmpbuf[300];
char *cp;
int i;
cp = netsnmp_mibindex_lookup( dirname );
if (!cp) {
i = _mibindex_add( dirname, -1 );
snprintf( tmpbuf, sizeof(tmpbuf), "%s/mib_indexes/%d",
get_persistent_directory(), i );
tmpbuf[sizeof(tmpbuf)-1] = 0;
cp = tmpbuf;
}
DEBUGMSGTL(("mibindex", "new: %s (%s)\n", dirname, cp ));
fp = fopen( cp, "w" );
if (fp)
fprintf( fp, "DIR %s\n", dirname );
return fp;
}
/**
* Unloads all mibs.
*/
void
shutdown_mib(void)
{
unload_all_mibs();
if (tree_top) {
if (tree_top->label)
SNMP_FREE(tree_top->label);
SNMP_FREE(tree_top);
}
tree_head = NULL;
Mib = NULL;
if (_mibindexes) {
int i;
for (i = 0; i < _mibindex; ++i)
SNMP_FREE(_mibindexes[i]);
free(_mibindexes);
_mibindex = 0;
_mibindex_max = 0;
_mibindexes = NULL;
}
if (Prefix != NULL && Prefix != &Standard_Prefix[0])
SNMP_FREE(Prefix);
if (Prefix)
Prefix = NULL;
SNMP_FREE(confmibs);
SNMP_FREE(confmibdir);
}
/**
* Prints the MIBs to the file fp.
*
* @param fp The file descriptor to print to.
*/
#ifndef NETSNMP_FEATURE_REMOVE_PRINT_MIB
void
print_mib(FILE * fp)
{
print_subtree(fp, tree_head, 0);
}
#endif /* NETSNMP_FEATURE_REMOVE_PRINT_MIB */
void
print_ascii_dump(FILE * fp)
{
fprintf(fp, "dump DEFINITIONS ::= BEGIN\n");
print_ascii_dump_tree(fp, tree_head, 0);
fprintf(fp, "END\n");
}
/**
* Set's the printing function printomat in a subtree according
* it's type
*
* @param subtree The subtree to set.
*/
void
set_function(struct tree *subtree)
{
subtree->printer = NULL;
switch (subtree->type) {
case TYPE_OBJID:
subtree->printomat = sprint_realloc_object_identifier;
break;
case TYPE_OCTETSTR:
subtree->printomat = sprint_realloc_octet_string;
break;
case TYPE_INTEGER:
subtree->printomat = sprint_realloc_integer;
break;
case TYPE_INTEGER32:
subtree->printomat = sprint_realloc_integer;
break;
case TYPE_NETADDR:
subtree->printomat = sprint_realloc_networkaddress;
break;
case TYPE_IPADDR:
subtree->printomat = sprint_realloc_ipaddress;