6986 lines
223 KiB
C
6986 lines
223 KiB
C
|
/*
|
|||
|
* 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 <EFBFBD> 2003 Sun Microsystems, Inc. All rights reserved.
|
|||
|
* Use is subject to license terms specified in the COPYING file
|
|||
|
* distributed with the Net-SNMP package.
|
|||
|
*
|
|||
|
* Portions of this file are copyrighted by:
|
|||
|
* Copyright (c) 2016 VMware, 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);
|
|||
|
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
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);
|
|||
|
#endif /*NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
|
|||
|
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
|
|||
|
*/
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
static int node_to_oid(struct tree *, oid *, size_t *);
|
|||
|
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 */
|
|||
|
|
|||
|
static char Standard_Prefix[] = ".1.3.6.1.2.1";
|
|||
|
|
|||
|
/*
|
|||
|
* Set default here as some uses of read_objid require valid pointer.
|
|||
|
*/
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
static char *Prefix = &Standard_Prefix[0];
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
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 <= 0)
|
|||
|
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':
|
|||
|
/* A string hint gives the max size - we may not need this much */
|
|||
|
cnt = SNMP_MIN(width, ecp - cp);
|
|||
|
while ((*out_len + cnt + 1) > *buf_len) {
|
|||
|
if (!allow_realloc || !snmp_realloc(buf, buf_len))
|
|||
|
return 0;
|
|||
|
}
|
|||
|
if (memchr(cp, '\0', cnt) == NULL) {
|
|||
|
/* No embedded '\0' - use memcpy() to preserve UTF-8 */
|
|||
|
memcpy(*buf + *out_len, cp, cnt);
|
|||
|
*out_len += cnt;
|
|||
|
*(*buf + *out_len) = '\0';
|
|||
|
} else 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)
|
|||
|
{
|
|||
|
char *printf_format_string = NULL;
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf_format_string = make_printf_format_string("%f");
|
|||
|
if (!printf_format_string) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
snprintf((char *)(*buf + *out_len), 128, printf_format_string, *var->val.floatVal);
|
|||
|
free(printf_format_string);
|
|||
|
*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)
|
|||
|
{
|
|||
|
char *printf_format_string = NULL;
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf_format_string = make_printf_format_string("%f");
|
|||
|
if (!printf_format_string) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
snprintf((char *)(*buf + *out_len), 128, printf_format_string, *var->val.doubleVal);
|
|||
|
free(printf_format_string);
|
|||
|
*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);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Generates a prinf format string.
|
|||
|
*
|
|||
|
* The original format string is combined with the optional
|
|||
|
* NETSNMP_DS_LIB_OUTPUT_PRECISION string (the -Op parameter).
|
|||
|
*
|
|||
|
* Example:
|
|||
|
* If the original format string is "%f", and the NETSNMP_DS_LIB_OUTPUT_PRECISION
|
|||
|
* is "5.2", the returned format string will be "%5.2f".
|
|||
|
*
|
|||
|
* The PRECISION string is inserted after the '%' of the original format string.
|
|||
|
* To prevent buffer overflow if NETSNMP_DS_LIB_OUTPUT_PRECISION is set to an
|
|||
|
* illegal size (e.g. with -Op 10000) snprintf should be used to prevent buffer
|
|||
|
* overflow.
|
|||
|
*
|
|||
|
* @param printf_format_default The format string used by the original printf.
|
|||
|
*
|
|||
|
* @return The address of of the new allocated format string (which must be freed
|
|||
|
* if no longer used), or NULL if any error (malloc).
|
|||
|
*/
|
|||
|
char *
|
|||
|
make_printf_format_string(const char *printf_format_default)
|
|||
|
{
|
|||
|
const char *cp_printf_format_default;
|
|||
|
const char *printf_precision;
|
|||
|
const char *cp_printf_precision;
|
|||
|
char *printf_format_string;
|
|||
|
char *cp_out;
|
|||
|
char c;
|
|||
|
|
|||
|
printf_precision = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION);
|
|||
|
if (!printf_precision) {
|
|||
|
printf_precision = "";
|
|||
|
}
|
|||
|
|
|||
|
/* reserve new format string buffer */
|
|||
|
printf_format_string = (char *) malloc(strlen(printf_format_default)+strlen(printf_precision)+1);
|
|||
|
if (!printf_format_string)
|
|||
|
{
|
|||
|
DEBUGMSGTL(("make_printf_format_string", "malloc failed\n"));
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
/* copy default format string, including the '%' */
|
|||
|
cp_out = printf_format_string;
|
|||
|
cp_printf_format_default = printf_format_default;
|
|||
|
while((c = *cp_printf_format_default) != '\0')
|
|||
|
{
|
|||
|
*cp_out++ = c;
|
|||
|
cp_printf_format_default++;
|
|||
|
if (c == '%') break;
|
|||
|
}
|
|||
|
|
|||
|
/* insert the precision string */
|
|||
|
cp_printf_precision = printf_precision;
|
|||
|
while ((c = *cp_printf_precision++) != '\0')
|
|||
|
{
|
|||
|
*cp_out++ = c;
|
|||
|
}
|
|||
|
|
|||
|
/* copy the remaining default format string, including the terminating '\0' */
|
|||
|
strcpy(cp_out, cp_printf_format_default);
|
|||
|
|
|||
|
DEBUGMSGTL(("make_printf_format_string", "\"%s\"+\"%s\"->\"%s\"\n",
|
|||
|
printf_format_default, printf_precision, printf_format_string));
|
|||
|
return printf_format_string;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#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_options(char *options, int argc, char *const *argv)
|
|||
|
{
|
|||
|
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 'p':
|
|||
|
/* What if argc/argv are null ? */
|
|||
|
if (!*(options)) {
|
|||
|
options = argv[optind++];
|
|||
|
}
|
|||
|
netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
|
|||
|
NETSNMP_DS_LIB_OUTPUT_PRECISION,
|
|||
|
options);
|
|||
|
return NULL; /* -Op... is a standalone option, so we're done here */
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
char *
|
|||
|
snmp_out_toggle_options(char *options)
|
|||
|
{
|
|||
|
return snmp_out_options( options, 0, 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, "%sp PRECISION: display floating point values with specified PRECISION (printf format string)\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; /* -Is... is a standalone option, so we're done here */
|
|||
|
|
|||
|
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; /* -IS... is a standalone option, so we're done here */
|
|||
|
|
|||
|
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());
|
|||
|
if (!env_var)
|
|||
|
return;
|
|||
|
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 );
|
|||
|
fclose( fp );
|
|||
|
if ( !cp ) {
|
|||
|
DEBUGMSGTL(("mibindex", "Empty MIB index (%d)\n", i));
|
|||
|
continue;
|
|||
|
}
|
|||
|
if ( strncmp( tmpbuf2, "DIR ", 4 ) != 0 ) {
|
|||
|
DEBUGMSGTL(("mibindex", "Malformed MIB index (%d)\n", i));
|
|||
|
continue;
|
|||
|
}
|
|||
|
tmpbuf2[strlen(tmpbuf2)-1] = 0;
|
|||
|
DEBUGMSGTL(("mibindex", "load: (%d) %s\n", i, tmpbuf2));
|
|||
|
(void)_mibindex_add( tmpbuf2+4, i ); /* Skip 'DIR ' */
|
|||
|
}
|
|||
|
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;
|
|||
|
break;
|
|||
|
case TYPE_COUNTER:
|
|||
|
subtree->printomat = sprint_realloc_counter;
|
|||
|
break;
|
|||
|
case TYPE_GAUGE:
|
|||
|
subtree->printomat = sprint_realloc_gauge;
|
|||
|
break;
|
|||
|
case TYPE_TIMETICKS:
|
|||
|
subtree->printomat = sprint_realloc_timeticks;
|
|||
|
break;
|
|||
|
case TYPE_OPAQUE:
|
|||
|
subtree->printomat = sprint_realloc_opaque;
|
|||
|
break;
|
|||
|
case TYPE_NULL:
|
|||
|
subtree->printomat = sprint_realloc_null;
|
|||
|
break;
|
|||
|
case TYPE_BITSTRING:
|
|||
|
subtree->printomat = sprint_realloc_bitstring;
|
|||
|
break;
|
|||
|
case TYPE_NSAPADDRESS:
|
|||
|
subtree->printomat = sprint_realloc_nsapaddress;
|
|||
|
break;
|
|||
|
case TYPE_COUNTER64:
|
|||
|
subtree->printomat = sprint_realloc_counter64;
|
|||
|
break;
|
|||
|
case TYPE_UINTEGER:
|
|||
|
subtree->printomat = sprint_realloc_uinteger;
|
|||
|
break;
|
|||
|
case TYPE_UNSIGNED32:
|
|||
|
subtree->printomat = sprint_realloc_gauge;
|
|||
|
break;
|
|||
|
case TYPE_OTHER:
|
|||
|
default:
|
|||
|
subtree->printomat = sprint_realloc_by_type;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
|
|||
|
/**
|
|||
|
* Reads an object identifier from an input string into internal OID form.
|
|||
|
*
|
|||
|
* When called, out_len must hold the maximum length of the output array.
|
|||
|
*
|
|||
|
* @param input the input string.
|
|||
|
* @param output the oid wirte.
|
|||
|
* @param out_len number of subid's in output.
|
|||
|
*
|
|||
|
* @return 1 if successful.
|
|||
|
*
|
|||
|
* If an error occurs, this function returns 0 and MAY set snmp_errno.
|
|||
|
* snmp_errno is NOT set if SET_SNMP_ERROR evaluates to nothing.
|
|||
|
* This can make multi-threaded use a tiny bit more robust.
|
|||
|
*/
|
|||
|
int
|
|||
|
read_objid(const char *input, oid * output, size_t * out_len)
|
|||
|
{ /* number of subid's in "output" */
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
struct tree *root = tree_top;
|
|||
|
char buf[SPRINT_MAX_LEN];
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
int ret, max_out_len;
|
|||
|
char *name, ch;
|
|||
|
const char *cp;
|
|||
|
|
|||
|
cp = input;
|
|||
|
while ((ch = *cp)) {
|
|||
|
if (('0' <= ch && ch <= '9')
|
|||
|
|| ('a' <= ch && ch <= 'z')
|
|||
|
|| ('A' <= ch && ch <= 'Z')
|
|||
|
|| ch == '-')
|
|||
|
cp++;
|
|||
|
else
|
|||
|
break;
|
|||
|
}
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
if (ch == ':')
|
|||
|
return get_node(input, output, out_len);
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
|
|||
|
if (*input == '.')
|
|||
|
input++;
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID)) {
|
|||
|
/*
|
|||
|
* get past leading '.', append '.' to Prefix.
|
|||
|
*/
|
|||
|
if (*Prefix == '.')
|
|||
|
strlcpy(buf, Prefix + 1, sizeof(buf));
|
|||
|
else
|
|||
|
strlcpy(buf, Prefix, sizeof(buf));
|
|||
|
strlcat(buf, ".", sizeof(buf));
|
|||
|
strlcat(buf, input, sizeof(buf));
|
|||
|
input = buf;
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
if ((root == NULL) && (tree_head != NULL)) {
|
|||
|
root = tree_head;
|
|||
|
}
|
|||
|
else if (root == NULL) {
|
|||
|
SET_SNMP_ERROR(SNMPERR_NOMIB);
|
|||
|
*out_len = 0;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
name = strdup(input);
|
|||
|
max_out_len = *out_len;
|
|||
|
*out_len = 0;
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
if ((ret =
|
|||
|
_add_strings_to_oid(root, name, output, out_len,
|
|||
|
max_out_len)) <= 0)
|
|||
|
#else
|
|||
|
if ((ret =
|
|||
|
_add_strings_to_oid(NULL, name, output, out_len,
|
|||
|
max_out_len)) <= 0)
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
{
|
|||
|
if (ret == 0)
|
|||
|
ret = SNMPERR_UNKNOWN_OBJID;
|
|||
|
SET_SNMP_ERROR(ret);
|
|||
|
SNMP_FREE(name);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
SNMP_FREE(name);
|
|||
|
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
*
|
|||
|
*/
|
|||
|
void
|
|||
|
netsnmp_sprint_realloc_objid(u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
int *buf_overflow,
|
|||
|
const oid * objid, size_t objidlen)
|
|||
|
{
|
|||
|
u_char *tbuf = NULL, *cp = NULL;
|
|||
|
size_t tbuf_len = 256, tout_len = 0;
|
|||
|
int tbuf_overflow = 0;
|
|||
|
int output_format;
|
|||
|
|
|||
|
if ((tbuf = (u_char *) calloc(tbuf_len, 1)) == NULL) {
|
|||
|
tbuf_overflow = 1;
|
|||
|
} else {
|
|||
|
*tbuf = '.';
|
|||
|
tout_len = 1;
|
|||
|
}
|
|||
|
|
|||
|
_oid_finish_printing(objid, objidlen,
|
|||
|
&tbuf, &tbuf_len, &tout_len,
|
|||
|
allow_realloc, &tbuf_overflow);
|
|||
|
|
|||
|
if (tbuf_overflow) {
|
|||
|
if (!*buf_overflow) {
|
|||
|
snmp_strcat(buf, buf_len, out_len, allow_realloc, tbuf);
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
SNMP_FREE(tbuf);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
|
|||
|
if (0 == output_format) {
|
|||
|
output_format = NETSNMP_OID_OUTPUT_NUMERIC;
|
|||
|
}
|
|||
|
switch (output_format) {
|
|||
|
case NETSNMP_OID_OUTPUT_FULL:
|
|||
|
case NETSNMP_OID_OUTPUT_NUMERIC:
|
|||
|
case NETSNMP_OID_OUTPUT_SUFFIX:
|
|||
|
case NETSNMP_OID_OUTPUT_MODULE:
|
|||
|
cp = tbuf;
|
|||
|
break;
|
|||
|
|
|||
|
case NETSNMP_OID_OUTPUT_NONE:
|
|||
|
default:
|
|||
|
cp = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (!*buf_overflow &&
|
|||
|
!snmp_strcat(buf, buf_len, out_len, allow_realloc, cp)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
SNMP_FREE(tbuf);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
*
|
|||
|
*/
|
|||
|
#ifdef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
void
|
|||
|
netsnmp_sprint_realloc_objid_tree(u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
int *buf_overflow,
|
|||
|
const oid * objid, size_t objidlen)
|
|||
|
{
|
|||
|
netsnmp_sprint_realloc_objid(buf, buf_len, out_len, allow_realloc,
|
|||
|
buf_overflow, objid, objidlen);
|
|||
|
}
|
|||
|
#else
|
|||
|
struct tree *
|
|||
|
netsnmp_sprint_realloc_objid_tree(u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
int *buf_overflow,
|
|||
|
const oid * objid, size_t objidlen)
|
|||
|
{
|
|||
|
u_char *tbuf = NULL, *cp = NULL;
|
|||
|
size_t tbuf_len = 512, tout_len = 0;
|
|||
|
struct tree *subtree = tree_head;
|
|||
|
size_t midpoint_offset = 0;
|
|||
|
int tbuf_overflow = 0;
|
|||
|
int output_format;
|
|||
|
|
|||
|
if ((tbuf = (u_char *) calloc(tbuf_len, 1)) == NULL) {
|
|||
|
tbuf_overflow = 1;
|
|||
|
} else {
|
|||
|
*tbuf = '.';
|
|||
|
tout_len = 1;
|
|||
|
}
|
|||
|
|
|||
|
subtree = _get_realloc_symbol(objid, objidlen, subtree,
|
|||
|
&tbuf, &tbuf_len, &tout_len,
|
|||
|
allow_realloc, &tbuf_overflow, NULL,
|
|||
|
&midpoint_offset);
|
|||
|
|
|||
|
if (tbuf_overflow) {
|
|||
|
if (!*buf_overflow) {
|
|||
|
snmp_strcat(buf, buf_len, out_len, allow_realloc, tbuf);
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
SNMP_FREE(tbuf);
|
|||
|
return subtree;
|
|||
|
}
|
|||
|
|
|||
|
output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
|
|||
|
if (0 == output_format) {
|
|||
|
output_format = NETSNMP_OID_OUTPUT_MODULE;
|
|||
|
}
|
|||
|
switch (output_format) {
|
|||
|
case NETSNMP_OID_OUTPUT_FULL:
|
|||
|
case NETSNMP_OID_OUTPUT_NUMERIC:
|
|||
|
cp = tbuf;
|
|||
|
break;
|
|||
|
|
|||
|
case NETSNMP_OID_OUTPUT_SUFFIX:
|
|||
|
case NETSNMP_OID_OUTPUT_MODULE:
|
|||
|
for (cp = tbuf; *cp; cp++);
|
|||
|
|
|||
|
if (midpoint_offset != 0) {
|
|||
|
cp = tbuf + midpoint_offset - 2; /* beyond the '.' */
|
|||
|
} else {
|
|||
|
while (cp >= tbuf) {
|
|||
|
if (isalpha(*cp)) {
|
|||
|
break;
|
|||
|
}
|
|||
|
cp--;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
while (cp >= tbuf) {
|
|||
|
if (*cp == '.') {
|
|||
|
break;
|
|||
|
}
|
|||
|
cp--;
|
|||
|
}
|
|||
|
|
|||
|
cp++;
|
|||
|
|
|||
|
if ((NETSNMP_OID_OUTPUT_MODULE == output_format)
|
|||
|
&& cp > tbuf) {
|
|||
|
char modbuf[256] = { 0 }, *mod =
|
|||
|
module_name(subtree->modid, modbuf);
|
|||
|
|
|||
|
/*
|
|||
|
* Don't add the module ID if it's just numeric (i.e. we couldn't look
|
|||
|
* it up properly.
|
|||
|
*/
|
|||
|
|
|||
|
if (!*buf_overflow && modbuf[0] != '#') {
|
|||
|
if (!snmp_strcat
|
|||
|
(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *) mod)
|
|||
|
|| !snmp_strcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *) "::")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case NETSNMP_OID_OUTPUT_UCD:
|
|||
|
{
|
|||
|
PrefixListPtr pp = &mib_prefixes[0];
|
|||
|
size_t ilen, tlen;
|
|||
|
const char *testcp;
|
|||
|
|
|||
|
cp = tbuf;
|
|||
|
tlen = strlen((char *) tbuf);
|
|||
|
|
|||
|
while (pp->str) {
|
|||
|
ilen = pp->len;
|
|||
|
testcp = pp->str;
|
|||
|
|
|||
|
if ((tlen > ilen) && memcmp(tbuf, testcp, ilen) == 0) {
|
|||
|
cp += (ilen + 1);
|
|||
|
break;
|
|||
|
}
|
|||
|
pp++;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case NETSNMP_OID_OUTPUT_NONE:
|
|||
|
default:
|
|||
|
cp = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (!*buf_overflow &&
|
|||
|
!snmp_strcat(buf, buf_len, out_len, allow_realloc, cp)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
SNMP_FREE(tbuf);
|
|||
|
return subtree;
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
|
|||
|
int
|
|||
|
sprint_realloc_objid(u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
const oid * objid, size_t objidlen)
|
|||
|
{
|
|||
|
int buf_overflow = 0;
|
|||
|
|
|||
|
netsnmp_sprint_realloc_objid_tree(buf, buf_len, out_len, allow_realloc,
|
|||
|
&buf_overflow, objid, objidlen);
|
|||
|
return !buf_overflow;
|
|||
|
}
|
|||
|
|
|||
|
#ifndef NETSNMP_FEATURE_REMOVE_SPRINT_OBJID
|
|||
|
int
|
|||
|
snprint_objid(char *buf, size_t buf_len,
|
|||
|
const oid * objid, size_t objidlen)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
|
|||
|
if (sprint_realloc_objid((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
objid, objidlen)) {
|
|||
|
return (int) out_len;
|
|||
|
} else {
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif /* NETSNMP_FEATURE_REMOVE_SPRINT_OBJID */
|
|||
|
|
|||
|
/**
|
|||
|
* Prints an oid to stdout.
|
|||
|
*
|
|||
|
* @param objid The oid to print
|
|||
|
* @param objidlen The length of oidid.
|
|||
|
*/
|
|||
|
void
|
|||
|
print_objid(const oid * objid, size_t objidlen)
|
|||
|
{ /* number of subidentifiers */
|
|||
|
fprint_objid(stdout, objid, objidlen);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Prints an oid to a file descriptor.
|
|||
|
*
|
|||
|
* @param f The file descriptor to print to.
|
|||
|
* @param objid The oid to print
|
|||
|
* @param objidlen The length of oidid.
|
|||
|
*/
|
|||
|
void
|
|||
|
fprint_objid(FILE * f, const oid * objid, size_t objidlen)
|
|||
|
{ /* number of subidentifiers */
|
|||
|
u_char *buf = NULL;
|
|||
|
size_t buf_len = 256, out_len = 0;
|
|||
|
int buf_overflow = 0;
|
|||
|
|
|||
|
if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
|
|||
|
fprintf(f, "[TRUNCATED]\n");
|
|||
|
return;
|
|||
|
} else {
|
|||
|
netsnmp_sprint_realloc_objid_tree(&buf, &buf_len, &out_len, 1,
|
|||
|
&buf_overflow, objid, objidlen);
|
|||
|
if (buf_overflow) {
|
|||
|
fprintf(f, "%s [TRUNCATED]\n", buf);
|
|||
|
} else {
|
|||
|
fprintf(f, "%s\n", buf);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SNMP_FREE(buf);
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
sprint_realloc_variable(u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
const oid * objid, size_t objidlen,
|
|||
|
const netsnmp_variable_list * variable)
|
|||
|
{
|
|||
|
int buf_overflow = 0;
|
|||
|
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
struct tree *subtree = tree_head;
|
|||
|
|
|||
|
subtree =
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
netsnmp_sprint_realloc_objid_tree(buf, buf_len, out_len,
|
|||
|
allow_realloc, &buf_overflow,
|
|||
|
objid, objidlen);
|
|||
|
|
|||
|
if (buf_overflow) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE)) {
|
|||
|
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) {
|
|||
|
if (!snmp_strcat
|
|||
|
(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *) " = ")) {
|
|||
|
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 *) " ")) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (!snmp_strcat
|
|||
|
(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *) " = ")) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
} /* end if-else NETSNMP_DS_LIB_QUICK_PRINT */
|
|||
|
} /* end if-else NETSNMP_DS_LIB_QUICKE_PRINT */
|
|||
|
} else {
|
|||
|
*out_len = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (variable->type == SNMP_NOSUCHOBJECT) {
|
|||
|
return snmp_strcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
"No Such Object available on this agent at this OID");
|
|||
|
} else if (variable->type == SNMP_NOSUCHINSTANCE) {
|
|||
|
return snmp_strcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
"No Such Instance currently exists at this OID");
|
|||
|
} else if (variable->type == SNMP_ENDOFMIBVIEW) {
|
|||
|
return snmp_strcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
"No more variables left in this MIB View (It is past the end of the MIB tree)");
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
} else if (subtree) {
|
|||
|
const char *units = NULL;
|
|||
|
const char *hint = NULL;
|
|||
|
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
|
|||
|
NETSNMP_DS_LIB_DONT_PRINT_UNITS)) {
|
|||
|
units = subtree->units;
|
|||
|
}
|
|||
|
|
|||
|
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
|
|||
|
NETSNMP_DS_LIB_NO_DISPLAY_HINT)) {
|
|||
|
hint = subtree->hint;
|
|||
|
}
|
|||
|
|
|||
|
if (subtree->printomat) {
|
|||
|
return (*subtree->printomat) (buf, buf_len, out_len,
|
|||
|
allow_realloc, variable,
|
|||
|
subtree->enums, hint,
|
|||
|
units);
|
|||
|
} else {
|
|||
|
return sprint_realloc_by_type(buf, buf_len, out_len,
|
|||
|
allow_realloc, variable,
|
|||
|
subtree->enums, hint,
|
|||
|
units);
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
} else {
|
|||
|
/*
|
|||
|
* Handle rare case where tree is empty.
|
|||
|
*/
|
|||
|
return sprint_realloc_by_type(buf, buf_len, out_len, allow_realloc,
|
|||
|
variable, NULL, NULL, NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#ifndef NETSNMP_FEATURE_REMOVE_SNPRINT_VARABLE
|
|||
|
int
|
|||
|
snprint_variable(char *buf, size_t buf_len,
|
|||
|
const oid * objid, size_t objidlen,
|
|||
|
const netsnmp_variable_list * variable)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
|
|||
|
if (sprint_realloc_variable((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
objid, objidlen, variable)) {
|
|||
|
return (int) out_len;
|
|||
|
} else {
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif /* NETSNMP_FEATURE_REMOVE_SNPRINT_VARABLE */
|
|||
|
|
|||
|
/**
|
|||
|
* Prints a variable to stdout.
|
|||
|
*
|
|||
|
* @param objid The object id.
|
|||
|
* @param objidlen The length of teh object id.
|
|||
|
* @param variable The variable to print.
|
|||
|
*/
|
|||
|
void
|
|||
|
print_variable(const oid * objid,
|
|||
|
size_t objidlen, const netsnmp_variable_list * variable)
|
|||
|
{
|
|||
|
fprint_variable(stdout, objid, objidlen, variable);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Prints a variable to a file descriptor.
|
|||
|
*
|
|||
|
* @param f The file descriptor to print to.
|
|||
|
* @param objid The object id.
|
|||
|
* @param objidlen The length of teh object id.
|
|||
|
* @param variable The variable to print.
|
|||
|
*/
|
|||
|
void
|
|||
|
fprint_variable(FILE * f,
|
|||
|
const oid * objid,
|
|||
|
size_t objidlen, const netsnmp_variable_list * variable)
|
|||
|
{
|
|||
|
u_char *buf = NULL;
|
|||
|
size_t buf_len = 256, out_len = 0;
|
|||
|
|
|||
|
if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
|
|||
|
fprintf(f, "[TRUNCATED]\n");
|
|||
|
return;
|
|||
|
} else {
|
|||
|
if (sprint_realloc_variable(&buf, &buf_len, &out_len, 1,
|
|||
|
objid, objidlen, variable)) {
|
|||
|
fprintf(f, "%s\n", buf);
|
|||
|
} else {
|
|||
|
fprintf(f, "%s [TRUNCATED]\n", buf);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SNMP_FREE(buf);
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
sprint_realloc_value(u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
const oid * objid, size_t objidlen,
|
|||
|
const netsnmp_variable_list * variable)
|
|||
|
{
|
|||
|
if (variable->type == SNMP_NOSUCHOBJECT) {
|
|||
|
return snmp_strcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
"No Such Object available on this agent at this OID");
|
|||
|
} else if (variable->type == SNMP_NOSUCHINSTANCE) {
|
|||
|
return snmp_strcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
"No Such Instance currently exists at this OID");
|
|||
|
} else if (variable->type == SNMP_ENDOFMIBVIEW) {
|
|||
|
return snmp_strcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
"No more variables left in this MIB View (It is past the end of the MIB tree)");
|
|||
|
} else {
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
const char *units = NULL;
|
|||
|
struct tree *subtree = tree_head;
|
|||
|
subtree = get_tree(objid, objidlen, subtree);
|
|||
|
if (subtree && !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
|
|||
|
NETSNMP_DS_LIB_DONT_PRINT_UNITS)) {
|
|||
|
units = subtree->units;
|
|||
|
}
|
|||
|
if (subtree) {
|
|||
|
if(subtree->printomat) {
|
|||
|
return (*subtree->printomat) (buf, buf_len, out_len,
|
|||
|
allow_realloc, variable,
|
|||
|
subtree->enums, subtree->hint,
|
|||
|
units);
|
|||
|
} else {
|
|||
|
return sprint_realloc_by_type(buf, buf_len, out_len,
|
|||
|
allow_realloc, variable,
|
|||
|
subtree->enums, subtree->hint,
|
|||
|
units);
|
|||
|
}
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
return sprint_realloc_by_type(buf, buf_len, out_len,
|
|||
|
allow_realloc, variable,
|
|||
|
NULL, NULL, NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#ifndef NETSNMP_FEATURE_REMOVE_SNPRINT_VALUE
|
|||
|
/* used in the perl module */
|
|||
|
int
|
|||
|
snprint_value(char *buf, size_t buf_len,
|
|||
|
const oid * objid, size_t objidlen,
|
|||
|
const netsnmp_variable_list * variable)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
|
|||
|
if (sprint_realloc_value((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
objid, objidlen, variable)) {
|
|||
|
return (int) out_len;
|
|||
|
} else {
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif /* NETSNMP_FEATURE_REMOVE_SNPRINT_VALUE */
|
|||
|
|
|||
|
void
|
|||
|
print_value(const oid * objid,
|
|||
|
size_t objidlen, const netsnmp_variable_list * variable)
|
|||
|
{
|
|||
|
fprint_value(stdout, objid, objidlen, variable);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
fprint_value(FILE * f,
|
|||
|
const oid * objid,
|
|||
|
size_t objidlen, const netsnmp_variable_list * variable)
|
|||
|
{
|
|||
|
u_char *buf = NULL;
|
|||
|
size_t buf_len = 256, out_len = 0;
|
|||
|
|
|||
|
if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
|
|||
|
fprintf(f, "[TRUNCATED]\n");
|
|||
|
return;
|
|||
|
} else {
|
|||
|
if (sprint_realloc_value(&buf, &buf_len, &out_len, 1,
|
|||
|
objid, objidlen, variable)) {
|
|||
|
fprintf(f, "%s\n", buf);
|
|||
|
} else {
|
|||
|
fprintf(f, "%s [TRUNCATED]\n", buf);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SNMP_FREE(buf);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Takes the value in VAR and turns it into an OID segment in var->name.
|
|||
|
*
|
|||
|
* @param var The variable.
|
|||
|
*
|
|||
|
* @return SNMPERR_SUCCESS or SNMPERR_GENERR
|
|||
|
*/
|
|||
|
int
|
|||
|
build_oid_segment(netsnmp_variable_list * var)
|
|||
|
{
|
|||
|
int i;
|
|||
|
uint32_t ipaddr;
|
|||
|
|
|||
|
if (var->name && var->name != var->name_loc)
|
|||
|
SNMP_FREE(var->name);
|
|||
|
switch (var->type) {
|
|||
|
case ASN_INTEGER:
|
|||
|
case ASN_COUNTER:
|
|||
|
case ASN_GAUGE:
|
|||
|
case ASN_TIMETICKS:
|
|||
|
var->name_length = 1;
|
|||
|
var->name = var->name_loc;
|
|||
|
var->name[0] = *(var->val.integer);
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_IPADDRESS:
|
|||
|
var->name_length = 4;
|
|||
|
var->name = var->name_loc;
|
|||
|
memcpy(&ipaddr, var->val.string, sizeof(ipaddr));
|
|||
|
var->name[0] = (ipaddr >> 24) & 0xff;
|
|||
|
var->name[1] = (ipaddr >> 16) & 0xff;
|
|||
|
var->name[2] = (ipaddr >> 8) & 0xff;
|
|||
|
var->name[3] = (ipaddr >> 0) & 0xff;
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_PRIV_IMPLIED_OBJECT_ID:
|
|||
|
var->name_length = var->val_len / sizeof(oid);
|
|||
|
if (var->name_length > (sizeof(var->name_loc) / sizeof(oid)))
|
|||
|
var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
|
|||
|
else
|
|||
|
var->name = var->name_loc;
|
|||
|
if (var->name == NULL)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
|
|||
|
for (i = 0; i < (int) var->name_length; i++)
|
|||
|
var->name[i] = var->val.objid[i];
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_OBJECT_ID:
|
|||
|
var->name_length = var->val_len / sizeof(oid) + 1;
|
|||
|
if (var->name_length > (sizeof(var->name_loc) / sizeof(oid)))
|
|||
|
var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
|
|||
|
else
|
|||
|
var->name = var->name_loc;
|
|||
|
if (var->name == NULL)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
|
|||
|
var->name[0] = var->name_length - 1;
|
|||
|
for (i = 0; i < (int) var->name_length - 1; i++)
|
|||
|
var->name[i + 1] = var->val.objid[i];
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_PRIV_IMPLIED_OCTET_STR:
|
|||
|
var->name_length = var->val_len;
|
|||
|
if (var->name_length > (sizeof(var->name_loc) / sizeof(oid)))
|
|||
|
var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
|
|||
|
else
|
|||
|
var->name = var->name_loc;
|
|||
|
if (var->name == NULL)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
|
|||
|
for (i = 0; i < (int) var->val_len; i++)
|
|||
|
var->name[i] = (oid) var->val.string[i];
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_OPAQUE:
|
|||
|
case ASN_OCTET_STR:
|
|||
|
var->name_length = var->val_len + 1;
|
|||
|
if (var->name_length > (sizeof(var->name_loc) / sizeof(oid)))
|
|||
|
var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
|
|||
|
else
|
|||
|
var->name = var->name_loc;
|
|||
|
if (var->name == NULL)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
|
|||
|
var->name[0] = (oid) var->val_len;
|
|||
|
for (i = 0; i < (int) var->val_len; i++)
|
|||
|
var->name[i + 1] = (oid) var->val.string[i];
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
DEBUGMSGTL(("build_oid_segment",
|
|||
|
"invalid asn type: %d\n", var->type));
|
|||
|
return SNMPERR_GENERR;
|
|||
|
}
|
|||
|
|
|||
|
if (var->name_length > MAX_OID_LEN) {
|
|||
|
DEBUGMSGTL(("build_oid_segment",
|
|||
|
"Something terribly wrong, namelen = %lu\n",
|
|||
|
(unsigned long)var->name_length));
|
|||
|
return SNMPERR_GENERR;
|
|||
|
}
|
|||
|
|
|||
|
return SNMPERR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int
|
|||
|
build_oid_noalloc(oid * in, size_t in_len, size_t * out_len,
|
|||
|
oid * prefix, size_t prefix_len,
|
|||
|
netsnmp_variable_list * indexes)
|
|||
|
{
|
|||
|
netsnmp_variable_list *var;
|
|||
|
|
|||
|
if (prefix) {
|
|||
|
if (in_len < prefix_len)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
memcpy(in, prefix, prefix_len * sizeof(oid));
|
|||
|
*out_len = prefix_len;
|
|||
|
} else {
|
|||
|
*out_len = 0;
|
|||
|
}
|
|||
|
|
|||
|
for (var = indexes; var != NULL; var = var->next_variable) {
|
|||
|
if (build_oid_segment(var) != SNMPERR_SUCCESS)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
if (var->name_length + *out_len <= in_len) {
|
|||
|
memcpy(&(in[*out_len]), var->name,
|
|||
|
sizeof(oid) * var->name_length);
|
|||
|
*out_len += var->name_length;
|
|||
|
} else {
|
|||
|
return SNMPERR_GENERR;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
DEBUGMSGTL(("build_oid_noalloc", "generated: "));
|
|||
|
DEBUGMSGOID(("build_oid_noalloc", in, *out_len));
|
|||
|
DEBUGMSG(("build_oid_noalloc", "\n"));
|
|||
|
return SNMPERR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
build_oid(oid ** out, size_t * out_len,
|
|||
|
oid * prefix, size_t prefix_len, netsnmp_variable_list * indexes)
|
|||
|
{
|
|||
|
oid tmpout[MAX_OID_LEN];
|
|||
|
|
|||
|
/*
|
|||
|
* xxx-rks: inefficent. try only building segments to find index len:
|
|||
|
* for (var = indexes; var != NULL; var = var->next_variable) {
|
|||
|
* if (build_oid_segment(var) != SNMPERR_SUCCESS)
|
|||
|
* return SNMPERR_GENERR;
|
|||
|
* *out_len += var->name_length;
|
|||
|
*
|
|||
|
* then see if it fits in existing buffer, or realloc buffer.
|
|||
|
*/
|
|||
|
if (build_oid_noalloc(tmpout, sizeof(tmpout), out_len,
|
|||
|
prefix, prefix_len, indexes) != SNMPERR_SUCCESS)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
|
|||
|
/** xxx-rks: should free previous value? */
|
|||
|
snmp_clone_mem((void **) out, (void *) tmpout, *out_len * sizeof(oid));
|
|||
|
|
|||
|
return SNMPERR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* vblist_out must contain a pre-allocated string of variables into
|
|||
|
* which indexes can be extracted based on the previously existing
|
|||
|
* types in the variable chain
|
|||
|
* returns:
|
|||
|
* SNMPERR_GENERR on error
|
|||
|
* SNMPERR_SUCCESS on success
|
|||
|
*/
|
|||
|
|
|||
|
int
|
|||
|
parse_oid_indexes(oid * oidIndex, size_t oidLen,
|
|||
|
netsnmp_variable_list * data)
|
|||
|
{
|
|||
|
netsnmp_variable_list *var = data;
|
|||
|
|
|||
|
while (var && oidLen > 0) {
|
|||
|
|
|||
|
if (parse_one_oid_index(&oidIndex, &oidLen, var, 0) !=
|
|||
|
SNMPERR_SUCCESS)
|
|||
|
break;
|
|||
|
|
|||
|
var = var->next_variable;
|
|||
|
}
|
|||
|
|
|||
|
if (var != NULL || oidLen != 0)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
return SNMPERR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int
|
|||
|
parse_one_oid_index(oid ** oidStart, size_t * oidLen,
|
|||
|
netsnmp_variable_list * data, int complete)
|
|||
|
{
|
|||
|
netsnmp_variable_list *var = data;
|
|||
|
oid tmpout[MAX_OID_LEN];
|
|||
|
unsigned int i;
|
|||
|
unsigned int uitmp = 0;
|
|||
|
|
|||
|
oid *oidIndex = *oidStart;
|
|||
|
|
|||
|
if (var == NULL || ((*oidLen == 0) && (complete == 0)))
|
|||
|
return SNMPERR_GENERR;
|
|||
|
else {
|
|||
|
switch (var->type) {
|
|||
|
case ASN_INTEGER:
|
|||
|
case ASN_COUNTER:
|
|||
|
case ASN_GAUGE:
|
|||
|
case ASN_TIMETICKS:
|
|||
|
if (*oidLen) {
|
|||
|
snmp_set_var_value(var, (u_char *) oidIndex++,
|
|||
|
sizeof(oid));
|
|||
|
--(*oidLen);
|
|||
|
} else {
|
|||
|
snmp_set_var_value(var, (u_char *) oidLen, sizeof(long));
|
|||
|
}
|
|||
|
DEBUGMSGTL(("parse_oid_indexes",
|
|||
|
"Parsed int(%d): %ld\n", var->type,
|
|||
|
*var->val.integer));
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_IPADDRESS:
|
|||
|
if ((4 > *oidLen) && (complete == 0))
|
|||
|
return SNMPERR_GENERR;
|
|||
|
|
|||
|
for (i = 0; i < 4 && i < *oidLen; ++i) {
|
|||
|
if (oidIndex[i] > 255) {
|
|||
|
DEBUGMSGTL(("parse_oid_indexes",
|
|||
|
"illegal oid in index: %" NETSNMP_PRIo "d\n",
|
|||
|
oidIndex[0]));
|
|||
|
return SNMPERR_GENERR; /* sub-identifier too large */
|
|||
|
}
|
|||
|
uitmp = uitmp + (oidIndex[i] << (8*(3-i)));
|
|||
|
}
|
|||
|
if (4 > (int) (*oidLen)) {
|
|||
|
oidIndex += *oidLen;
|
|||
|
(*oidLen) = 0;
|
|||
|
} else {
|
|||
|
oidIndex += 4;
|
|||
|
(*oidLen) -= 4;
|
|||
|
}
|
|||
|
uitmp = htonl(uitmp); /* put it in proper order for byte copies */
|
|||
|
uitmp =
|
|||
|
snmp_set_var_value(var, (u_char *) &uitmp, 4);
|
|||
|
DEBUGMSGTL(("parse_oid_indexes",
|
|||
|
"Parsed ipaddr(%d): %d.%d.%d.%d\n", var->type,
|
|||
|
var->val.string[0], var->val.string[1],
|
|||
|
var->val.string[2], var->val.string[3]));
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_OBJECT_ID:
|
|||
|
case ASN_PRIV_IMPLIED_OBJECT_ID:
|
|||
|
if (var->type == ASN_PRIV_IMPLIED_OBJECT_ID) {
|
|||
|
/*
|
|||
|
* might not be implied, might be fixed len. check if
|
|||
|
* caller set up val len, and use it if they did.
|
|||
|
*/
|
|||
|
if (0 == var->val_len)
|
|||
|
uitmp = *oidLen;
|
|||
|
else {
|
|||
|
DEBUGMSGTL(("parse_oid_indexes:fix", "fixed len oid\n"));
|
|||
|
uitmp = var->val_len;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (*oidLen) {
|
|||
|
uitmp = *oidIndex++;
|
|||
|
--(*oidLen);
|
|||
|
} else {
|
|||
|
uitmp = 0;
|
|||
|
}
|
|||
|
if ((uitmp > *oidLen) && (complete == 0))
|
|||
|
return SNMPERR_GENERR;
|
|||
|
}
|
|||
|
|
|||
|
if (uitmp > MAX_OID_LEN)
|
|||
|
return SNMPERR_GENERR; /* too big and illegal */
|
|||
|
|
|||
|
if (uitmp > *oidLen) {
|
|||
|
memcpy(tmpout, oidIndex, sizeof(oid) * (*oidLen));
|
|||
|
memset(&tmpout[*oidLen], 0x00,
|
|||
|
sizeof(oid) * (uitmp - *oidLen));
|
|||
|
snmp_set_var_value(var, (u_char *) tmpout,
|
|||
|
sizeof(oid) * uitmp);
|
|||
|
oidIndex += *oidLen;
|
|||
|
(*oidLen) = 0;
|
|||
|
} else {
|
|||
|
snmp_set_var_value(var, (u_char *) oidIndex,
|
|||
|
sizeof(oid) * uitmp);
|
|||
|
oidIndex += uitmp;
|
|||
|
(*oidLen) -= uitmp;
|
|||
|
}
|
|||
|
|
|||
|
DEBUGMSGTL(("parse_oid_indexes", "Parsed oid: "));
|
|||
|
DEBUGMSGOID(("parse_oid_indexes",
|
|||
|
var->val.objid, var->val_len / sizeof(oid)));
|
|||
|
DEBUGMSG(("parse_oid_indexes", "\n"));
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_OPAQUE:
|
|||
|
case ASN_OCTET_STR:
|
|||
|
case ASN_PRIV_IMPLIED_OCTET_STR:
|
|||
|
if (var->type == ASN_PRIV_IMPLIED_OCTET_STR) {
|
|||
|
/*
|
|||
|
* might not be implied, might be fixed len. check if
|
|||
|
* caller set up val len, and use it if they did.
|
|||
|
*/
|
|||
|
if (0 == var->val_len)
|
|||
|
uitmp = *oidLen;
|
|||
|
else {
|
|||
|
DEBUGMSGTL(("parse_oid_indexes:fix", "fixed len str\n"));
|
|||
|
uitmp = var->val_len;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (*oidLen) {
|
|||
|
uitmp = *oidIndex++;
|
|||
|
--(*oidLen);
|
|||
|
} else {
|
|||
|
uitmp = 0;
|
|||
|
}
|
|||
|
if ((uitmp > *oidLen) && (complete == 0))
|
|||
|
return SNMPERR_GENERR;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* we handle this one ourselves since we don't have
|
|||
|
* pre-allocated memory to copy from using
|
|||
|
* snmp_set_var_value()
|
|||
|
*/
|
|||
|
|
|||
|
if (uitmp == 0)
|
|||
|
break; /* zero length strings shouldn't malloc */
|
|||
|
|
|||
|
if (uitmp > MAX_OID_LEN)
|
|||
|
return SNMPERR_GENERR; /* too big and illegal */
|
|||
|
|
|||
|
/*
|
|||
|
* malloc by size+1 to allow a null to be appended.
|
|||
|
*/
|
|||
|
var->val_len = uitmp;
|
|||
|
var->val.string = (u_char *) calloc(1, uitmp + 1);
|
|||
|
if (var->val.string == NULL)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
|
|||
|
if ((size_t)uitmp > (*oidLen)) {
|
|||
|
for (i = 0; i < *oidLen; ++i)
|
|||
|
var->val.string[i] = (u_char) * oidIndex++;
|
|||
|
for (i = *oidLen; i < uitmp; ++i)
|
|||
|
var->val.string[i] = '\0';
|
|||
|
(*oidLen) = 0;
|
|||
|
} else {
|
|||
|
for (i = 0; i < uitmp; ++i)
|
|||
|
var->val.string[i] = (u_char) * oidIndex++;
|
|||
|
(*oidLen) -= uitmp;
|
|||
|
}
|
|||
|
var->val.string[uitmp] = '\0';
|
|||
|
|
|||
|
DEBUGMSGTL(("parse_oid_indexes",
|
|||
|
"Parsed str(%d): %s\n", var->type,
|
|||
|
var->val.string));
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
DEBUGMSGTL(("parse_oid_indexes",
|
|||
|
"invalid asn type: %d\n", var->type));
|
|||
|
return SNMPERR_GENERR;
|
|||
|
}
|
|||
|
}
|
|||
|
(*oidStart) = oidIndex;
|
|||
|
return SNMPERR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* dump_realloc_oid_to_inetaddress:
|
|||
|
* return 0 for failure,
|
|||
|
* return 1 for success,
|
|||
|
* return 2 for not handled
|
|||
|
*/
|
|||
|
|
|||
|
int
|
|||
|
dump_realloc_oid_to_inetaddress(const int addr_type, const oid * objid, size_t objidlen,
|
|||
|
u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
char quotechar)
|
|||
|
{
|
|||
|
int i, len;
|
|||
|
char intbuf[64], *p;
|
|||
|
char *const end = intbuf + sizeof(intbuf);
|
|||
|
unsigned char *zc;
|
|||
|
unsigned long zone;
|
|||
|
|
|||
|
if (!buf)
|
|||
|
return 1;
|
|||
|
|
|||
|
for (i = 0; i < objidlen; i++)
|
|||
|
if (objid[i] < 0 || objid[i] > 255)
|
|||
|
return 2;
|
|||
|
|
|||
|
p = intbuf;
|
|||
|
*p++ = quotechar;
|
|||
|
|
|||
|
switch (addr_type) {
|
|||
|
case IPV4:
|
|||
|
case IPV4Z:
|
|||
|
if ((addr_type == IPV4 && objidlen != 4) ||
|
|||
|
(addr_type == IPV4Z && objidlen != 8))
|
|||
|
return 2;
|
|||
|
|
|||
|
len = snprintf(p, end - p, "%" NETSNMP_PRIo "u.%" NETSNMP_PRIo "u."
|
|||
|
"%" NETSNMP_PRIo "u.%" NETSNMP_PRIo "u",
|
|||
|
objid[0], objid[1], objid[2], objid[3]);
|
|||
|
p += len;
|
|||
|
if (p >= end)
|
|||
|
return 2;
|
|||
|
if (addr_type == IPV4Z) {
|
|||
|
zc = (unsigned char*)&zone;
|
|||
|
zc[0] = objid[4];
|
|||
|
zc[1] = objid[5];
|
|||
|
zc[2] = objid[6];
|
|||
|
zc[3] = objid[7];
|
|||
|
zone = ntohl(zone);
|
|||
|
len = snprintf(p, end - p, "%%%lu", zone);
|
|||
|
p += len;
|
|||
|
if (p >= end)
|
|||
|
return 2;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case IPV6:
|
|||
|
case IPV6Z:
|
|||
|
if ((addr_type == IPV6 && objidlen != 16) ||
|
|||
|
(addr_type == IPV6Z && objidlen != 20))
|
|||
|
return 2;
|
|||
|
|
|||
|
len = 0;
|
|||
|
for (i = 0; i < 16; i ++) {
|
|||
|
len = snprintf(p, end - p, "%s%02" NETSNMP_PRIo "x", i ? ":" : "",
|
|||
|
objid[i]);
|
|||
|
p += len;
|
|||
|
if (p >= end)
|
|||
|
return 2;
|
|||
|
}
|
|||
|
|
|||
|
if (addr_type == IPV6Z) {
|
|||
|
zc = (unsigned char*)&zone;
|
|||
|
zc[0] = objid[16];
|
|||
|
zc[1] = objid[17];
|
|||
|
zc[2] = objid[18];
|
|||
|
zc[3] = objid[19];
|
|||
|
zone = ntohl(zone);
|
|||
|
len = snprintf(p, end - p, "%%%lu", zone);
|
|||
|
p += len;
|
|||
|
if (p >= end)
|
|||
|
return 2;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case DNS:
|
|||
|
default:
|
|||
|
/* DNS can just be handled by dump_realloc_oid_to_string() */
|
|||
|
return 2;
|
|||
|
}
|
|||
|
|
|||
|
*p++ = quotechar;
|
|||
|
if (p >= end)
|
|||
|
return 2;
|
|||
|
|
|||
|
*p++ = '\0';
|
|||
|
if (p >= end)
|
|||
|
return 2;
|
|||
|
|
|||
|
return snmp_cstrcat(buf, buf_len, out_len, allow_realloc, intbuf);
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
dump_realloc_oid_to_string(const oid * objid, size_t objidlen,
|
|||
|
u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
char quotechar)
|
|||
|
{
|
|||
|
if (buf) {
|
|||
|
int i, alen;
|
|||
|
|
|||
|
for (i = 0, alen = 0; i < (int) objidlen; i++) {
|
|||
|
oid tst = objid[i];
|
|||
|
if ((tst > 254) || (!isprint(tst))) {
|
|||
|
tst = (oid) '.';
|
|||
|
}
|
|||
|
|
|||
|
if (alen == 0) {
|
|||
|
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) {
|
|||
|
while ((*out_len + 2) >= *buf_len) {
|
|||
|
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
*(*buf + *out_len) = '\\';
|
|||
|
(*out_len)++;
|
|||
|
}
|
|||
|
while ((*out_len + 2) >= *buf_len) {
|
|||
|
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
*(*buf + *out_len) = quotechar;
|
|||
|
(*out_len)++;
|
|||
|
}
|
|||
|
|
|||
|
while ((*out_len + 2) >= *buf_len) {
|
|||
|
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
*(*buf + *out_len) = (char) tst;
|
|||
|
(*out_len)++;
|
|||
|
alen++;
|
|||
|
}
|
|||
|
|
|||
|
if (alen) {
|
|||
|
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) {
|
|||
|
while ((*out_len + 2) >= *buf_len) {
|
|||
|
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
*(*buf + *out_len) = '\\';
|
|||
|
(*out_len)++;
|
|||
|
}
|
|||
|
while ((*out_len + 2) >= *buf_len) {
|
|||
|
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
*(*buf + *out_len) = quotechar;
|
|||
|
(*out_len)++;
|
|||
|
}
|
|||
|
|
|||
|
*(*buf + *out_len) = '\0';
|
|||
|
}
|
|||
|
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
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) {
|
|||
|
char intbuf[64];
|
|||
|
if (*buf != NULL && *(*buf + *out_len - 1) != '.') {
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) ".")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
while (objidlen-- > 0) { /* output rest of name, uninterpreted */
|
|||
|
sprintf(intbuf, "%" NETSNMP_PRIo "u.", *objid++);
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) intbuf)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (*buf != NULL) {
|
|||
|
*(*buf + *out_len - 1) = '\0'; /* remove trailing dot */
|
|||
|
*out_len = *out_len - 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
static void
|
|||
|
_get_realloc_symbol_octet_string(size_t numids, const oid * objid,
|
|||
|
u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
int *buf_overflow, struct tree* tp)
|
|||
|
{
|
|||
|
netsnmp_variable_list var = { 0 };
|
|||
|
u_char buffer[1024];
|
|||
|
size_t i;
|
|||
|
|
|||
|
for (i = 0; i < numids; i++)
|
|||
|
buffer[i] = (u_char) objid[i];
|
|||
|
var.type = ASN_OCTET_STR;
|
|||
|
var.val.string = buffer;
|
|||
|
var.val_len = numids;
|
|||
|
if (!*buf_overflow) {
|
|||
|
if (!sprint_realloc_octet_string(buf, buf_len, out_len,
|
|||
|
allow_realloc, &var,
|
|||
|
NULL, tp->hint,
|
|||
|
NULL)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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)
|
|||
|
{
|
|||
|
struct tree *return_tree = NULL;
|
|||
|
int extended_index =
|
|||
|
netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX);
|
|||
|
int output_format =
|
|||
|
netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
|
|||
|
char intbuf[64];
|
|||
|
struct tree *orgtree = subtree;
|
|||
|
|
|||
|
if (!objid || !buf) {
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
for (; subtree; subtree = subtree->next_peer) {
|
|||
|
if (*objid == subtree->subid) {
|
|||
|
while (subtree->next_peer && subtree->next_peer->subid == *objid)
|
|||
|
subtree = subtree->next_peer;
|
|||
|
if (subtree->indexes) {
|
|||
|
in_dices = subtree->indexes;
|
|||
|
} else if (subtree->augments) {
|
|||
|
struct tree *tp2 =
|
|||
|
find_tree_node(subtree->augments, -1);
|
|||
|
if (tp2) {
|
|||
|
in_dices = tp2->indexes;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!strncmp(subtree->label, ANON, ANON_LEN) ||
|
|||
|
(NETSNMP_OID_OUTPUT_NUMERIC == output_format)) {
|
|||
|
sprintf(intbuf, "%lu", subtree->subid);
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
intbuf)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
subtree->label)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (objidlen > 1) {
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) ".")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
|
|||
|
return_tree = _get_realloc_symbol(objid + 1, objidlen - 1,
|
|||
|
subtree->child_list,
|
|||
|
buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
buf_overflow, in_dices,
|
|||
|
end_of_known);
|
|||
|
}
|
|||
|
|
|||
|
if (return_tree != NULL) {
|
|||
|
return return_tree;
|
|||
|
} else {
|
|||
|
return subtree;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (end_of_known) {
|
|||
|
*end_of_known = *out_len;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Subtree not found.
|
|||
|
*/
|
|||
|
|
|||
|
if (orgtree && in_dices && objidlen > 0) {
|
|||
|
sprintf(intbuf, "%" NETSNMP_PRIo "u.", *objid);
|
|||
|
if (!*buf_overflow
|
|||
|
&& !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) intbuf)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
objid++;
|
|||
|
objidlen--;
|
|||
|
}
|
|||
|
|
|||
|
while (in_dices && (objidlen > 0) &&
|
|||
|
(NETSNMP_OID_OUTPUT_NUMERIC != output_format) &&
|
|||
|
!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS)) {
|
|||
|
size_t numids;
|
|||
|
struct tree *tp;
|
|||
|
|
|||
|
tp = find_tree_node(in_dices->ilabel, -1);
|
|||
|
|
|||
|
if (!tp) {
|
|||
|
/*
|
|||
|
* Can't find an index in the mib tree. Bail.
|
|||
|
*/
|
|||
|
goto finish_it;
|
|||
|
}
|
|||
|
|
|||
|
if (extended_index) {
|
|||
|
if (*buf != NULL && *(*buf + *out_len - 1) == '.') {
|
|||
|
(*out_len)--;
|
|||
|
}
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) "[")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
switch (tp->type) {
|
|||
|
case TYPE_OCTETSTR:
|
|||
|
if (extended_index && tp->hint) {
|
|||
|
if (in_dices->isimplied) {
|
|||
|
numids = objidlen;
|
|||
|
if (numids > objidlen)
|
|||
|
goto finish_it;
|
|||
|
} else if (tp->ranges && !tp->ranges->next
|
|||
|
&& tp->ranges->low == tp->ranges->high) {
|
|||
|
numids = tp->ranges->low;
|
|||
|
if (numids > objidlen)
|
|||
|
goto finish_it;
|
|||
|
} else {
|
|||
|
numids = *objid;
|
|||
|
if (numids >= objidlen)
|
|||
|
goto finish_it;
|
|||
|
objid++;
|
|||
|
objidlen--;
|
|||
|
}
|
|||
|
if (numids > objidlen)
|
|||
|
goto finish_it;
|
|||
|
_get_realloc_symbol_octet_string(numids, objid, buf, buf_len,
|
|||
|
out_len, allow_realloc,
|
|||
|
buf_overflow, tp);
|
|||
|
} else if (in_dices->isimplied) {
|
|||
|
numids = objidlen;
|
|||
|
if (numids > objidlen)
|
|||
|
goto finish_it;
|
|||
|
|
|||
|
if (!*buf_overflow) {
|
|||
|
if (!dump_realloc_oid_to_string
|
|||
|
(objid, numids, buf, buf_len, out_len,
|
|||
|
allow_realloc, '\'')) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
} else if (tp->ranges && !tp->ranges->next
|
|||
|
&& tp->ranges->low == tp->ranges->high) {
|
|||
|
/*
|
|||
|
* a fixed-length octet string
|
|||
|
*/
|
|||
|
numids = tp->ranges->low;
|
|||
|
if (numids > objidlen)
|
|||
|
goto finish_it;
|
|||
|
|
|||
|
if (!*buf_overflow) {
|
|||
|
if (!dump_realloc_oid_to_string
|
|||
|
(objid, numids, buf, buf_len, out_len,
|
|||
|
allow_realloc, '\'')) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
numids = (size_t) * objid + 1;
|
|||
|
if (numids > objidlen)
|
|||
|
goto finish_it;
|
|||
|
if (numids == 1) {
|
|||
|
if (netsnmp_ds_get_boolean
|
|||
|
(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) {
|
|||
|
if (!*buf_overflow
|
|||
|
&& !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) "\\")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!*buf_overflow
|
|||
|
&& !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) "\"")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
if (netsnmp_ds_get_boolean
|
|||
|
(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) {
|
|||
|
if (!*buf_overflow
|
|||
|
&& !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) "\\")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!*buf_overflow
|
|||
|
&& !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) "\"")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (!*buf_overflow) {
|
|||
|
struct tree * next_peer;
|
|||
|
int normal_handling = 1;
|
|||
|
|
|||
|
if (tp->next_peer) {
|
|||
|
next_peer = tp->next_peer;
|
|||
|
}
|
|||
|
|
|||
|
/* Try handling the InetAddress in the OID, in case of failure,
|
|||
|
* use the normal_handling.
|
|||
|
*/
|
|||
|
if (tp->next_peer &&
|
|||
|
tp->tc_index != -1 &&
|
|||
|
next_peer->tc_index != -1 &&
|
|||
|
strcmp(get_tc_descriptor(tp->tc_index), "InetAddress") == 0 &&
|
|||
|
strcmp(get_tc_descriptor(next_peer->tc_index),
|
|||
|
"InetAddressType") == 0 ) {
|
|||
|
|
|||
|
int ret;
|
|||
|
int addr_type = *(objid - 1);
|
|||
|
|
|||
|
ret = dump_realloc_oid_to_inetaddress(addr_type,
|
|||
|
objid + 1, numids - 1, buf, buf_len, out_len,
|
|||
|
allow_realloc, '"');
|
|||
|
if (ret != 2) {
|
|||
|
normal_handling = 0;
|
|||
|
if (ret == 0) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
if (normal_handling && !dump_realloc_oid_to_string
|
|||
|
(objid + 1, numids - 1, buf, buf_len, out_len,
|
|||
|
allow_realloc, '"')) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
objid += numids;
|
|||
|
objidlen -= numids;
|
|||
|
break;
|
|||
|
|
|||
|
case TYPE_INTEGER32:
|
|||
|
case TYPE_UINTEGER:
|
|||
|
case TYPE_UNSIGNED32:
|
|||
|
case TYPE_GAUGE:
|
|||
|
case TYPE_INTEGER:
|
|||
|
if (tp->enums) {
|
|||
|
struct enum_list *ep = tp->enums;
|
|||
|
while (ep && ep->value != (int) (*objid)) {
|
|||
|
ep = ep->next;
|
|||
|
}
|
|||
|
if (ep) {
|
|||
|
if (!*buf_overflow
|
|||
|
&& !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) ep->label)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
} else {
|
|||
|
sprintf(intbuf, "%" NETSNMP_PRIo "u", *objid);
|
|||
|
if (!*buf_overflow
|
|||
|
&& !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) intbuf)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
sprintf(intbuf, "%" NETSNMP_PRIo "u", *objid);
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
intbuf)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
objid++;
|
|||
|
objidlen--;
|
|||
|
break;
|
|||
|
|
|||
|
case TYPE_TIMETICKS:
|
|||
|
/* In an index, this is probably a timefilter */
|
|||
|
if (extended_index) {
|
|||
|
uptimeString( *objid, intbuf, sizeof( intbuf ) );
|
|||
|
} else {
|
|||
|
sprintf(intbuf, "%" NETSNMP_PRIo "u", *objid);
|
|||
|
}
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
intbuf)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
objid++;
|
|||
|
objidlen--;
|
|||
|
break;
|
|||
|
|
|||
|
case TYPE_OBJID:
|
|||
|
if (in_dices->isimplied) {
|
|||
|
numids = objidlen;
|
|||
|
} else {
|
|||
|
numids = (size_t) * objid + 1;
|
|||
|
}
|
|||
|
if (numids > objidlen)
|
|||
|
goto finish_it;
|
|||
|
if (extended_index) {
|
|||
|
if (in_dices->isimplied) {
|
|||
|
if (!*buf_overflow
|
|||
|
&& !netsnmp_sprint_realloc_objid_tree(buf, buf_len,
|
|||
|
out_len,
|
|||
|
allow_realloc,
|
|||
|
buf_overflow,
|
|||
|
objid,
|
|||
|
numids)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (!*buf_overflow
|
|||
|
&& !netsnmp_sprint_realloc_objid_tree(buf, buf_len,
|
|||
|
out_len,
|
|||
|
allow_realloc,
|
|||
|
buf_overflow,
|
|||
|
objid + 1,
|
|||
|
numids -
|
|||
|
1)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
_get_realloc_symbol(objid, numids, NULL, buf, buf_len,
|
|||
|
out_len, allow_realloc, buf_overflow,
|
|||
|
NULL, NULL);
|
|||
|
}
|
|||
|
objid += (numids);
|
|||
|
objidlen -= (numids);
|
|||
|
break;
|
|||
|
|
|||
|
case TYPE_IPADDR:
|
|||
|
if (objidlen < 4)
|
|||
|
goto finish_it;
|
|||
|
sprintf(intbuf, "%" NETSNMP_PRIo "u.%" NETSNMP_PRIo "u."
|
|||
|
"%" NETSNMP_PRIo "u.%" NETSNMP_PRIo "u",
|
|||
|
objid[0], objid[1], objid[2], objid[3]);
|
|||
|
objid += 4;
|
|||
|
objidlen -= 4;
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) intbuf)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TYPE_NETADDR:{
|
|||
|
oid ntype = *objid++;
|
|||
|
|
|||
|
objidlen--;
|
|||
|
sprintf(intbuf, "%" NETSNMP_PRIo "u.", ntype);
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *)
|
|||
|
intbuf)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
|
|||
|
if (ntype == 1 && objidlen >= 4) {
|
|||
|
sprintf(intbuf, "%" NETSNMP_PRIo "u.%" NETSNMP_PRIo "u."
|
|||
|
"%" NETSNMP_PRIo "u.%" NETSNMP_PRIo "u",
|
|||
|
objid[0], objid[1], objid[2], objid[3]);
|
|||
|
if (!*buf_overflow
|
|||
|
&& !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) intbuf)) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
objid += 4;
|
|||
|
objidlen -= 4;
|
|||
|
} else {
|
|||
|
goto finish_it;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TYPE_NSAPADDRESS:
|
|||
|
default:
|
|||
|
goto finish_it;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (extended_index) {
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) "]")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len,
|
|||
|
allow_realloc,
|
|||
|
(const u_char *) ".")) {
|
|||
|
*buf_overflow = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
in_dices = in_dices->next;
|
|||
|
}
|
|||
|
|
|||
|
finish_it:
|
|||
|
_oid_finish_printing(objid, objidlen,
|
|||
|
buf, buf_len, out_len,
|
|||
|
allow_realloc, buf_overflow);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
struct tree *
|
|||
|
get_tree(const oid * objid, size_t objidlen, struct tree *subtree)
|
|||
|
{
|
|||
|
struct tree *return_tree = NULL;
|
|||
|
|
|||
|
for (; subtree; subtree = subtree->next_peer) {
|
|||
|
if (*objid == subtree->subid)
|
|||
|
goto found;
|
|||
|
}
|
|||
|
|
|||
|
return NULL;
|
|||
|
|
|||
|
found:
|
|||
|
while (subtree->next_peer && subtree->next_peer->subid == *objid)
|
|||
|
subtree = subtree->next_peer;
|
|||
|
if (objidlen > 1)
|
|||
|
return_tree =
|
|||
|
get_tree(objid + 1, objidlen - 1, subtree->child_list);
|
|||
|
if (return_tree != NULL)
|
|||
|
return return_tree;
|
|||
|
else
|
|||
|
return subtree;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Prints on oid description on stdout.
|
|||
|
*
|
|||
|
* @see fprint_description
|
|||
|
*/
|
|||
|
void
|
|||
|
print_description(oid * objid, size_t objidlen, /* number of subidentifiers */
|
|||
|
int width)
|
|||
|
{
|
|||
|
fprint_description(stdout, objid, objidlen, width);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Prints on oid description into a file descriptor.
|
|||
|
*
|
|||
|
* @param f The file descriptor to print to.
|
|||
|
* @param objid The object identifier.
|
|||
|
* @param objidlen The object id length.
|
|||
|
* @param width Number of subidentifiers.
|
|||
|
*/
|
|||
|
void
|
|||
|
fprint_description(FILE * f, oid * objid, size_t objidlen,
|
|||
|
int width)
|
|||
|
{
|
|||
|
u_char *buf = NULL;
|
|||
|
size_t buf_len = 256, out_len = 0;
|
|||
|
|
|||
|
if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) {
|
|||
|
fprintf(f, "[TRUNCATED]\n");
|
|||
|
return;
|
|||
|
} else {
|
|||
|
if (!sprint_realloc_description(&buf, &buf_len, &out_len, 1,
|
|||
|
objid, objidlen, width)) {
|
|||
|
fprintf(f, "%s [TRUNCATED]\n", buf);
|
|||
|
} else {
|
|||
|
fprintf(f, "%s\n", buf);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SNMP_FREE(buf);
|
|||
|
}
|
|||
|
|
|||
|
#ifndef NETSNMP_FEATURE_REMOVE_MIB_SNPRINT_DESCRIPTION
|
|||
|
int
|
|||
|
snprint_description(char *buf, size_t buf_len,
|
|||
|
oid * objid, size_t objidlen, int width)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
|
|||
|
if (sprint_realloc_description((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
objid, objidlen, width)) {
|
|||
|
return (int) out_len;
|
|||
|
} else {
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif /* NETSNMP_FEATURE_REMOVE_MIB_SNPRINT_DESCRIPTION */
|
|||
|
|
|||
|
int
|
|||
|
sprint_realloc_description(u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
oid * objid, size_t objidlen, int width)
|
|||
|
{
|
|||
|
struct tree *tp = get_tree(objid, objidlen, tree_head);
|
|||
|
struct tree *subtree = tree_head;
|
|||
|
int pos, len;
|
|||
|
char tmpbuf[128];
|
|||
|
const char *cp;
|
|||
|
|
|||
|
if (NULL == tp)
|
|||
|
return 0;
|
|||
|
|
|||
|
if (tp->type <= TYPE_SIMPLE_LAST)
|
|||
|
cp = " OBJECT-TYPE";
|
|||
|
else
|
|||
|
switch (tp->type) {
|
|||
|
case TYPE_TRAPTYPE:
|
|||
|
cp = " TRAP-TYPE";
|
|||
|
break;
|
|||
|
case TYPE_NOTIFTYPE:
|
|||
|
cp = " NOTIFICATION-TYPE";
|
|||
|
break;
|
|||
|
case TYPE_OBJGROUP:
|
|||
|
cp = " OBJECT-GROUP";
|
|||
|
break;
|
|||
|
case TYPE_AGENTCAP:
|
|||
|
cp = " AGENT-CAPABILITIES";
|
|||
|
break;
|
|||
|
case TYPE_MODID:
|
|||
|
cp = " MODULE-IDENTITY";
|
|||
|
break;
|
|||
|
case TYPE_OBJIDENTITY:
|
|||
|
cp = " OBJECT-IDENTITY";
|
|||
|
break;
|
|||
|
case TYPE_MODCOMP:
|
|||
|
cp = " MODULE-COMPLIANCE";
|
|||
|
break;
|
|||
|
default:
|
|||
|
sprintf(tmpbuf, " type_%d", tp->type);
|
|||
|
cp = tmpbuf;
|
|||
|
}
|
|||
|
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->label) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n")) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
if (!print_tree_node(buf, buf_len, out_len, allow_realloc, tp, width))
|
|||
|
return 0;
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "::= {"))
|
|||
|
return 0;
|
|||
|
pos = 5;
|
|||
|
while (objidlen > 1) {
|
|||
|
for (; subtree; subtree = subtree->next_peer) {
|
|||
|
if (*objid == subtree->subid) {
|
|||
|
while (subtree->next_peer && subtree->next_peer->subid == *objid)
|
|||
|
subtree = subtree->next_peer;
|
|||
|
if (strncmp(subtree->label, ANON, ANON_LEN)) {
|
|||
|
snprintf(tmpbuf, sizeof(tmpbuf), " %s(%lu)", subtree->label, subtree->subid);
|
|||
|
tmpbuf[ sizeof(tmpbuf)-1 ] = 0;
|
|||
|
} else
|
|||
|
sprintf(tmpbuf, " %lu", subtree->subid);
|
|||
|
len = strlen(tmpbuf);
|
|||
|
if (pos + len + 2 > width) {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len,
|
|||
|
allow_realloc, "\n "))
|
|||
|
return 0;
|
|||
|
pos = 5;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tmpbuf))
|
|||
|
return 0;
|
|||
|
pos += len;
|
|||
|
objid++;
|
|||
|
objidlen--;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (subtree)
|
|||
|
subtree = subtree->child_list;
|
|||
|
else
|
|||
|
break;
|
|||
|
}
|
|||
|
while (objidlen > 1) {
|
|||
|
sprintf(tmpbuf, " %" NETSNMP_PRIo "u", *objid);
|
|||
|
len = strlen(tmpbuf);
|
|||
|
if (pos + len + 2 > width) {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n "))
|
|||
|
return 0;
|
|||
|
pos = 5;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tmpbuf))
|
|||
|
return 0;
|
|||
|
pos += len;
|
|||
|
objid++;
|
|||
|
objidlen--;
|
|||
|
}
|
|||
|
sprintf(tmpbuf, " %" NETSNMP_PRIo "u }", *objid);
|
|||
|
len = strlen(tmpbuf);
|
|||
|
if (pos + len + 2 > width) {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n "))
|
|||
|
return 0;
|
|||
|
pos = 5;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tmpbuf))
|
|||
|
return 0;
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
static int
|
|||
|
print_tree_node(u_char ** buf, size_t * buf_len,
|
|||
|
size_t * out_len, int allow_realloc,
|
|||
|
struct tree *tp, int width)
|
|||
|
{
|
|||
|
const char *cp;
|
|||
|
char str[MAXTOKEN];
|
|||
|
int i, prevmod, pos, len;
|
|||
|
|
|||
|
if (tp) {
|
|||
|
module_name(tp->modid, str);
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " -- FROM\t") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
|
|||
|
return 0;
|
|||
|
pos = 16+strlen(str);
|
|||
|
for (i = 1, prevmod = tp->modid; i < tp->number_modules; i++) {
|
|||
|
if (prevmod != tp->module_list[i]) {
|
|||
|
module_name(tp->module_list[i], str);
|
|||
|
len = strlen(str);
|
|||
|
if (pos + len + 2 > width) {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
",\n --\t\t"))
|
|||
|
return 0;
|
|||
|
pos = 16;
|
|||
|
}
|
|||
|
else {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", "))
|
|||
|
return 0;
|
|||
|
pos += 2;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
|
|||
|
return 0;
|
|||
|
pos += len;
|
|||
|
}
|
|||
|
prevmod = tp->module_list[i];
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
|
|||
|
return 0;
|
|||
|
if (tp->tc_index != -1) {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" -- TEXTUAL CONVENTION ") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
get_tc_descriptor(tp->tc_index)) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
|
|||
|
return 0;
|
|||
|
}
|
|||
|
switch (tp->type) {
|
|||
|
case TYPE_OBJID:
|
|||
|
cp = "OBJECT IDENTIFIER";
|
|||
|
break;
|
|||
|
case TYPE_OCTETSTR:
|
|||
|
cp = "OCTET STRING";
|
|||
|
break;
|
|||
|
case TYPE_INTEGER:
|
|||
|
cp = "INTEGER";
|
|||
|
break;
|
|||
|
case TYPE_NETADDR:
|
|||
|
cp = "NetworkAddress";
|
|||
|
break;
|
|||
|
case TYPE_IPADDR:
|
|||
|
cp = "IpAddress";
|
|||
|
break;
|
|||
|
case TYPE_COUNTER:
|
|||
|
cp = "Counter32";
|
|||
|
break;
|
|||
|
case TYPE_GAUGE:
|
|||
|
cp = "Gauge32";
|
|||
|
break;
|
|||
|
case TYPE_TIMETICKS:
|
|||
|
cp = "TimeTicks";
|
|||
|
break;
|
|||
|
case TYPE_OPAQUE:
|
|||
|
cp = "Opaque";
|
|||
|
break;
|
|||
|
case TYPE_NULL:
|
|||
|
cp = "NULL";
|
|||
|
break;
|
|||
|
case TYPE_COUNTER64:
|
|||
|
cp = "Counter64";
|
|||
|
break;
|
|||
|
case TYPE_BITSTRING:
|
|||
|
cp = "BITS";
|
|||
|
break;
|
|||
|
case TYPE_NSAPADDRESS:
|
|||
|
cp = "NsapAddress";
|
|||
|
break;
|
|||
|
case TYPE_UINTEGER:
|
|||
|
cp = "UInteger32";
|
|||
|
break;
|
|||
|
case TYPE_UNSIGNED32:
|
|||
|
cp = "Unsigned32";
|
|||
|
break;
|
|||
|
case TYPE_INTEGER32:
|
|||
|
cp = "Integer32";
|
|||
|
break;
|
|||
|
default:
|
|||
|
cp = NULL;
|
|||
|
break;
|
|||
|
}
|
|||
|
#if NETSNMP_ENABLE_TESTING_CODE
|
|||
|
if (!cp && (tp->ranges || tp->enums)) { /* ranges without type ? */
|
|||
|
sprintf(str, "?0 with %s %s ?",
|
|||
|
tp->ranges ? "Range" : "", tp->enums ? "Enum" : "");
|
|||
|
cp = str;
|
|||
|
}
|
|||
|
#endif /* NETSNMP_ENABLE_TESTING_CODE */
|
|||
|
if (cp)
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" SYNTAX\t") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp))
|
|||
|
return 0;
|
|||
|
if (tp->ranges) {
|
|||
|
struct range_list *rp = tp->ranges;
|
|||
|
int first = 1;
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ("))
|
|||
|
return 0;
|
|||
|
while (rp) {
|
|||
|
switch (tp->type) {
|
|||
|
case TYPE_INTEGER:
|
|||
|
case TYPE_INTEGER32:
|
|||
|
if (rp->low == rp->high)
|
|||
|
sprintf(str, "%s%d", (first ? "" : " | "), rp->low );
|
|||
|
else
|
|||
|
sprintf(str, "%s%d..%d", (first ? "" : " | "),
|
|||
|
rp->low, rp->high);
|
|||
|
break;
|
|||
|
case TYPE_UNSIGNED32:
|
|||
|
case TYPE_OCTETSTR:
|
|||
|
case TYPE_GAUGE:
|
|||
|
case TYPE_UINTEGER:
|
|||
|
if (rp->low == rp->high)
|
|||
|
sprintf(str, "%s%u", (first ? "" : " | "),
|
|||
|
(unsigned)rp->low );
|
|||
|
else
|
|||
|
sprintf(str, "%s%u..%u", (first ? "" : " | "),
|
|||
|
(unsigned)rp->low, (unsigned)rp->high);
|
|||
|
break;
|
|||
|
default:
|
|||
|
/* No other range types allowed */
|
|||
|
break;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
|
|||
|
return 0;
|
|||
|
if (first)
|
|||
|
first = 0;
|
|||
|
rp = rp->next;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ") "))
|
|||
|
return 0;
|
|||
|
}
|
|||
|
if (tp->enums) {
|
|||
|
struct enum_list *ep = tp->enums;
|
|||
|
int first = 1;
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " {"))
|
|||
|
return 0;
|
|||
|
pos = 16 + strlen(cp) + 2;
|
|||
|
while (ep) {
|
|||
|
if (first)
|
|||
|
first = 0;
|
|||
|
else
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", "))
|
|||
|
return 0;
|
|||
|
snprintf(str, sizeof(str), "%s(%d)", ep->label, ep->value);
|
|||
|
str[ sizeof(str)-1 ] = 0;
|
|||
|
len = strlen(str);
|
|||
|
if (pos + len + 2 > width) {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len,
|
|||
|
allow_realloc, "\n\t\t "))
|
|||
|
return 0;
|
|||
|
pos = 18;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
|
|||
|
return 0;
|
|||
|
pos += len + 2;
|
|||
|
ep = ep->next;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "} "))
|
|||
|
return 0;
|
|||
|
}
|
|||
|
if (cp)
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
|
|||
|
return 0;
|
|||
|
if (tp->hint)
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" DISPLAY-HINT\t\"") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->hint) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\n"))
|
|||
|
return 0;
|
|||
|
if (tp->units)
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" UNITS\t\t\"") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->units) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\n"))
|
|||
|
return 0;
|
|||
|
switch (tp->access) {
|
|||
|
case MIB_ACCESS_READONLY:
|
|||
|
cp = "read-only";
|
|||
|
break;
|
|||
|
case MIB_ACCESS_READWRITE:
|
|||
|
cp = "read-write";
|
|||
|
break;
|
|||
|
case MIB_ACCESS_WRITEONLY:
|
|||
|
cp = "write-only";
|
|||
|
break;
|
|||
|
case MIB_ACCESS_NOACCESS:
|
|||
|
cp = "not-accessible";
|
|||
|
break;
|
|||
|
case MIB_ACCESS_NOTIFY:
|
|||
|
cp = "accessible-for-notify";
|
|||
|
break;
|
|||
|
case MIB_ACCESS_CREATE:
|
|||
|
cp = "read-create";
|
|||
|
break;
|
|||
|
case 0:
|
|||
|
cp = NULL;
|
|||
|
break;
|
|||
|
default:
|
|||
|
sprintf(str, "access_%d", tp->access);
|
|||
|
cp = str;
|
|||
|
}
|
|||
|
if (cp)
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" MAX-ACCESS\t") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
|
|||
|
return 0;
|
|||
|
switch (tp->status) {
|
|||
|
case MIB_STATUS_MANDATORY:
|
|||
|
cp = "mandatory";
|
|||
|
break;
|
|||
|
case MIB_STATUS_OPTIONAL:
|
|||
|
cp = "optional";
|
|||
|
break;
|
|||
|
case MIB_STATUS_OBSOLETE:
|
|||
|
cp = "obsolete";
|
|||
|
break;
|
|||
|
case MIB_STATUS_DEPRECATED:
|
|||
|
cp = "deprecated";
|
|||
|
break;
|
|||
|
case MIB_STATUS_CURRENT:
|
|||
|
cp = "current";
|
|||
|
break;
|
|||
|
case 0:
|
|||
|
cp = NULL;
|
|||
|
break;
|
|||
|
default:
|
|||
|
sprintf(str, "status_%d", tp->status);
|
|||
|
cp = str;
|
|||
|
}
|
|||
|
#if NETSNMP_ENABLE_TESTING_CODE
|
|||
|
if (!cp && (tp->indexes)) { /* index without status ? */
|
|||
|
sprintf(str, "?0 with %s ?", tp->indexes ? "Index" : "");
|
|||
|
cp = str;
|
|||
|
}
|
|||
|
#endif /* NETSNMP_ENABLE_TESTING_CODE */
|
|||
|
if (cp)
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" STATUS\t") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
|
|||
|
return 0;
|
|||
|
if (tp->augments)
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" AUGMENTS\t{ ") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->augments) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n"))
|
|||
|
return 0;
|
|||
|
if (tp->indexes) {
|
|||
|
struct index_list *ip = tp->indexes;
|
|||
|
int first = 1;
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" INDEX\t\t{ "))
|
|||
|
return 0;
|
|||
|
pos = 16 + 2;
|
|||
|
while (ip) {
|
|||
|
if (first)
|
|||
|
first = 0;
|
|||
|
else
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", "))
|
|||
|
return 0;
|
|||
|
snprintf(str, sizeof(str), "%s%s",
|
|||
|
ip->isimplied ? "IMPLIED " : "",
|
|||
|
ip->ilabel);
|
|||
|
str[ sizeof(str)-1 ] = 0;
|
|||
|
len = strlen(str);
|
|||
|
if (pos + len + 2 > width) {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n\t\t "))
|
|||
|
return 0;
|
|||
|
pos = 16 + 2;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
|
|||
|
return 0;
|
|||
|
pos += len + 2;
|
|||
|
ip = ip->next;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n"))
|
|||
|
return 0;
|
|||
|
}
|
|||
|
if (tp->varbinds) {
|
|||
|
struct varbind_list *vp = tp->varbinds;
|
|||
|
int first = 1;
|
|||
|
|
|||
|
if (tp->type == TYPE_TRAPTYPE) {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" VARIABLES\t{ "))
|
|||
|
return 0;
|
|||
|
} else {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" OBJECTS\t{ "))
|
|||
|
return 0;
|
|||
|
}
|
|||
|
pos = 16 + 2;
|
|||
|
while (vp) {
|
|||
|
if (first)
|
|||
|
first = 0;
|
|||
|
else
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", "))
|
|||
|
return 0;
|
|||
|
strlcpy(str, vp->vblabel, sizeof(str));
|
|||
|
len = strlen(str);
|
|||
|
if (pos + len + 2 > width) {
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
"\n\t\t "))
|
|||
|
return 0;
|
|||
|
pos = 16 + 2;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
|
|||
|
return 0;
|
|||
|
pos += len + 2;
|
|||
|
vp = vp->next;
|
|||
|
}
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n"))
|
|||
|
return 0;
|
|||
|
}
|
|||
|
if (tp->description)
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" DESCRIPTION\t\"") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->description) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\n"))
|
|||
|
return 0;
|
|||
|
if (tp->defaultValue)
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
|
|||
|
" DEFVAL\t{ ") ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->defaultValue) ||
|
|||
|
!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n"))
|
|||
|
return 0;
|
|||
|
} else
|
|||
|
if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "No description\n"))
|
|||
|
return 0;
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
get_module_node(const char *fname,
|
|||
|
const char *module, oid * objid, size_t * objidlen)
|
|||
|
{
|
|||
|
int modid, rc = 0;
|
|||
|
struct tree *tp;
|
|||
|
char *name, *cp;
|
|||
|
|
|||
|
if (!strcmp(module, "ANY"))
|
|||
|
modid = -1;
|
|||
|
else {
|
|||
|
netsnmp_read_module(module);
|
|||
|
modid = which_module(module);
|
|||
|
if (modid == -1)
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Isolate the first component of the name ...
|
|||
|
*/
|
|||
|
name = strdup(fname);
|
|||
|
cp = strchr(name, '.');
|
|||
|
if (cp != NULL) {
|
|||
|
*cp = '\0';
|
|||
|
cp++;
|
|||
|
}
|
|||
|
/*
|
|||
|
* ... and locate it in the tree.
|
|||
|
*/
|
|||
|
tp = find_tree_node(name, modid);
|
|||
|
if (tp) {
|
|||
|
size_t maxlen = *objidlen;
|
|||
|
|
|||
|
/*
|
|||
|
* Set the first element of the object ID
|
|||
|
*/
|
|||
|
if (node_to_oid(tp, objid, objidlen)) {
|
|||
|
rc = 1;
|
|||
|
|
|||
|
/*
|
|||
|
* If the name requested was more than one element,
|
|||
|
* tag on the rest of the components
|
|||
|
*/
|
|||
|
if (cp != NULL)
|
|||
|
rc = _add_strings_to_oid(tp, cp, objid, objidlen, maxlen);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SNMP_FREE(name);
|
|||
|
return (rc);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* @internal
|
|||
|
*
|
|||
|
* Populates the object identifier from a node in the MIB hierarchy.
|
|||
|
* Builds up the object ID, working backwards,
|
|||
|
* starting from the end of the objid buffer.
|
|||
|
* When the top of the MIB tree is reached, the buffer is adjusted.
|
|||
|
*
|
|||
|
* The buffer length is set to the number of subidentifiers
|
|||
|
* for the object identifier associated with the MIB node.
|
|||
|
*
|
|||
|
* @return the number of subidentifiers copied.
|
|||
|
*
|
|||
|
* If 0 is returned, the objid buffer is too small,
|
|||
|
* and the buffer contents are indeterminate.
|
|||
|
* The buffer length can be used to create a larger buffer.
|
|||
|
*/
|
|||
|
static int
|
|||
|
node_to_oid(struct tree *tp, oid * objid, size_t * objidlen)
|
|||
|
{
|
|||
|
int numids, lenids;
|
|||
|
oid *op;
|
|||
|
|
|||
|
if (!tp || !objid || !objidlen)
|
|||
|
return 0;
|
|||
|
|
|||
|
lenids = (int) *objidlen;
|
|||
|
op = objid + lenids; /* points after the last element */
|
|||
|
|
|||
|
for (numids = 0; tp; tp = tp->parent, numids++) {
|
|||
|
if (numids >= lenids)
|
|||
|
continue;
|
|||
|
--op;
|
|||
|
*op = tp->subid;
|
|||
|
}
|
|||
|
|
|||
|
*objidlen = (size_t) numids;
|
|||
|
if (numids > lenids) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
if (numids < lenids)
|
|||
|
memmove(objid, op, numids * sizeof(oid));
|
|||
|
|
|||
|
return (numids);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Replace \x with x stop at eos_marker
|
|||
|
* return NULL if eos_marker not found
|
|||
|
*/
|
|||
|
static char *_apply_escapes(char *src, char eos_marker)
|
|||
|
{
|
|||
|
char *dst;
|
|||
|
int backslash = 0;
|
|||
|
|
|||
|
dst = src;
|
|||
|
while (*src) {
|
|||
|
if (backslash) {
|
|||
|
backslash = 0;
|
|||
|
*dst++ = *src;
|
|||
|
} else {
|
|||
|
if (eos_marker == *src) break;
|
|||
|
if ('\\' == *src) {
|
|||
|
backslash = 1;
|
|||
|
} else {
|
|||
|
*dst++ = *src;
|
|||
|
}
|
|||
|
}
|
|||
|
src++;
|
|||
|
}
|
|||
|
if (!*src) {
|
|||
|
/* never found eos_marker */
|
|||
|
return NULL;
|
|||
|
} else {
|
|||
|
*dst = 0;
|
|||
|
return src;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
|
|||
|
static int
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
_add_strings_to_oid(struct tree *tp, char *cp,
|
|||
|
oid * objid, size_t * objidlen, size_t maxlen)
|
|||
|
#else
|
|||
|
_add_strings_to_oid(void *tp, char *cp,
|
|||
|
oid * objid, size_t * objidlen, size_t maxlen)
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
{
|
|||
|
oid subid;
|
|||
|
char *fcp, *ecp, *cp2 = NULL;
|
|||
|
char doingquote;
|
|||
|
int len = -1;
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
struct tree *tp2 = NULL;
|
|||
|
struct index_list *in_dices = NULL;
|
|||
|
int pos = -1;
|
|||
|
int check =
|
|||
|
!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE);
|
|||
|
int do_hint = !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT);
|
|||
|
int len_index = 1000000;
|
|||
|
|
|||
|
while (cp && tp && tp->child_list) {
|
|||
|
fcp = cp;
|
|||
|
tp2 = tp->child_list;
|
|||
|
/*
|
|||
|
* Isolate the next entry
|
|||
|
*/
|
|||
|
cp2 = strchr(cp, '.');
|
|||
|
if (cp2)
|
|||
|
*cp2++ = '\0';
|
|||
|
|
|||
|
/*
|
|||
|
* Search for the appropriate child
|
|||
|
*/
|
|||
|
if (isdigit((unsigned char)(*cp))) {
|
|||
|
subid = strtoul(cp, &ecp, 0);
|
|||
|
if (*ecp)
|
|||
|
goto bad_id;
|
|||
|
while (tp2 && tp2->subid != subid)
|
|||
|
tp2 = tp2->next_peer;
|
|||
|
} else {
|
|||
|
while (tp2 && strcmp(tp2->label, fcp))
|
|||
|
tp2 = tp2->next_peer;
|
|||
|
if (!tp2)
|
|||
|
goto bad_id;
|
|||
|
subid = tp2->subid;
|
|||
|
}
|
|||
|
if (*objidlen >= maxlen)
|
|||
|
goto bad_id;
|
|||
|
while (tp2 && tp2->next_peer && tp2->next_peer->subid == subid)
|
|||
|
tp2 = tp2->next_peer;
|
|||
|
objid[*objidlen] = subid;
|
|||
|
(*objidlen)++;
|
|||
|
|
|||
|
cp = cp2;
|
|||
|
if (!tp2)
|
|||
|
break;
|
|||
|
tp = tp2;
|
|||
|
}
|
|||
|
|
|||
|
if (tp && !tp->child_list) {
|
|||
|
if ((tp2 = tp->parent)) {
|
|||
|
if (tp2->indexes)
|
|||
|
in_dices = tp2->indexes;
|
|||
|
else if (tp2->augments) {
|
|||
|
tp2 = find_tree_node(tp2->augments, -1);
|
|||
|
if (tp2)
|
|||
|
in_dices = tp2->indexes;
|
|||
|
}
|
|||
|
}
|
|||
|
tp = NULL;
|
|||
|
}
|
|||
|
|
|||
|
while (cp && in_dices) {
|
|||
|
fcp = cp;
|
|||
|
|
|||
|
tp = find_tree_node(in_dices->ilabel, -1);
|
|||
|
if (!tp)
|
|||
|
break;
|
|||
|
switch (tp->type) {
|
|||
|
case TYPE_INTEGER:
|
|||
|
case TYPE_INTEGER32:
|
|||
|
case TYPE_UINTEGER:
|
|||
|
case TYPE_UNSIGNED32:
|
|||
|
case TYPE_TIMETICKS:
|
|||
|
/*
|
|||
|
* Isolate the next entry
|
|||
|
*/
|
|||
|
cp2 = strchr(cp, '.');
|
|||
|
if (cp2)
|
|||
|
*cp2++ = '\0';
|
|||
|
if (isdigit((unsigned char)(*cp))) {
|
|||
|
subid = strtoul(cp, &ecp, 0);
|
|||
|
if (*ecp)
|
|||
|
goto bad_id;
|
|||
|
} else {
|
|||
|
if (tp->enums) {
|
|||
|
struct enum_list *ep = tp->enums;
|
|||
|
while (ep && strcmp(ep->label, cp))
|
|||
|
ep = ep->next;
|
|||
|
if (!ep)
|
|||
|
goto bad_id;
|
|||
|
subid = ep->value;
|
|||
|
} else
|
|||
|
goto bad_id;
|
|||
|
}
|
|||
|
if (check && tp->ranges) {
|
|||
|
struct range_list *rp = tp->ranges;
|
|||
|
int ok = 0;
|
|||
|
if (tp->type == TYPE_INTEGER ||
|
|||
|
tp->type == TYPE_INTEGER32) {
|
|||
|
while (!ok && rp) {
|
|||
|
if ((rp->low <= (int) subid)
|
|||
|
&& ((int) subid <= rp->high))
|
|||
|
ok = 1;
|
|||
|
else
|
|||
|
rp = rp->next;
|
|||
|
}
|
|||
|
} else { /* check unsigned range */
|
|||
|
while (!ok && rp) {
|
|||
|
if (((unsigned int)rp->low <= subid)
|
|||
|
&& (subid <= (unsigned int)rp->high))
|
|||
|
ok = 1;
|
|||
|
else
|
|||
|
rp = rp->next;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!ok)
|
|||
|
goto bad_id;
|
|||
|
}
|
|||
|
if (*objidlen >= maxlen)
|
|||
|
goto bad_id;
|
|||
|
objid[*objidlen] = subid;
|
|||
|
(*objidlen)++;
|
|||
|
break;
|
|||
|
case TYPE_IPADDR:
|
|||
|
if (*objidlen + 4 > maxlen)
|
|||
|
goto bad_id;
|
|||
|
for (subid = 0; cp && subid < 4; subid++) {
|
|||
|
fcp = cp;
|
|||
|
cp2 = strchr(cp, '.');
|
|||
|
if (cp2)
|
|||
|
*cp2++ = 0;
|
|||
|
objid[*objidlen] = strtoul(cp, &ecp, 0);
|
|||
|
if (*ecp)
|
|||
|
goto bad_id;
|
|||
|
if (check && objid[*objidlen] > 255)
|
|||
|
goto bad_id;
|
|||
|
(*objidlen)++;
|
|||
|
cp = cp2;
|
|||
|
}
|
|||
|
break;
|
|||
|
case TYPE_OCTETSTR:
|
|||
|
if (tp->ranges && !tp->ranges->next
|
|||
|
&& tp->ranges->low == tp->ranges->high)
|
|||
|
len = tp->ranges->low;
|
|||
|
else
|
|||
|
len = -1;
|
|||
|
pos = 0;
|
|||
|
if (*cp == '"' || *cp == '\'') {
|
|||
|
doingquote = *cp++;
|
|||
|
/*
|
|||
|
* insert length if requested
|
|||
|
*/
|
|||
|
if (!in_dices->isimplied && len == -1) {
|
|||
|
if (doingquote == '\'') {
|
|||
|
snmp_set_detail
|
|||
|
("'-quote is for fixed length strings");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
if (*objidlen >= maxlen)
|
|||
|
goto bad_id;
|
|||
|
len_index = *objidlen;
|
|||
|
(*objidlen)++;
|
|||
|
} else if (doingquote == '"') {
|
|||
|
snmp_set_detail
|
|||
|
("\"-quote is for variable length strings");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
cp2 = _apply_escapes(cp, doingquote);
|
|||
|
if (!cp2) goto bad_id;
|
|||
|
else {
|
|||
|
unsigned char *new_val;
|
|||
|
int new_val_len;
|
|||
|
int parsed_hint = 0;
|
|||
|
const char *parsed_value;
|
|||
|
|
|||
|
if (do_hint && tp->hint) {
|
|||
|
parsed_value = parse_octet_hint(tp->hint, cp,
|
|||
|
&new_val, &new_val_len);
|
|||
|
parsed_hint = parsed_value == NULL;
|
|||
|
}
|
|||
|
if (parsed_hint) {
|
|||
|
int i;
|
|||
|
for (i = 0; i < new_val_len; i++) {
|
|||
|
if (*objidlen >= maxlen) goto bad_id;
|
|||
|
objid[ *objidlen ] = new_val[i];
|
|||
|
(*objidlen)++;
|
|||
|
pos++;
|
|||
|
}
|
|||
|
SNMP_FREE(new_val);
|
|||
|
} else {
|
|||
|
while(*cp) {
|
|||
|
if (*objidlen >= maxlen) goto bad_id;
|
|||
|
objid[ *objidlen ] = *cp++;
|
|||
|
(*objidlen)++;
|
|||
|
pos++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
cp2++;
|
|||
|
if (!*cp2)
|
|||
|
cp2 = NULL;
|
|||
|
else if (*cp2 != '.')
|
|||
|
goto bad_id;
|
|||
|
else
|
|||
|
cp2++;
|
|||
|
if (check) {
|
|||
|
if (len == -1) {
|
|||
|
struct range_list *rp = tp->ranges;
|
|||
|
int ok = 0;
|
|||
|
while (rp && !ok)
|
|||
|
if (rp->low <= pos && pos <= rp->high)
|
|||
|
ok = 1;
|
|||
|
else
|
|||
|
rp = rp->next;
|
|||
|
if (!ok)
|
|||
|
goto bad_id;
|
|||
|
if (!in_dices->isimplied)
|
|||
|
objid[len_index] = pos;
|
|||
|
} else if (pos != len)
|
|||
|
goto bad_id;
|
|||
|
}
|
|||
|
else if (len == -1 && !in_dices->isimplied)
|
|||
|
objid[len_index] = pos;
|
|||
|
} else {
|
|||
|
if (!in_dices->isimplied && len == -1) {
|
|||
|
fcp = cp;
|
|||
|
cp2 = strchr(cp, '.');
|
|||
|
if (cp2)
|
|||
|
*cp2++ = 0;
|
|||
|
len = strtoul(cp, &ecp, 0);
|
|||
|
if (*ecp)
|
|||
|
goto bad_id;
|
|||
|
if (*objidlen + len + 1 >= maxlen)
|
|||
|
goto bad_id;
|
|||
|
objid[*objidlen] = len;
|
|||
|
(*objidlen)++;
|
|||
|
cp = cp2;
|
|||
|
}
|
|||
|
while (len && cp) {
|
|||
|
fcp = cp;
|
|||
|
cp2 = strchr(cp, '.');
|
|||
|
if (cp2)
|
|||
|
*cp2++ = 0;
|
|||
|
objid[*objidlen] = strtoul(cp, &ecp, 0);
|
|||
|
if (*ecp)
|
|||
|
goto bad_id;
|
|||
|
if (check && objid[*objidlen] > 255)
|
|||
|
goto bad_id;
|
|||
|
(*objidlen)++;
|
|||
|
len--;
|
|||
|
cp = cp2;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case TYPE_OBJID:
|
|||
|
in_dices = NULL;
|
|||
|
cp2 = cp;
|
|||
|
break;
|
|||
|
case TYPE_NETADDR:
|
|||
|
fcp = cp;
|
|||
|
cp2 = strchr(cp, '.');
|
|||
|
if (cp2)
|
|||
|
*cp2++ = 0;
|
|||
|
subid = strtoul(cp, &ecp, 0);
|
|||
|
if (*ecp)
|
|||
|
goto bad_id;
|
|||
|
if (*objidlen + 1 >= maxlen)
|
|||
|
goto bad_id;
|
|||
|
objid[*objidlen] = subid;
|
|||
|
(*objidlen)++;
|
|||
|
cp = cp2;
|
|||
|
if (subid == 1) {
|
|||
|
for (len = 0; cp && len < 4; len++) {
|
|||
|
fcp = cp;
|
|||
|
cp2 = strchr(cp, '.');
|
|||
|
if (cp2)
|
|||
|
*cp2++ = 0;
|
|||
|
subid = strtoul(cp, &ecp, 0);
|
|||
|
if (*ecp)
|
|||
|
goto bad_id;
|
|||
|
if (*objidlen + 1 >= maxlen)
|
|||
|
goto bad_id;
|
|||
|
if (check && subid > 255)
|
|||
|
goto bad_id;
|
|||
|
objid[*objidlen] = subid;
|
|||
|
(*objidlen)++;
|
|||
|
cp = cp2;
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
in_dices = NULL;
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
snmp_log(LOG_ERR, "Unexpected index type: %d %s %s\n",
|
|||
|
tp->type, in_dices->ilabel, cp);
|
|||
|
in_dices = NULL;
|
|||
|
cp2 = cp;
|
|||
|
break;
|
|||
|
}
|
|||
|
cp = cp2;
|
|||
|
if (in_dices)
|
|||
|
in_dices = in_dices->next;
|
|||
|
}
|
|||
|
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
while (cp) {
|
|||
|
fcp = cp;
|
|||
|
switch (*cp) {
|
|||
|
case '0':
|
|||
|
case '1':
|
|||
|
case '2':
|
|||
|
case '3':
|
|||
|
case '4':
|
|||
|
case '5':
|
|||
|
case '6':
|
|||
|
case '7':
|
|||
|
case '8':
|
|||
|
case '9':
|
|||
|
cp2 = strchr(cp, '.');
|
|||
|
if (cp2)
|
|||
|
*cp2++ = 0;
|
|||
|
subid = strtoul(cp, &ecp, 0);
|
|||
|
if (*ecp)
|
|||
|
goto bad_id;
|
|||
|
if (*objidlen >= maxlen)
|
|||
|
goto bad_id;
|
|||
|
objid[*objidlen] = subid;
|
|||
|
(*objidlen)++;
|
|||
|
break;
|
|||
|
case '"':
|
|||
|
case '\'':
|
|||
|
doingquote = *cp++;
|
|||
|
/*
|
|||
|
* insert length if requested
|
|||
|
*/
|
|||
|
if (doingquote == '"') {
|
|||
|
if (*objidlen >= maxlen)
|
|||
|
goto bad_id;
|
|||
|
objid[*objidlen] = len = strchr(cp, doingquote) - cp;
|
|||
|
(*objidlen)++;
|
|||
|
}
|
|||
|
|
|||
|
while (*cp && *cp != doingquote) {
|
|||
|
if (*objidlen >= maxlen)
|
|||
|
goto bad_id;
|
|||
|
objid[*objidlen] = *cp++;
|
|||
|
(*objidlen)++;
|
|||
|
}
|
|||
|
cp2 = cp + 1;
|
|||
|
if (!*cp2)
|
|||
|
cp2 = NULL;
|
|||
|
else if (*cp2 == '.')
|
|||
|
cp2++;
|
|||
|
else
|
|||
|
goto bad_id;
|
|||
|
break;
|
|||
|
default:
|
|||
|
goto bad_id;
|
|||
|
}
|
|||
|
cp = cp2;
|
|||
|
}
|
|||
|
return 1;
|
|||
|
|
|||
|
bad_id:
|
|||
|
{
|
|||
|
char buf[256];
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
if (in_dices)
|
|||
|
snprintf(buf, sizeof(buf), "Index out of range: %s (%s)",
|
|||
|
fcp, in_dices->ilabel);
|
|||
|
else if (tp)
|
|||
|
snprintf(buf, sizeof(buf), "Sub-id not found: %s -> %s", tp->label, fcp);
|
|||
|
else
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
snprintf(buf, sizeof(buf), "%s", fcp);
|
|||
|
buf[ sizeof(buf)-1 ] = 0;
|
|||
|
|
|||
|
snmp_set_detail(buf);
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
/**
|
|||
|
* @see comments on find_best_tree_node for usage after first time.
|
|||
|
*/
|
|||
|
int
|
|||
|
get_wild_node(const char *name, oid * objid, size_t * objidlen)
|
|||
|
{
|
|||
|
struct tree *tp = find_best_tree_node(name, tree_head, NULL);
|
|||
|
if (!tp)
|
|||
|
return 0;
|
|||
|
return get_node(tp->label, objid, objidlen);
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
get_node(const char *name, oid * objid, size_t * objidlen)
|
|||
|
{
|
|||
|
const char *cp;
|
|||
|
char ch;
|
|||
|
int res;
|
|||
|
|
|||
|
cp = name;
|
|||
|
while ((ch = *cp))
|
|||
|
if (('0' <= ch && ch <= '9')
|
|||
|
|| ('a' <= ch && ch <= 'z')
|
|||
|
|| ('A' <= ch && ch <= 'Z')
|
|||
|
|| ch == '-')
|
|||
|
cp++;
|
|||
|
else
|
|||
|
break;
|
|||
|
if (ch != ':')
|
|||
|
if (*name == '.')
|
|||
|
res = get_module_node(name + 1, "ANY", objid, objidlen);
|
|||
|
else
|
|||
|
res = get_module_node(name, "ANY", objid, objidlen);
|
|||
|
else {
|
|||
|
char *module;
|
|||
|
/*
|
|||
|
* requested name is of the form
|
|||
|
* "module:subidentifier"
|
|||
|
*/
|
|||
|
module = (char *) malloc((size_t) (cp - name + 1));
|
|||
|
if (!module)
|
|||
|
return SNMPERR_GENERR;
|
|||
|
sprintf(module, "%.*s", (int) (cp - name), name);
|
|||
|
cp++; /* cp now point to the subidentifier */
|
|||
|
if (*cp == ':')
|
|||
|
cp++;
|
|||
|
|
|||
|
/*
|
|||
|
* 'cp' and 'name' *do* go that way round!
|
|||
|
*/
|
|||
|
res = get_module_node(cp, module, objid, objidlen);
|
|||
|
SNMP_FREE(module);
|
|||
|
}
|
|||
|
if (res == 0) {
|
|||
|
SET_SNMP_ERROR(SNMPERR_UNKNOWN_OBJID);
|
|||
|
}
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
|
|||
|
#ifdef testing
|
|||
|
|
|||
|
main(int argc, char *argv[])
|
|||
|
{
|
|||
|
oid objid[MAX_OID_LEN];
|
|||
|
int objidlen = MAX_OID_LEN;
|
|||
|
int count;
|
|||
|
netsnmp_variable_list variable;
|
|||
|
|
|||
|
netsnmp_init_mib();
|
|||
|
if (argc < 2)
|
|||
|
print_subtree(stdout, tree_head, 0);
|
|||
|
variable.type = ASN_INTEGER;
|
|||
|
variable.val.integer = 3;
|
|||
|
variable.val_len = 4;
|
|||
|
for (argc--; argc; argc--, argv++) {
|
|||
|
objidlen = MAX_OID_LEN;
|
|||
|
printf("read_objid(%s) = %d\n",
|
|||
|
argv[1], read_objid(argv[1], objid, &objidlen));
|
|||
|
for (count = 0; count < objidlen; count++)
|
|||
|
printf("%d.", objid[count]);
|
|||
|
printf("\n");
|
|||
|
print_variable(objid, objidlen, &variable);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif /* testing */
|
|||
|
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
/*
|
|||
|
* initialize: no peers included in the report.
|
|||
|
*/
|
|||
|
void
|
|||
|
clear_tree_flags(register struct tree *tp)
|
|||
|
{
|
|||
|
for (; tp; tp = tp->next_peer) {
|
|||
|
tp->reported = 0;
|
|||
|
if (tp->child_list)
|
|||
|
clear_tree_flags(tp->child_list);
|
|||
|
/*RECURSE*/}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Update: 1998-07-17 <jhy@gsu.edu>
|
|||
|
* Added print_oid_report* functions.
|
|||
|
*/
|
|||
|
static int print_subtree_oid_report_labeledoid = 0;
|
|||
|
static int print_subtree_oid_report_oid = 0;
|
|||
|
static int print_subtree_oid_report_symbolic = 0;
|
|||
|
static int print_subtree_oid_report_mibchildoid = 0;
|
|||
|
static int print_subtree_oid_report_suffix = 0;
|
|||
|
|
|||
|
/*
|
|||
|
* These methods recurse.
|
|||
|
*/
|
|||
|
static void print_parent_labeledoid(FILE *, struct tree *);
|
|||
|
static void print_parent_oid(FILE *, struct tree *);
|
|||
|
static void print_parent_mibchildoid(FILE *, struct tree *);
|
|||
|
static void print_parent_label(FILE *, struct tree *);
|
|||
|
static void print_subtree_oid_report(FILE *, struct tree *, int);
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
print_oid_report(FILE * fp)
|
|||
|
{
|
|||
|
struct tree *tp;
|
|||
|
clear_tree_flags(tree_head);
|
|||
|
for (tp = tree_head; tp; tp = tp->next_peer)
|
|||
|
print_subtree_oid_report(fp, tp, 0);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
print_oid_report_enable_labeledoid(void)
|
|||
|
{
|
|||
|
print_subtree_oid_report_labeledoid = 1;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
print_oid_report_enable_oid(void)
|
|||
|
{
|
|||
|
print_subtree_oid_report_oid = 1;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
print_oid_report_enable_suffix(void)
|
|||
|
{
|
|||
|
print_subtree_oid_report_suffix = 1;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
print_oid_report_enable_symbolic(void)
|
|||
|
{
|
|||
|
print_subtree_oid_report_symbolic = 1;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
print_oid_report_enable_mibchildoid(void)
|
|||
|
{
|
|||
|
print_subtree_oid_report_mibchildoid = 1;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* helper methods for print_subtree_oid_report()
|
|||
|
* each one traverses back up the node tree
|
|||
|
* until there is no parent. Then, the label combination
|
|||
|
* is output, such that the parent is displayed first.
|
|||
|
*
|
|||
|
* Warning: these methods are all recursive.
|
|||
|
*/
|
|||
|
|
|||
|
static void
|
|||
|
print_parent_labeledoid(FILE * f, struct tree *tp)
|
|||
|
{
|
|||
|
if (tp) {
|
|||
|
if (tp->parent) {
|
|||
|
print_parent_labeledoid(f, tp->parent);
|
|||
|
/*RECURSE*/}
|
|||
|
fprintf(f, ".%s(%lu)", tp->label, tp->subid);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
print_parent_oid(FILE * f, struct tree *tp)
|
|||
|
{
|
|||
|
if (tp) {
|
|||
|
if (tp->parent) {
|
|||
|
print_parent_oid(f, tp->parent);
|
|||
|
/*RECURSE*/}
|
|||
|
fprintf(f, ".%lu", tp->subid);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static void print_parent_mibchildoid(FILE * f, struct tree *tp)
|
|||
|
{
|
|||
|
static struct tree *temp;
|
|||
|
unsigned long elems[100];
|
|||
|
int elem_cnt = 0;
|
|||
|
int i = 0;
|
|||
|
temp = tp;
|
|||
|
if (temp) {
|
|||
|
while (temp->parent) {
|
|||
|
elems[elem_cnt++] = temp->subid;
|
|||
|
temp = temp->parent;
|
|||
|
}
|
|||
|
elems[elem_cnt++] = temp->subid;
|
|||
|
}
|
|||
|
for (i = elem_cnt - 1; i >= 0; i--) {
|
|||
|
if (i == elem_cnt - 1) {
|
|||
|
fprintf(f, "%lu", elems[i]);
|
|||
|
} else {
|
|||
|
fprintf(f, ".%lu", elems[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
print_parent_label(FILE * f, struct tree *tp)
|
|||
|
{
|
|||
|
if (tp) {
|
|||
|
if (tp->parent) {
|
|||
|
print_parent_label(f, tp->parent);
|
|||
|
/*RECURSE*/}
|
|||
|
fprintf(f, ".%s", tp->label);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @internal
|
|||
|
* This methods generates variations on the original print_subtree() report.
|
|||
|
* Traverse the tree depth first, from least to greatest sub-identifier.
|
|||
|
* Warning: this methods recurses and calls methods that recurse.
|
|||
|
*
|
|||
|
* @param f File descriptor to print to.
|
|||
|
* @param tree ???
|
|||
|
* @param count ???
|
|||
|
*/
|
|||
|
|
|||
|
static void
|
|||
|
print_subtree_oid_report(FILE * f, struct tree *tree, int count)
|
|||
|
{
|
|||
|
struct tree *tp;
|
|||
|
|
|||
|
count++;
|
|||
|
|
|||
|
/*
|
|||
|
* sanity check
|
|||
|
*/
|
|||
|
if (!tree) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* find the not reported peer with the lowest sub-identifier.
|
|||
|
* if no more, break the loop and cleanup.
|
|||
|
* set "reported" flag, and create report for this peer.
|
|||
|
* recurse using the children of this peer, if any.
|
|||
|
*/
|
|||
|
while (1) {
|
|||
|
register struct tree *ntp;
|
|||
|
|
|||
|
tp = NULL;
|
|||
|
for (ntp = tree->child_list; ntp; ntp = ntp->next_peer) {
|
|||
|
if (ntp->reported)
|
|||
|
continue;
|
|||
|
|
|||
|
if (!tp || (tp->subid > ntp->subid))
|
|||
|
tp = ntp;
|
|||
|
}
|
|||
|
if (!tp)
|
|||
|
break;
|
|||
|
|
|||
|
tp->reported = 1;
|
|||
|
|
|||
|
if (print_subtree_oid_report_labeledoid) {
|
|||
|
print_parent_labeledoid(f, tp);
|
|||
|
fprintf(f, "\n");
|
|||
|
}
|
|||
|
if (print_subtree_oid_report_oid) {
|
|||
|
print_parent_oid(f, tp);
|
|||
|
fprintf(f, "\n");
|
|||
|
}
|
|||
|
if (print_subtree_oid_report_symbolic) {
|
|||
|
print_parent_label(f, tp);
|
|||
|
fprintf(f, "\n");
|
|||
|
}
|
|||
|
if (print_subtree_oid_report_mibchildoid) {
|
|||
|
fprintf(f, "\"%s\"\t", tp->label);
|
|||
|
fprintf(f, "\t\t\"");
|
|||
|
print_parent_mibchildoid(f, tp);
|
|||
|
fprintf(f, "\"\n");
|
|||
|
}
|
|||
|
if (print_subtree_oid_report_suffix) {
|
|||
|
int i;
|
|||
|
for (i = 0; i < count; i++)
|
|||
|
fprintf(f, " ");
|
|||
|
fprintf(f, "%s(%ld) type=%d", tp->label, tp->subid, tp->type);
|
|||
|
if (tp->tc_index != -1)
|
|||
|
fprintf(f, " tc=%d", tp->tc_index);
|
|||
|
if (tp->hint)
|
|||
|
fprintf(f, " hint=%s", tp->hint);
|
|||
|
if (tp->units)
|
|||
|
fprintf(f, " units=%s", tp->units);
|
|||
|
|
|||
|
fprintf(f, "\n");
|
|||
|
}
|
|||
|
print_subtree_oid_report(f, tp, count);
|
|||
|
/*RECURSE*/}
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* 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
|
|||
|
*
|
|||
|
* @see uptimeString
|
|||
|
*/
|
|||
|
char *
|
|||
|
uptime_string(u_long timeticks, char *buf)
|
|||
|
{
|
|||
|
return uptime_string_n( timeticks, buf, 40);
|
|||
|
}
|
|||
|
|
|||
|
char *
|
|||
|
uptime_string_n(u_long timeticks, char *buf, size_t buflen)
|
|||
|
{
|
|||
|
uptimeString(timeticks, buf, buflen);
|
|||
|
return buf;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Given a string, parses an oid out of it (if possible).
|
|||
|
* It will try to parse it based on predetermined configuration if
|
|||
|
* present or by every method possible otherwise.
|
|||
|
* If a suffix has been registered using NETSNMP_DS_LIB_OIDSUFFIX, it
|
|||
|
* will be appended to the input string before processing.
|
|||
|
*
|
|||
|
* @param argv The OID to string parse
|
|||
|
* @param root An OID array where the results are stored.
|
|||
|
* @param rootlen The max length of the array going in and the data
|
|||
|
* length coming out.
|
|||
|
*
|
|||
|
* @return The root oid pointer if successful, or NULL otherwise.
|
|||
|
*/
|
|||
|
|
|||
|
oid *
|
|||
|
snmp_parse_oid(const char *argv, oid * root, size_t * rootlen)
|
|||
|
{
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
size_t savlen = *rootlen;
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
static size_t tmpbuf_len = 0;
|
|||
|
static char *tmpbuf = NULL;
|
|||
|
const char *suffix, *prefix;
|
|||
|
|
|||
|
suffix = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
|
|||
|
NETSNMP_DS_LIB_OIDSUFFIX);
|
|||
|
prefix = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
|
|||
|
NETSNMP_DS_LIB_OIDPREFIX);
|
|||
|
if ((suffix && suffix[0]) || (prefix && prefix[0])) {
|
|||
|
if (!suffix)
|
|||
|
suffix = "";
|
|||
|
if (!prefix)
|
|||
|
prefix = "";
|
|||
|
if ((strlen(suffix) + strlen(prefix) + strlen(argv) + 2) > tmpbuf_len) {
|
|||
|
tmpbuf_len = strlen(suffix) + strlen(argv) + strlen(prefix) + 2;
|
|||
|
tmpbuf = malloc(tmpbuf_len);
|
|||
|
}
|
|||
|
snprintf(tmpbuf, tmpbuf_len, "%s%s%s%s", prefix, argv,
|
|||
|
((suffix[0] == '.' || suffix[0] == '\0') ? "" : "."),
|
|||
|
suffix);
|
|||
|
argv = tmpbuf;
|
|||
|
DEBUGMSGTL(("snmp_parse_oid","Parsing: %s\n",argv));
|
|||
|
}
|
|||
|
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS)
|
|||
|
|| strchr(argv, ':')) {
|
|||
|
if (get_node(argv, root, rootlen)) {
|
|||
|
free(tmpbuf);
|
|||
|
return root;
|
|||
|
}
|
|||
|
} else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REGEX_ACCESS)) {
|
|||
|
clear_tree_flags(tree_head);
|
|||
|
if (get_wild_node(argv, root, rootlen)) {
|
|||
|
free(tmpbuf);
|
|||
|
return root;
|
|||
|
}
|
|||
|
} else {
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
if (read_objid(argv, root, rootlen)) {
|
|||
|
free(tmpbuf);
|
|||
|
return root;
|
|||
|
}
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
*rootlen = savlen;
|
|||
|
if (get_node(argv, root, rootlen)) {
|
|||
|
free(tmpbuf);
|
|||
|
return root;
|
|||
|
}
|
|||
|
*rootlen = savlen;
|
|||
|
DEBUGMSGTL(("parse_oid", "wildly parsing\n"));
|
|||
|
clear_tree_flags(tree_head);
|
|||
|
if (get_wild_node(argv, root, rootlen)) {
|
|||
|
free(tmpbuf);
|
|||
|
return root;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
free(tmpbuf);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
#ifndef NETSNMP_DISABLE_MIB_LOADING
|
|||
|
/*
|
|||
|
* Use DISPLAY-HINT to parse a value into an octet string.
|
|||
|
*
|
|||
|
* note that "1d1d", "11" could have come from an octet string that
|
|||
|
* looked like { 1, 1 } or an octet string that looked like { 11 }
|
|||
|
* because of this, it's doubtful that anyone would use such a display
|
|||
|
* string. Therefore, the parser ignores this case.
|
|||
|
*/
|
|||
|
|
|||
|
struct parse_hints {
|
|||
|
int length;
|
|||
|
int repeat;
|
|||
|
int format;
|
|||
|
int separator;
|
|||
|
int terminator;
|
|||
|
unsigned char *result;
|
|||
|
int result_max;
|
|||
|
int result_len;
|
|||
|
};
|
|||
|
|
|||
|
static void parse_hints_reset(struct parse_hints *ph)
|
|||
|
{
|
|||
|
ph->length = 0;
|
|||
|
ph->repeat = 0;
|
|||
|
ph->format = 0;
|
|||
|
ph->separator = 0;
|
|||
|
ph->terminator = 0;
|
|||
|
}
|
|||
|
|
|||
|
static void parse_hints_ctor(struct parse_hints *ph)
|
|||
|
{
|
|||
|
parse_hints_reset(ph);
|
|||
|
ph->result = NULL;
|
|||
|
ph->result_max = 0;
|
|||
|
ph->result_len = 0;
|
|||
|
}
|
|||
|
|
|||
|
static int parse_hints_add_result_octet(struct parse_hints *ph, unsigned char octet)
|
|||
|
{
|
|||
|
if (!(ph->result_len < ph->result_max)) {
|
|||
|
ph->result_max = ph->result_len + 32;
|
|||
|
if (!ph->result) {
|
|||
|
ph->result = (unsigned char *)malloc(ph->result_max);
|
|||
|
} else {
|
|||
|
ph->result = (unsigned char *)realloc(ph->result, ph->result_max);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!ph->result) {
|
|||
|
return 0; /* failed */
|
|||
|
}
|
|||
|
|
|||
|
ph->result[ph->result_len++] = octet;
|
|||
|
return 1; /* success */
|
|||
|
}
|
|||
|
|
|||
|
static int parse_hints_parse(struct parse_hints *ph, const char **v_in_out)
|
|||
|
{
|
|||
|
const char *v = *v_in_out;
|
|||
|
char *nv;
|
|||
|
int base;
|
|||
|
int repeats = 0;
|
|||
|
int repeat_fixup = ph->result_len;
|
|||
|
|
|||
|
if (ph->repeat) {
|
|||
|
if (!parse_hints_add_result_octet(ph, 0)) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
do {
|
|||
|
base = 0;
|
|||
|
switch (ph->format) {
|
|||
|
case 'x': base += 6; /* fall through */
|
|||
|
case 'd': base += 2; /* fall through */
|
|||
|
case 'o': base += 8; /* fall through */
|
|||
|
{
|
|||
|
int i;
|
|||
|
unsigned long number = strtol(v, &nv, base);
|
|||
|
if (nv == v) return 0;
|
|||
|
v = nv;
|
|||
|
for (i = 0; i < ph->length; i++) {
|
|||
|
int shift = 8 * (ph->length - 1 - i);
|
|||
|
if (!parse_hints_add_result_octet(ph, (u_char)(number >> shift) )) {
|
|||
|
return 0; /* failed */
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 'a':
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
for (i = 0; i < ph->length && *v; i++) {
|
|||
|
if (!parse_hints_add_result_octet(ph, *v++)) {
|
|||
|
return 0; /* failed */
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
repeats++;
|
|||
|
|
|||
|
if (ph->separator && *v) {
|
|||
|
if (*v == ph->separator) {
|
|||
|
v++;
|
|||
|
} else {
|
|||
|
return 0; /* failed */
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (ph->terminator) {
|
|||
|
if (*v == ph->terminator) {
|
|||
|
v++;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
} while (ph->repeat && *v);
|
|||
|
if (ph->repeat) {
|
|||
|
ph->result[repeat_fixup] = repeats;
|
|||
|
}
|
|||
|
|
|||
|
*v_in_out = v;
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
static void parse_hints_length_add_digit(struct parse_hints *ph, int digit)
|
|||
|
{
|
|||
|
ph->length *= 10;
|
|||
|
ph->length += digit - '0';
|
|||
|
}
|
|||
|
|
|||
|
const char *parse_octet_hint(const char *hint, const char *value, unsigned char **new_val, int *new_val_len)
|
|||
|
{
|
|||
|
const char *h = hint;
|
|||
|
const char *v = value;
|
|||
|
struct parse_hints ph;
|
|||
|
int retval = 1;
|
|||
|
/* See RFC 1443 */
|
|||
|
enum {
|
|||
|
HINT_1_2,
|
|||
|
HINT_2_3,
|
|||
|
HINT_1_2_4,
|
|||
|
HINT_1_2_5
|
|||
|
} state = HINT_1_2;
|
|||
|
|
|||
|
parse_hints_ctor(&ph);
|
|||
|
while (*h && *v && retval) {
|
|||
|
switch (state) {
|
|||
|
case HINT_1_2:
|
|||
|
if ('*' == *h) {
|
|||
|
ph.repeat = 1;
|
|||
|
state = HINT_2_3;
|
|||
|
} else if (isdigit((unsigned char)(*h))) {
|
|||
|
parse_hints_length_add_digit(&ph, *h);
|
|||
|
state = HINT_2_3;
|
|||
|
} else {
|
|||
|
return v; /* failed */
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case HINT_2_3:
|
|||
|
if (isdigit((unsigned char)(*h))) {
|
|||
|
parse_hints_length_add_digit(&ph, *h);
|
|||
|
/* state = HINT_2_3 */
|
|||
|
} else if ('x' == *h || 'd' == *h || 'o' == *h || 'a' == *h) {
|
|||
|
ph.format = *h;
|
|||
|
state = HINT_1_2_4;
|
|||
|
} else {
|
|||
|
return v; /* failed */
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case HINT_1_2_4:
|
|||
|
if ('*' == *h) {
|
|||
|
retval = parse_hints_parse(&ph, &v);
|
|||
|
parse_hints_reset(&ph);
|
|||
|
|
|||
|
ph.repeat = 1;
|
|||
|
state = HINT_2_3;
|
|||
|
} else if (isdigit((unsigned char)(*h))) {
|
|||
|
retval = parse_hints_parse(&ph, &v);
|
|||
|
parse_hints_reset(&ph);
|
|||
|
|
|||
|
parse_hints_length_add_digit(&ph, *h);
|
|||
|
state = HINT_2_3;
|
|||
|
} else {
|
|||
|
ph.separator = *h;
|
|||
|
state = HINT_1_2_5;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case HINT_1_2_5:
|
|||
|
if ('*' == *h) {
|
|||
|
retval = parse_hints_parse(&ph, &v);
|
|||
|
parse_hints_reset(&ph);
|
|||
|
|
|||
|
ph.repeat = 1;
|
|||
|
state = HINT_2_3;
|
|||
|
} else if (isdigit((unsigned char)(*h))) {
|
|||
|
retval = parse_hints_parse(&ph, &v);
|
|||
|
parse_hints_reset(&ph);
|
|||
|
|
|||
|
parse_hints_length_add_digit(&ph, *h);
|
|||
|
state = HINT_2_3;
|
|||
|
} else {
|
|||
|
ph.terminator = *h;
|
|||
|
|
|||
|
retval = parse_hints_parse(&ph, &v);
|
|||
|
parse_hints_reset(&ph);
|
|||
|
|
|||
|
state = HINT_1_2;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
h++;
|
|||
|
}
|
|||
|
while (*v && retval) {
|
|||
|
retval = parse_hints_parse(&ph, &v);
|
|||
|
}
|
|||
|
if (retval) {
|
|||
|
*new_val = ph.result;
|
|||
|
*new_val_len = ph.result_len;
|
|||
|
} else {
|
|||
|
if (ph.result) {
|
|||
|
SNMP_FREE(ph.result);
|
|||
|
}
|
|||
|
*new_val = NULL;
|
|||
|
*new_val_len = 0;
|
|||
|
}
|
|||
|
return retval ? NULL : v;
|
|||
|
}
|
|||
|
#endif /* NETSNMP_DISABLE_MIB_LOADING */
|
|||
|
|
|||
|
#ifdef test_display_hint
|
|||
|
|
|||
|
int main(int argc, const char **argv)
|
|||
|
{
|
|||
|
const char *hint;
|
|||
|
const char *value;
|
|||
|
unsigned char *new_val;
|
|||
|
int new_val_len;
|
|||
|
char *r;
|
|||
|
|
|||
|
if (argc < 3) {
|
|||
|
fprintf(stderr, "usage: dh <hint> <value>\n");
|
|||
|
exit(2);
|
|||
|
}
|
|||
|
hint = argv[1];
|
|||
|
value = argv[2];
|
|||
|
r = parse_octet_hint(hint, value, &new_val, &new_val_len);
|
|||
|
printf("{\"%s\", \"%s\"}: \n\t", hint, value);
|
|||
|
if (r) {
|
|||
|
*r = 0;
|
|||
|
printf("returned failed\n");
|
|||
|
printf("value syntax error at: %s\n", value);
|
|||
|
}
|
|||
|
else {
|
|||
|
int i;
|
|||
|
printf("returned success\n");
|
|||
|
for (i = 0; i < new_val_len; i++) {
|
|||
|
int c = new_val[i] & 0xFF;
|
|||
|
printf("%02X(%c) ", c, isprint(c) ? c : ' ');
|
|||
|
}
|
|||
|
SNMP_FREE(new_val);
|
|||
|
}
|
|||
|
printf("\n");
|
|||
|
exit(0);
|
|||
|
}
|
|||
|
|
|||
|
#endif /* test_display_hint */
|
|||
|
|
|||
|
#ifndef NETSNMP_FEATURE_REMOVE_MIB_TO_ASN_TYPE
|
|||
|
u_char
|
|||
|
mib_to_asn_type(int mib_type)
|
|||
|
{
|
|||
|
switch (mib_type) {
|
|||
|
case TYPE_OBJID:
|
|||
|
return ASN_OBJECT_ID;
|
|||
|
|
|||
|
case TYPE_OCTETSTR:
|
|||
|
return ASN_OCTET_STR;
|
|||
|
|
|||
|
case TYPE_NETADDR:
|
|||
|
case TYPE_IPADDR:
|
|||
|
return ASN_IPADDRESS;
|
|||
|
|
|||
|
case TYPE_INTEGER32:
|
|||
|
case TYPE_INTEGER:
|
|||
|
return ASN_INTEGER;
|
|||
|
|
|||
|
case TYPE_COUNTER:
|
|||
|
return ASN_COUNTER;
|
|||
|
|
|||
|
case TYPE_GAUGE:
|
|||
|
return ASN_GAUGE;
|
|||
|
|
|||
|
case TYPE_TIMETICKS:
|
|||
|
return ASN_TIMETICKS;
|
|||
|
|
|||
|
case TYPE_OPAQUE:
|
|||
|
return ASN_OPAQUE;
|
|||
|
|
|||
|
case TYPE_NULL:
|
|||
|
return ASN_NULL;
|
|||
|
|
|||
|
case TYPE_COUNTER64:
|
|||
|
return ASN_COUNTER64;
|
|||
|
|
|||
|
case TYPE_BITSTRING:
|
|||
|
return ASN_BIT_STR;
|
|||
|
|
|||
|
case TYPE_UINTEGER:
|
|||
|
case TYPE_UNSIGNED32:
|
|||
|
return ASN_UNSIGNED;
|
|||
|
|
|||
|
case TYPE_NSAPADDRESS:
|
|||
|
return ASN_NSAP;
|
|||
|
|
|||
|
}
|
|||
|
return -1;
|
|||
|
}
|
|||
|
#endif /* NETSNMP_FEATURE_REMOVE_MIB_TO_ASN_TYPE */
|
|||
|
|
|||
|
/**
|
|||
|
* Converts a string to its OID form.
|
|||
|
* in example "hello" = 5 . 'h' . 'e' . 'l' . 'l' . 'o'
|
|||
|
*
|
|||
|
* @param S The string.
|
|||
|
* @param O The oid.
|
|||
|
* @param L The length of the oid.
|
|||
|
*
|
|||
|
* @return 0 on Sucess, 1 on failure.
|
|||
|
*/
|
|||
|
#ifndef NETSNMP_FEATURE_REMOVE_MIB_STRING_CONVERSIONS
|
|||
|
int
|
|||
|
netsnmp_str2oid(const char *S, oid * O, int L)
|
|||
|
{
|
|||
|
const char *c = S;
|
|||
|
oid *o = &O[1];
|
|||
|
|
|||
|
--L; /* leave room for length prefix */
|
|||
|
|
|||
|
for (; *c && L; --L, ++o, ++c)
|
|||
|
*o = *c;
|
|||
|
|
|||
|
/*
|
|||
|
* make sure we got to the end of the string
|
|||
|
*/
|
|||
|
if (*c != 0)
|
|||
|
return 1;
|
|||
|
|
|||
|
/*
|
|||
|
* set the length of the oid
|
|||
|
*/
|
|||
|
*O = c - S;
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Converts an OID to its character form.
|
|||
|
* in example 5 . 1 . 2 . 3 . 4 . 5 = 12345
|
|||
|
*
|
|||
|
* @param C The character buffer.
|
|||
|
* @param L The length of the buffer.
|
|||
|
* @param O The oid.
|
|||
|
*
|
|||
|
* @return 0 on Sucess, 1 on failure.
|
|||
|
*/
|
|||
|
int
|
|||
|
netsnmp_oid2chars(char *C, int L, const oid * O)
|
|||
|
{
|
|||
|
char *c = C;
|
|||
|
const oid *o = &O[1];
|
|||
|
|
|||
|
if (L < (int)*O)
|
|||
|
return 1;
|
|||
|
|
|||
|
L = *O; /** length */
|
|||
|
for (; L; --L, ++o, ++c) {
|
|||
|
if (*o > 0xFF)
|
|||
|
return 1;
|
|||
|
*c = (char)*o;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Converts an OID to its string form.
|
|||
|
* in example 5 . 'h' . 'e' . 'l' . 'l' . 'o' = "hello\0" (null terminated)
|
|||
|
*
|
|||
|
* @param S The character string buffer.
|
|||
|
* @param L The length of the string buffer.
|
|||
|
* @param O The oid.
|
|||
|
*
|
|||
|
* @return 0 on Sucess, 1 on failure.
|
|||
|
*/
|
|||
|
int
|
|||
|
netsnmp_oid2str(char *S, int L, oid * O)
|
|||
|
{
|
|||
|
int rc;
|
|||
|
|
|||
|
if (L <= (int)*O)
|
|||
|
return 1;
|
|||
|
|
|||
|
rc = netsnmp_oid2chars(S, L, O);
|
|||
|
if (rc)
|
|||
|
return 1;
|
|||
|
|
|||
|
S[ *O ] = 0;
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
#endif /* NETSNMP_FEATURE_REMOVE_MIB_STRING_CONVERSIONS */
|
|||
|
|
|||
|
|
|||
|
#ifndef NETSNMP_FEATURE_REMOVE_MIB_SNPRINT
|
|||
|
int
|
|||
|
snprint_by_type(char *buf, size_t buf_len,
|
|||
|
netsnmp_variable_list * var,
|
|||
|
const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_by_type((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_hexstring(char *buf, size_t buf_len, const u_char * cp, size_t len)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_hexstring((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
cp, len))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_asciistring(char *buf, size_t buf_len,
|
|||
|
const u_char * cp, size_t len)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_asciistring
|
|||
|
((u_char **) & buf, &buf_len, &out_len, 0, cp, len))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_octet_string(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_octet_string
|
|||
|
((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint,
|
|||
|
units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_opaque(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_opaque((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_object_identifier(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var,
|
|||
|
const struct enum_list *enums, const char *hint,
|
|||
|
const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_object_identifier
|
|||
|
((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint,
|
|||
|
units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_timeticks(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_timeticks((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_hinted_integer(char *buf, size_t buf_len,
|
|||
|
long val, const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_hinted_integer
|
|||
|
((u_char **) & buf, &buf_len, &out_len, 0, val, 'd', hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_integer(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_integer((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_uinteger(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_uinteger((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_gauge(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_gauge((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_counter(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_counter((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_networkaddress(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var,
|
|||
|
const struct enum_list *enums, const char *hint,
|
|||
|
const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_networkaddress
|
|||
|
((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint,
|
|||
|
units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_ipaddress(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_ipaddress((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_null(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_null((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_bitstring(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_bitstring((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_nsapaddress(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_nsapaddress
|
|||
|
((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint,
|
|||
|
units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_counter64(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_counter64((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_badtype(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_badtype((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
|
|||
|
int
|
|||
|
snprint_float(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_float((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
snprint_double(char *buf, size_t buf_len,
|
|||
|
const netsnmp_variable_list * var, const struct enum_list *enums,
|
|||
|
const char *hint, const char *units)
|
|||
|
{
|
|||
|
size_t out_len = 0;
|
|||
|
if (sprint_realloc_double((u_char **) & buf, &buf_len, &out_len, 0,
|
|||
|
var, enums, hint, units))
|
|||
|
return (int) out_len;
|
|||
|
else
|
|||
|
return -1;
|
|||
|
}
|
|||
|
#endif
|
|||
|
#endif /* NETSNMP_FEATURE_REMOVE_MIB_SNPRINT */
|
|||
|
/** @} */
|
|||
|
|