| /* |
| * mib.c |
| * |
| * $Id$ |
| * |
| * Update: 1998-07-17 <jhy@gsu.edu> |
| * Added print_oid_report* functions. |
| * |
| */ |
| /* Portions of this file are subject to the following copyrights. See |
| * the Net-SNMP's COPYING file for more details and other copyrights |
| * that may apply: |
| */ |
| /********************************************************************** |
| Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University |
| |
| All Rights Reserved |
| |
| Permission to use, copy, modify, and distribute this software and its |
| documentation for any purpose and without fee is hereby granted, |
| provided that the above copyright notice appear in all copies and that |
| both that copyright notice and this permission notice appear in |
| supporting documentation, and that the name of CMU not be |
| used in advertising or publicity pertaining to distribution of the |
| software without specific, written prior permission. |
| |
| CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING |
| ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL |
| CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR |
| ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
| WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
| ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
| SOFTWARE. |
| ******************************************************************/ |
| /* |
| * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms specified in the COPYING file |
| * distributed with the Net-SNMP package. |
| */ |
| #include <net-snmp/net-snmp-config.h> |
| |
| #include <stdio.h> |
| #include <ctype.h> |
| #include <sys/types.h> |
| #if HAVE_NETINET_IN_H |
| #include <netinet/in.h> |
| #endif |
| #if TIME_WITH_SYS_TIME |
| # ifdef WIN32 |
| # include <sys/timeb.h> |
| # else |
| # include <sys/time.h> |
| # endif |
| # 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_WINSOCK_H |
| #include <winsock.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> |
| |
| /** @defgroup mib_utilities mib parsing and datatype manipulation routines. |
| * @ingroup library |
| * |
| * @{ |
| */ |
| |
| static char *uptimeString(u_long, char *, size_t); |
| |
| static struct tree *_get_realloc_symbol(const oid * objid, size_t objidlen, |
| struct tree *subtree, |
| u_char ** buf, size_t * buf_len, |
| size_t * out_len, |
| int allow_realloc, |
| int *buf_overflow, |
| struct index_list *in_dices, |
| size_t * end_of_known); |
| |
| static int print_tree_node(u_char ** buf, size_t * buf_len, |
| size_t * out_len, int allow_realloc, |
| struct tree *tp, int width); |
| static void handle_mibdirs_conf(const char *token, char *line); |
| static void handle_mibs_conf(const char *token, char *line); |
| static void handle_mibfile_conf(const char *token, char *line); |
| |
| static void _oid_finish_printing(const oid * objid, size_t objidlen, |
| u_char ** buf, size_t * buf_len, |
| size_t * out_len, |
| int allow_realloc, int *buf_overflow); |
| |
| /* |
| * helper functions for get_module_node |
| */ |
| static int node_to_oid(struct tree *, oid *, size_t *); |
| #ifndef NETSNMP_DISABLE_MIB_LOADING |
| static int _add_strings_to_oid(struct tree *, char *, |
| oid *, size_t *, size_t); |
| #else |
| static int _add_strings_to_oid(void *, char *, |
| oid *, size_t *, size_t); |
| #endif /* NETSNMP_DISABLE_MIB_LOADING */ |
| |
| #ifndef NETSNMP_DISABLE_MIB_LOADING |
| extern struct tree *tree_head; |
| static struct tree *tree_top; |
| |
| struct tree *Mib; /* Backwards compatibility */ |
| #endif /* NETSNMP_DISABLE_MIB_LOADING */ |
| |
| oid RFC1213_MIB[] = { 1, 3, 6, 1, 2, 1 }; |
| static char Standard_Prefix[] = ".1.3.6.1.2.1"; |
| |
| /* |
| * Set default here as some uses of read_objid require valid pointer. |
| */ |
| static char *Prefix = &Standard_Prefix[0]; |
| typedef struct _PrefixList { |
| const char *str; |
| int len; |
| } *PrefixListPtr, PrefixList; |
| |
| /* |
| * Here are the prefix strings. |
| * Note that the first one finds the value of Prefix or Standard_Prefix. |
| * Any of these MAY start with period; all will NOT end with period. |
| * Period is added where needed. See use of Prefix in this module. |
| */ |
| PrefixList mib_prefixes[] = { |
| {&Standard_Prefix[0]}, /* placeholder for Prefix data */ |
| {".iso.org.dod.internet.mgmt.mib-2"}, |
| {".iso.org.dod.internet.experimental"}, |
| {".iso.org.dod.internet.private"}, |
| {".iso.org.dod.internet.snmpParties"}, |
| {".iso.org.dod.internet.snmpSecrets"}, |
| {NULL, 0} /* end of list */ |
| }; |
| |
| enum inet_address_type { |
| IPV4 = 1, |
| IPV6 = 2, |
| IPV4Z = 3, |
| IPV6Z = 4, |
| DNS = 16 |
| }; |
| |
| |
| /** |
| * @internal |
| * Converts timeticks to hours, minutes, seconds string. |
| * |
| * @param timeticks The timeticks to convert. |
| * @param buf Buffer to write to, has to be at |
| * least 40 Bytes large. |
| * |
| * @return The buffer. |
| */ |
| static char * |
| uptimeString(u_long timeticks, char *buf, size_t buflen) |
| { |
| int centisecs, seconds, minutes, hours, days; |
| |
| if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS)) { |
| snprintf(buf, buflen, "%lu", timeticks); |
| return buf; |
| } |
| |
| |
| centisecs = timeticks % 100; |
| timeticks /= 100; |
| days = timeticks / (60 * 60 * 24); |
| timeticks %= (60 * 60 * 24); |
| |
| hours = timeticks / (60 * 60); |
| timeticks %= (60 * 60); |
| |
| minutes = timeticks / 60; |
| seconds = timeticks % 60; |
| |
| if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) |
| snprintf(buf, buflen, "%d:%d:%02d:%02d.%02d", |
| days, hours, minutes, seconds, centisecs); |
| else { |
| if (days == 0) { |
| snprintf(buf, buflen, "%d:%02d:%02d.%02d", |
| hours, minutes, seconds, centisecs); |
| } else if (days == 1) { |
| snprintf(buf, buflen, "%d day, %d:%02d:%02d.%02d", |
| days, hours, minutes, seconds, centisecs); |
| } else { |
| snprintf(buf, buflen, "%d days, %d:%02d:%02d.%02d", |
| days, hours, minutes, seconds, centisecs); |
| } |
| } |
| return buf; |
| } |
| |
| |
| |
| /** |
| * @internal |
| * Prints the character pointed to if in human-readable ASCII range, |
| * otherwise prints a dot. |
| * |
| * @param buf Buffer to print the character to. |
| * @param ch Character to print. |
| */ |
| static void |
| sprint_char(char *buf, const u_char ch) |
| { |
| if (isprint(ch) || isspace(ch)) { |
| sprintf(buf, "%c", (int) ch); |
| } else { |
| sprintf(buf, "."); |
| } |
| } |
| |
| |
| |
| /** |
| * Prints a hexadecimal string into a buffer. |
| * |
| * The characters pointed by *cp are encoded as hexadecimal string. |
| * |
| * If allow_realloc is true the buffer will be (re)allocated to fit in the |
| * needed size. (Note: *buf may change due to this.) |
| * |
| * @param buf address of the buffer to print to. |
| * @param buf_len address to an integer containing the size of buf. |
| * @param out_len incremented by the number of characters printed. |
| * @param allow_realloc if not zero reallocate the buffer to fit the |
| * needed size. |
| * @param cp the array of characters to encode. |
| * @param line_len the array length of cp. |
| * |
| * @return 1 on success, or 0 on failure (out of memory, or buffer to |
| * small when not allowed to realloc.) |
| */ |
| int |
| _sprint_hexstring_line(u_char ** buf, size_t * buf_len, size_t * out_len, |
| int allow_realloc, const u_char * cp, size_t line_len) |
| { |
| const u_char *tp; |
| const u_char *cp2 = cp; |
| size_t lenleft = line_len; |
| |
| /* |
| * Make sure there's enough room for the hex output.... |
| */ |
| while ((*out_len + line_len*3+1) >= *buf_len) { |
| if (!(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| } |
| |
| /* |
| * .... and display the hex values themselves.... |
| */ |
| for (; lenleft >= 8; lenleft-=8) { |
| sprintf((char *) (*buf + *out_len), |
| "%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1], |
| cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); |
| *out_len += strlen((char *) (*buf + *out_len)); |
| cp += 8; |
| } |
| for (; lenleft > 0; lenleft--) { |
| sprintf((char *) (*buf + *out_len), "%02X ", *cp++); |
| *out_len += strlen((char *) (*buf + *out_len)); |
| } |
| |
| /* |
| * .... plus (optionally) do the same for the ASCII equivalent. |
| */ |
| if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT)) { |
| while ((*out_len + line_len+5) >= *buf_len) { |
| if (!(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| } |
| sprintf((char *) (*buf + *out_len), " ["); |
| *out_len += strlen((char *) (*buf + *out_len)); |
| for (tp = cp2; tp < cp; tp++) { |
| sprint_char((char *) (*buf + *out_len), *tp); |
| (*out_len)++; |
| } |
| sprintf((char *) (*buf + *out_len), "]"); |
| *out_len += strlen((char *) (*buf + *out_len)); |
| } |
| return 1; |
| } |
| |
| int |
| sprint_realloc_hexstring(u_char ** buf, size_t * buf_len, size_t * out_len, |
| int allow_realloc, const u_char * cp, size_t len) |
| { |
| int line_len = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, |
| NETSNMP_DS_LIB_HEX_OUTPUT_LENGTH); |
| if (!line_len) |
| line_len=len; |
| |
| for (; (int)len > line_len; len -= line_len) { |
| if(!_sprint_hexstring_line(buf, buf_len, out_len, allow_realloc, cp, line_len)) |
| return 0; |
| *(*buf + (*out_len)++) = '\n'; |
| *(*buf + *out_len) = 0; |
| cp += line_len; |
| } |
| if(!_sprint_hexstring_line(buf, buf_len, out_len, allow_realloc, cp, len)) |
| return 0; |
| *(*buf + *out_len) = 0; |
| return 1; |
| } |
| |
| |
| |
| /** |
| * Prints an ascii string into a buffer. |
| * |
| * The characters pointed by *cp are encoded as an ascii string. |
| * |
| * If allow_realloc is true the buffer will be (re)allocated to fit in the |
| * needed size. (Note: *buf may change due to this.) |
| * |
| * @param buf address of the buffer to print to. |
| * @param buf_len address to an integer containing the size of buf. |
| * @param out_len incremented by the number of characters printed. |
| * @param allow_realloc if not zero reallocate the buffer to fit the |
| * needed size. |
| * @param cp the array of characters to encode. |
| * @param len the array length of cp. |
| * |
| * @return 1 on success, or 0 on failure (out of memory, or buffer to |
| * small when not allowed to realloc.) |
| */ |
| int |
| sprint_realloc_asciistring(u_char ** buf, size_t * buf_len, |
| size_t * out_len, int allow_realloc, |
| const u_char * cp, size_t len) |
| { |
| int i; |
| |
| for (i = 0; i < (int) len; i++) { |
| if (isprint(*cp) || isspace(*cp)) { |
| if (*cp == '\\' || *cp == '"') { |
| if ((*out_len >= *buf_len) && |
| !(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| *(*buf + (*out_len)++) = '\\'; |
| } |
| if ((*out_len >= *buf_len) && |
| !(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| *(*buf + (*out_len)++) = *cp++; |
| } else { |
| if ((*out_len >= *buf_len) && |
| !(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| *(*buf + (*out_len)++) = '.'; |
| cp++; |
| } |
| } |
| if ((*out_len >= *buf_len) && |
| !(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| *(*buf + *out_len) = '\0'; |
| return 1; |
| } |
| |
| /** |
| * Prints an octet string into a buffer. |
| * |
| * The variable var is encoded as octet string. |
| * |
| * If allow_realloc is true the buffer will be (re)allocated to fit in the |
| * needed size. (Note: *buf may change due to this.) |
| * |
| * @param buf Address of the buffer to print to. |
| * @param buf_len Address to an integer containing the size of buf. |
| * @param out_len Incremented by the number of characters printed. |
| * @param allow_realloc if not zero reallocate the buffer to fit the |
| * needed size. |
| * @param var The variable to encode. |
| * @param enums The enumeration ff this variable is enumerated. may be NULL. |
| * @param hint Contents of the DISPLAY-HINT clause of the MIB. |
| * See RFC 1903 Section 3.1 for details. may be NULL. |
| * @param units Contents of the UNITS clause of the MIB. may be NULL. |
| * |
| * @return 1 on success, or 0 on failure (out of memory, or buffer to |
| * small when not allowed to realloc.) |
| */ |
| int |
| sprint_realloc_octet_string(u_char ** buf, size_t * buf_len, |
| size_t * out_len, int allow_realloc, |
| const netsnmp_variable_list * var, |
| const struct enum_list *enums, const char *hint, |
| const char *units) |
| { |
| size_t saved_out_len = *out_len; |
| const char *saved_hint = hint; |
| int hex = 0, x = 0; |
| u_char *cp; |
| int output_format, cnt; |
| |
| if ((var->type != ASN_OCTET_STR) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| |
| if (hint) { |
| int repeat, width = 1; |
| long value; |
| char code = 'd', separ = 0, term = 0, ch, intbuf[32]; |
| 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 (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, |
| NETSNMP_DS_LIB_2DIGIT_HEX_OUTPUT) |
| && value < 16) { |
| sprintf(intbuf, "0%lx", value); |
| } else { |
| sprintf(intbuf, "%lx", value); |
| } |
| if (!snmp_cstrcat |
| (buf, buf_len, out_len, allow_realloc, intbuf)) { |
| return 0; |
| } |
| break; |
| case 'd': |
| sprintf(intbuf, "%ld", value); |
| if (!snmp_cstrcat |
| (buf, buf_len, out_len, allow_realloc, intbuf)) { |
| return 0; |
| } |
| break; |
| case 'o': |
| sprintf(intbuf, "%lo", value); |
| if (!snmp_cstrcat |
| (buf, buf_len, out_len, allow_realloc, intbuf)) { |
| return 0; |
| } |
| break; |
| case 't': /* new in rfc 3411 */ |
| case 'a': |
| cnt = SNMP_MIN(width, ecp - cp); |
| if (!sprint_realloc_asciistring(buf, buf_len, out_len, |
| allow_realloc, cp, cnt)) |
| return 0; |
| cp += cnt; |
| break; |
| default: |
| *out_len = saved_out_len; |
| if (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, |
| "(Bad hint ignored: ") |
| && snmp_cstrcat(buf, buf_len, out_len, |
| allow_realloc, saved_hint) |
| && snmp_cstrcat(buf, buf_len, out_len, |
| allow_realloc, ") ")) { |
| return sprint_realloc_octet_string(buf, buf_len, |
| out_len, |
| allow_realloc, |
| var, enums, |
| NULL, NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| if (cp < ecp && separ) { |
| while ((*out_len + 1) >= *buf_len) { |
| if (!(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| } |
| *(*buf + *out_len) = separ; |
| (*out_len)++; |
| *(*buf + *out_len) = '\0'; |
| } |
| repeat--; |
| } |
| |
| if (term && cp < ecp) { |
| while ((*out_len + 1) >= *buf_len) { |
| if (!(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| } |
| *(*buf + *out_len) = term; |
| (*out_len)++; |
| *(*buf + *out_len) = '\0'; |
| } |
| } |
| |
| if (units) { |
| return (snmp_cstrcat |
| (buf, buf_len, out_len, allow_realloc, " ") |
| && snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units)); |
| } |
| if ((*out_len >= *buf_len) && |
| !(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| *(*buf + *out_len) = '\0'; |
| |
| return 1; |
| } |
| |
| output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT); |
| if (0 == output_format) { |
| output_format = NETSNMP_STRING_OUTPUT_GUESS; |
| } |
| switch (output_format) { |
| case NETSNMP_STRING_OUTPUT_GUESS: |
| hex = 0; |
| for (cp = var->val.string, x = 0; x < (int) var->val_len; x++, cp++) { |
| if (!isprint(*cp) && !isspace(*cp)) { |
| hex = 1; |
| } |
| } |
| break; |
| |
| case NETSNMP_STRING_OUTPUT_ASCII: |
| hex = 0; |
| break; |
| |
| case NETSNMP_STRING_OUTPUT_HEX: |
| hex = 1; |
| break; |
| } |
| |
| if (var->val_len == 0) { |
| return snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\""); |
| } |
| |
| if (hex) { |
| if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { |
| if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"")) { |
| return 0; |
| } |
| } else { |
| if (!snmp_cstrcat |
| (buf, buf_len, out_len, allow_realloc, "Hex-STRING: ")) { |
| return 0; |
| } |
| } |
| |
| if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc, |
| var->val.string, var->val_len)) { |
| return 0; |
| } |
| |
| if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { |
| if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"")) { |
| return 0; |
| } |
| } |
| } else { |
| if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { |
| if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, |
| "STRING: ")) { |
| return 0; |
| } |
| } |
| if (!snmp_cstrcat |
| (buf, buf_len, out_len, allow_realloc, "\"")) { |
| return 0; |
| } |
| if (!sprint_realloc_asciistring |
| (buf, buf_len, out_len, allow_realloc, var->val.string, |
| var->val_len)) { |
| return 0; |
| } |
| if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"")) { |
| return 0; |
| } |
| } |
| |
| if (units) { |
| return (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ") |
| && snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units)); |
| } |
| return 1; |
| } |
| |
| #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES |
| |
| /** |
| * Prints a float into a buffer. |
| * |
| * The variable var is encoded as a floating point value. |
| * |
| * If allow_realloc is true the buffer will be (re)allocated to fit in the |
| * needed size. (Note: *buf may change due to this.) |
| * |
| * @param buf Address of the buffer to print to. |
| * @param buf_len Address to an integer containing the size of buf. |
| * @param out_len Incremented by the number of characters printed. |
| * @param allow_realloc if not zero reallocate the buffer to fit the |
| * needed size. |
| * @param var The variable to encode. |
| * @param enums The enumeration ff this variable is enumerated. may be NULL. |
| * @param hint Contents of the DISPLAY-HINT clause of the MIB. |
| * See RFC 1903 Section 3.1 for details. may be NULL. |
| * @param units Contents of the UNITS clause of the MIB. may be NULL. |
| * |
| * @return 1 on success, or 0 on failure (out of memory, or buffer to |
| * small when not allowed to realloc.) |
| */ |
| int |
| sprint_realloc_float(u_char ** buf, size_t * buf_len, |
| size_t * out_len, int allow_realloc, |
| const netsnmp_variable_list * var, |
| const struct enum_list *enums, |
| const char *hint, const char *units) |
| { |
| if ((var->type != ASN_OPAQUE_FLOAT) && |
| (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { |
| if (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, |
| "Wrong Type (should be Float): ")) { |
| return sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| 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, "Opaque: Float: ")) { |
| return 0; |
| } |
| } |
| |
| |
| /* |
| * How much space needed for max. length float? 128 is overkill. |
| */ |
| |
| while ((*out_len + 128 + 1) >= *buf_len) { |
| if (!(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| } |
| |
| sprintf((char *) (*buf + *out_len), "%f", *var->val.floatVal); |
| *out_len += strlen((char *) (*buf + *out_len)); |
| |
| if (units) { |
| return (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ") |
| && snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units)); |
| } |
| return 1; |
| } |
| |
| |
| /** |
| * Prints a double into a buffer. |
| * |
| * The variable var is encoded as a double precision floating point value. |
| * |
| * If allow_realloc is true the buffer will be (re)allocated to fit in the |
| * needed size. (Note: *buf may change due to this.) |
| * |
| * @param buf Address of the buffer to print to. |
| * @param buf_len Address to an integer containing the size of buf. |
| * @param out_len Incremented by the number of characters printed. |
| * @param allow_realloc if not zero reallocate the buffer to fit the |
| * needed size. |
| * @param var The variable to encode. |
| * @param enums The enumeration ff this variable is enumerated. may be NULL. |
| * @param hint Contents of the DISPLAY-HINT clause of the MIB. |
| * See RFC 1903 Section 3.1 for details. may be NULL. |
| * @param units Contents of the UNITS clause of the MIB. may be NULL. |
| * |
| * @return 1 on success, or 0 on failure (out of memory, or buffer to |
| * small when not allowed to realloc.) |
| */ |
| int |
| sprint_realloc_double(u_char ** buf, size_t * buf_len, |
| size_t * out_len, int allow_realloc, |
| const netsnmp_variable_list * var, |
| const struct enum_list *enums, |
| const char *hint, const char *units) |
| { |
| if ((var->type != ASN_OPAQUE_DOUBLE) && |
| (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { |
| if (snmp_cstrcat |
| (buf, buf_len, out_len, allow_realloc, |
| "Wrong Type (should be Double): ")) { |
| return sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| 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, "Opaque: Float: ")) { |
| return 0; |
| } |
| } |
| |
| /* |
| * How much space needed for max. length double? 128 is overkill. |
| */ |
| |
| while ((*out_len + 128 + 1) >= *buf_len) { |
| if (!(allow_realloc && snmp_realloc(buf, buf_len))) { |
| return 0; |
| } |
| } |
| |
| sprintf((char *) (*buf + *out_len), "%f", *var->val.doubleVal); |
| *out_len += strlen((char *) (*buf + *out_len)); |
| |
| if (units) { |
| return (snmp_cstrcat |
| (buf, buf_len, out_len, allow_realloc, " ") |
| && snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units)); |
| } |
| return 1; |
| } |
| |
| #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ |
| |
| |
| /** |
| * Prints a counter into a buffer. |
| * |
| * The variable var is encoded as a counter value. |
| * |
| * If allow_realloc is true the buffer will be (re)allocated to fit in the |
| * needed size. (Note: *buf may change due to this.) |
| * |
| * @param buf Address of the buffer to print to. |
| * @param buf_len Address to an integer containing the size of buf. |
| * @param out_len Incremented by the number of characters printed. |
| * @param allow_realloc if not zero reallocate the buffer to fit the |
| * needed size. |
| * @param var The variable to encode. |
| * @param enums The enumeration ff this variable is enumerated. may be NULL. |
| * @param hint Contents of the DISPLAY-HINT clause of the MIB. |
| * See RFC 1903 Section 3.1 for details. may be NULL. |
| * @param units Contents of the UNITS clause of the MIB. may be NULL. |
| * |
| * @return 1 on success, or 0 on failure (out of memory, or buffer to |
| * small when not allowed to realloc.) |
| */ |
| int |
| sprint_realloc_counter64(u_char ** buf, size_t * buf_len, size_t * out_len, |
| int allow_realloc, |
| const netsnmp_variable_list * var, |
| const struct enum_list *enums, |
| const char *hint, const char *units) |
| { |
| char a64buf[I64CHARSZ + 1]; |
| |
| if ((var->type != ASN_COUNTER64 |
| #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES |
| && var->type != ASN_OPAQUE_COUNTER64 |
| && var->type != ASN_OPAQUE_I64 && var->type != ASN_OPAQUE_U64 |
| #endif |
| ) && (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { |
| if (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, |
| "Wrong Type (should be Counter64): ")) { |
| return sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| 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 */ |
| ) && (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { |
| if (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, |
| "Wrong Type (should be Opaque): ")) { |
| return sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| #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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| 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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| 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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| 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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| 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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| 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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| 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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| 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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| 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) |
| { |
| if ((var->type != ASN_NULL) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } else { |
| u_char str[] = "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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| 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 { |
| 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) && |
| (!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 sprint_realloc_by_type(buf, buf_len, out_len, |
| allow_realloc, var, NULL, NULL, |
| NULL); |
| } else { |
| return 0; |
| } |
| } |
| |
| if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { |
| u_char str[] = "NsapAddress: "; |
| if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { |
| return 0; |
| } |
| } |
| |
| return sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc, |
| var->val.string, var->val_len); |
| } |
| |
| |
| /** |
| * Fallback routine for a bad type, prints "Variable has bad type" into a buffer. |
| * |
| * If allow_realloc is true the buffer will be (re)allocated to fit in the |
| * needed size. (Note: *buf may change due to this.) |
| * |
| * @param buf Address of the buffer to print to. |
| * @param buf_len Address to an integer containing the size of buf. |
| * @param out_len Incremented by the number of characters printed. |
| * @param allow_realloc if not zero reallocate the buffer to fit the |
| * needed size. |
| * @param var The variable to encode. |
| * @param enums The enumeration ff this variable is enumerated. may be NULL. |
| * @param hint Contents of the DISPLAY-HINT clause of the MIB. |
| * See RFC 1903 Section 3.1 for details. may be NULL. |
| * @param units Contents of the UNITS clause of the MIB. may be NULL. |
| * |
| * @return 1 on success, or 0 on failure (out of memory, or buffer to |
| * small when not allowed to realloc.) |
| */ |
| int |
| sprint_realloc_badtype(u_char ** buf, size_t * buf_len, size_t * out_len, |
| int allow_realloc, |
| const netsnmp_variable_list * var, |
| const struct enum_list *enums, |
| const char *hint, const char *units) |
| { |
| u_char str[] = "Variable has bad type"; |
| |
| return snmp_strcat(buf, buf_len, out_len, allow_realloc, str); |
| } |
| |
| |
| |
| /** |
| * Universal print routine, prints a variable into a buffer according to the variable |
| * type. |
| * |
| * If allow_realloc is true the buffer will be (re)allocated to fit in the |
| * needed size. (Note: *buf may change due to this.) |
| * |
| * @param buf Address of the buffer to print to. |
| * @param buf_len Address to an integer containing the size of buf. |
| * @param out_len Incremented by the number of characters printed. |
| * @param allow_realloc if not zero reallocate the buffer to fit the |
| * needed size. |
| * @param var The variable to encode. |
| * @param enums The enumeration ff this variable is enumerated. may be NULL. |
| * @param hint Contents of the DISPLAY-HINT clause of the MIB. |
| * See RFC 1903 Section 3.1 for details. may be NULL. |
| * @param units Contents of the UNITS clause of the MIB. may be NULL. |
| * |
| * @return 1 on success, or 0 on failure (out of memory, or buffer to |
| * small when not allowed to realloc.) |
| */ |
| int |
| sprint_realloc_by_type(u_char ** buf, size_t * buf_len, size_t * out_len, |
| int allow_realloc, |
| const netsnmp_variable_list * var, |
| const struct enum_list *enums, |
| const char *hint, const char *units) |
| { |
| DEBUGMSGTL(("output", "sprint_by_type, type %d\n", var->type)); |
| |
| switch (var->type) { |
| case ASN_INTEGER: |
| return sprint_realloc_integer(buf, buf_len, out_len, allow_realloc, |
| var, enums, hint, units); |
| case ASN_OCTET_STR: |
| return sprint_realloc_octet_string(buf, buf_len, out_len, |
| allow_realloc, var, enums, hint, |
| units); |
| case ASN_BIT_STR: |
| return sprint_realloc_bitstring(buf, buf_len, out_len, |
| allow_realloc, var, enums, hint, |
| units); |
| case ASN_OPAQUE: |
| return sprint_realloc_opaque(buf, buf_len, out_len, allow_realloc, |
| var, enums, hint, units); |
| case ASN_OBJECT_ID: |
| return sprint_realloc_object_identifier(buf, buf_len, out_len, |
| allow_realloc, var, enums, |
| hint, units); |
| case ASN_TIMETICKS: |
| return sprint_realloc_timeticks(buf, buf_len, out_len, |
| allow_realloc, var, enums, hint, |
| units); |
| case ASN_GAUGE: |
| return sprint_realloc_gauge(buf, buf_len, out_len, allow_realloc, |
| var, enums, hint, units); |
| case ASN_COUNTER: |
| return sprint_realloc_counter(buf, buf_len, out_len, allow_realloc, |
| var, enums, hint, units); |
| case ASN_IPADDRESS: |
| return sprint_realloc_ipaddress(buf, buf_len, out_len, |
| allow_realloc, var, enums, hint, |
| units); |
| case ASN_NULL: |
| return sprint_realloc_null(buf, buf_len, out_len, allow_realloc, |
| var, enums, hint, units); |
| case ASN_UINTEGER: |
| return sprint_realloc_uinteger(buf, buf_len, out_len, |
| allow_realloc, var, enums, hint, |
| units); |
| case ASN_COUNTER64: |
| #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES |
| case ASN_OPAQUE_U64: |
| case ASN_OPAQUE_I64: |
| case ASN_OPAQUE_COUNTER64: |
| #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ |
| return sprint_realloc_counter64(buf, buf_len, out_len, |
| allow_realloc, var, enums, hint, |
| units); |
| #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES |
| case ASN_OPAQUE_FLOAT: |
| return sprint_realloc_float(buf, buf_len, out_len, allow_realloc, |
| var, enums, hint, units); |
| case ASN_OPAQUE_DOUBLE: |
| return sprint_realloc_double(buf, buf_len, out_len, allow_realloc, |
| var, enums, hint, units); |
| #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ |
| default: |
| DEBUGMSGTL(("sprint_by_type", "bad type: %d\n", var->type)); |
| return sprint_realloc_badtype(buf, buf_len, out_len, allow_realloc, |
| var, enums, hint, units); |
| } |
| } |
| |
| |
| #ifndef NETSNMP_DISABLE_MIB_LOADING |
| /** |
| * Retrieves the tree head. |
| * |
| * @return the tree head. |
| */ |
| struct tree * |
| get_tree_head(void) |
| { |
| return (tree_head); |
| } |
| |
| static char *confmibdir = NULL; |
| static char *confmibs = NULL; |
| |
| static void |
| handle_mibdirs_conf(const char *token, char *line) |
| { |
| char *ctmp; |
| |
| if (confmibdir) { |
| if ((*line == '+') || (*line == '-')) { |
| ctmp = (char *) malloc(strlen(confmibdir) + strlen(line) + 2); |
| if (!ctmp) { |
| DEBUGMSGTL(("read_config:initmib", |
| "mibdir conf malloc failed")); |
| return; |
| } |
| if(*line++ == '+') |
| sprintf(ctmp, "%s%c%s", confmibdir, ENV_SEPARATOR_CHAR, line); |
| else |
| sprintf(ctmp, "%s%c%s", line, ENV_SEPARATOR_CHAR, confmibdir); |
| } else { |
| ctmp = strdup(line); |
| if (!ctmp) { |
| DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); |
| return; |
| } |
| } |
| SNMP_FREE(confmibdir); |
| } else { |
| ctmp = strdup(line); |
| if (!ctmp) { |
| DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); |
| return; |
| } |
| } |
| confmibdir = ctmp; |
| DEBUGMSGTL(("read_config:initmib", "using mibdirs: %s\n", confmibdir)); |
| } |
| |
| static void |
| handle_mibs_conf(const char *token, char *line) |
| { |
| char *ctmp; |
| |
| if (confmibs) { |
| if ((*line == '+') || (*line == '-')) { |
| ctmp = (char *) malloc(strlen(confmibs) + strlen(line) + 2); |
| if (!ctmp) { |
| DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); |
| return; |
| } |
| if(*line++ == '+') |
| sprintf(ctmp, "%s%c%s", confmibs, ENV_SEPARATOR_CHAR, line); |
| else |
| sprintf(ctmp, "%s%c%s", line, ENV_SEPARATOR_CHAR, confmibdir); |
| } else { |
| ctmp = strdup(line); |
| if (!ctmp) { |
| DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); |
| return; |
| } |
| } |
| SNMP_FREE(confmibs); |
| } else { |
| ctmp = strdup(line); |
| if (!ctmp) { |
| DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); |
| return; |
| } |
| } |
| confmibs = ctmp; |
| DEBUGMSGTL(("read_config:initmib", "using mibs: %s\n", confmibs)); |
| } |
| |
| |
| static void |
| handle_mibfile_conf(const char *token, char *line) |
| { |
| DEBUGMSGTL(("read_config:initmib", "reading mibfile: %s\n", line)); |
| read_mib(line); |
| } |
| #endif |
| |
| static void |
| handle_print_numeric(const char *token, char *line) |
| { |
| const char *value; |
| char *st; |
| |
| value = strtok_r(line, " \t\n", &st); |
| if (value && ( |
| (strcasecmp(value, "yes") == 0) || |
| (strcasecmp(value, "true") == 0) || |
| (*value == '1') )) { |
| |
| netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, |
| NETSNMP_OID_OUTPUT_NUMERIC); |
| } |
| } |
| |
| char * |
| snmp_out_toggle_options(char *options) |
| { |
| while (*options) { |
| switch (*options++) { |
| case '0': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, |
| NETSNMP_DS_LIB_2DIGIT_HEX_OUTPUT); |
| break; |
| case 'a': |
| netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT, |
| NETSNMP_STRING_OUTPUT_ASCII); |
| break; |
| case 'b': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS); |
| break; |
| case 'e': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM); |
| break; |
| case 'E': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES); |
| break; |
| case 'f': |
| netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, |
| NETSNMP_OID_OUTPUT_FULL); |
| break; |
| case 'n': |
| netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, |
| NETSNMP_OID_OUTPUT_NUMERIC); |
| break; |
| case 'q': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT); |
| break; |
| case 'Q': |
| netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT, 1); |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT); |
| break; |
| case 's': |
| netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, |
| NETSNMP_OID_OUTPUT_SUFFIX); |
| break; |
| case 'S': |
| netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, |
| NETSNMP_OID_OUTPUT_MODULE); |
| break; |
| case 't': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS); |
| break; |
| case 'T': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT); |
| break; |
| case 'u': |
| netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, |
| NETSNMP_OID_OUTPUT_UCD); |
| break; |
| case 'U': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS); |
| break; |
| case 'v': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE); |
| break; |
| case 'x': |
| netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT, |
| NETSNMP_STRING_OUTPUT_HEX); |
| break; |
| case 'X': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX); |
| break; |
| default: |
| return options - 1; |
| } |
| } |
| return NULL; |
| } |
| |
| void |
| snmp_out_toggle_options_usage(const char *lead, FILE * outf) |
| { |
| fprintf(outf, "%s0: print leading 0 for single-digit hex characters\n", lead); |
| fprintf(outf, "%sa: print all strings in ascii format\n", lead); |
| fprintf(outf, "%sb: do not break OID indexes down\n", lead); |
| fprintf(outf, "%se: print enums numerically\n", lead); |
| fprintf(outf, "%sE: escape quotes in string indices\n", lead); |
| fprintf(outf, "%sf: print full OIDs on output\n", lead); |
| fprintf(outf, "%sn: print OIDs numerically\n", lead); |
| fprintf(outf, "%sq: quick print for easier parsing\n", lead); |
| fprintf(outf, "%sQ: quick print with equal-signs\n", lead); /* @@JDW */ |
| fprintf(outf, "%ss: print only last symbolic element of OID\n", lead); |
| fprintf(outf, "%sS: print MIB module-id plus last element\n", lead); |
| fprintf(outf, "%st: print timeticks unparsed as numeric integers\n", |
| lead); |
| fprintf(outf, |
| "%sT: print human-readable text along with hex strings\n", |
| lead); |
| fprintf(outf, "%su: print OIDs using UCD-style prefix suppression\n", |
| lead); |
| fprintf(outf, "%sU: don't print units\n", lead); |
| fprintf(outf, "%sv: print values only (not OID = value)\n", lead); |
| fprintf(outf, "%sx: print all strings in hex format\n", lead); |
| fprintf(outf, "%sX: extended index format\n", lead); |
| } |
| |
| char * |
| snmp_in_options(char *optarg, int argc, char *const *argv) |
| { |
| char *cp; |
| |
| for (cp = optarg; *cp; cp++) { |
| switch (*cp) { |
| case 'b': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REGEX_ACCESS); |
| break; |
| case 'R': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS); |
| break; |
| case 'r': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE); |
| break; |
| case 'h': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT); |
| break; |
| case 'u': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID); |
| break; |
| case 's': |
| /* What if argc/argv are null ? */ |
| if (!*(++cp)) |
| cp = argv[optind++]; |
| netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, |
| NETSNMP_DS_LIB_OIDSUFFIX, |
| cp); |
| return NULL; |
| |
| case 'S': |
| /* What if argc/argv are null ? */ |
| if (!*(++cp)) |
| cp = argv[optind++]; |
| netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, |
| NETSNMP_DS_LIB_OIDPREFIX, |
| cp); |
| return NULL; |
| |
| default: |
| /* |
| * Here? Or in snmp_parse_args? |
| snmp_log(LOG_ERR, "Unknown input option passed to -I: %c.\n", *cp); |
| */ |
| return cp; |
| } |
| } |
| return NULL; |
| } |
| |
| char * |
| snmp_in_toggle_options(char *options) |
| { |
| return snmp_in_options( options, 0, NULL ); |
| } |
| |
| |
| /** |
| * Prints out a help usage for the in* toggle options. |
| * |
| * @param lead The lead to print for every line. |
| * @param outf The file descriptor to write to. |
| * |
| */ |
| void |
| snmp_in_toggle_options_usage(const char *lead, FILE * outf) |
| { |
| fprintf(outf, "%sb: do best/regex matching to find a MIB node\n", lead); |
| fprintf(outf, "%sh: don't apply DISPLAY-HINTs\n", lead); |
| fprintf(outf, "%sr: do not check values for range/type legality\n", lead); |
| fprintf(outf, "%sR: do random access to OID labels\n", lead); |
| fprintf(outf, |
| "%su: top-level OIDs must have '.' prefix (UCD-style)\n", lead); |
| fprintf(outf, |
| "%ss SUFFIX: Append all textual OIDs with SUFFIX before parsing\n", |
| lead); |
| fprintf(outf, |
| "%sS PREFIX: Prepend all textual OIDs with PREFIX before parsing\n", |
| lead); |
| } |
| |
| /*** |
| * |
| */ |
| void |
| register_mib_handlers(void) |
| { |
| #ifndef NETSNMP_DISABLE_MIB_LOADING |
| register_prenetsnmp_mib_handler("snmp", "mibdirs", |
| handle_mibdirs_conf, NULL, |
| "[mib-dirs|+mib-dirs|-mib-dirs]"); |
| register_prenetsnmp_mib_handler("snmp", "mibs", |
| handle_mibs_conf, NULL, |
| "[mib-tokens|+mib-tokens]"); |
| register_config_handler("snmp", "mibfile", |
| handle_mibfile_conf, NULL, "mibfile-to-read"); |
| /* |
| * register the snmp.conf configuration handlers for default |
| * parsing behaviour |
| */ |
| |
| netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "showMibErrors", |
| NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_ERRORS); |
| netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "strictCommentTerm", |
| 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()); |
| |
| 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, "/") != 0) { |
| 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 != 0) { |
| 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_CLEAN_NAMESPACE |
| void |
| init_mib(void) |
| { |
| netsnmp_init_mib(); |
| } |
| #endif |
| |
| |
| /** |
| * 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_top = NULL; |
| } |
| tree_head = NULL; |
| Mib = 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. |
| */ |
| void |
| print_mib(FILE * fp) |
| { |
| print_subtree(fp, tree_head, 0); |
| } |
| |
| 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; |
| #endif /* NETSNMP_DISABLE_MIB_LOADING */ |
| char buf[SPRINT_MAX_LEN]; |
| 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); |
|