Ethereal-dev: Re: [ethereal-dev] packet-snmp.c and libsmi
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Sun, 25 Jun 2000 13:56:24 -0700
On Sat, Jun 24, 2000 at 01:14:06PM -0700, Guy Harris wrote: > On Fri, Jun 23, 2000 at 11:38:12PM -0700, Guy Harris wrote: > > This is a patch to the current "packet-snmp.c" in the CVS tree. > > ...and this is a slightly better one (again, a patch to the code in the > CVS tree), that doesn't reintroduce the no-longer-necessary > commented-out examples of "hf_register_info" entries (no longer > necessary because there are *real* entries now for some of the SNMP V3 > stuff). ...and this one is even better (again, a patch to the stuff in the CVS tree; update your CVS tree first), as it gets rid of a string-size #define that is no longer used.
Index: packet-snmp.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet-snmp.c,v
retrieving revision 1.38
diff -c -r1.38 packet-snmp.c
*** packet-snmp.c 2000/06/25 20:55:09 1.38
--- packet-snmp.c 2000/06/25 20:57:37
***************
*** 45,193 ****
# include <netinet/in.h>
#endif
! #define MAX_STRING_LEN 2048 /* TBC */
! #ifdef linux
! #include <dlfcn.h>
#endif
- #include <glib.h>
-
#include "packet.h"
#include "etypes.h"
#include "packet-ipx.h"
-
- #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
- /*
- * UCD or CMU SNMP?
- */
- # if defined(HAVE_UCD_SNMP_SNMP_H)
- /*
- * UCD SNMP.
- */
- # include <ucd-snmp/asn1.h>
- # include <ucd-snmp/snmp_api.h>
- # include <ucd-snmp/snmp_impl.h>
- # include <ucd-snmp/mib.h>
-
- /*
- * Sigh. UCD SNMP 4.1.1 makes "snmp_set_suffix_only()" a macro
- * that calls "ds_set_int()" with the first two arguments
- * being DS_LIBRARY_ID and DS_LIB_PRINT_SUFFIX_ONLY; this means that,
- * when building with 4.1.1, we need to arrange that
- * <ucd-snmp/default_store.h> is included, to define those two values
- * and to declare "ds_int()".
- *
- * However:
- *
- * 1) we can't include it on earlier versions (at least not 3.6.2),
- * as it doesn't exist in those versions;
- *
- * 2) we don't want to include <ucd-snmp/ucd-snmp-includes.h>,
- * as that includes <ucd-snmp/snmp.h>, and that defines a whole
- * bunch of values that we also define ourselves.
- *
- * So we only include it if "snmp_set_full_objid" is defined as
- * a macro.
- */
- # ifdef snmp_set_suffix_only
- # include <ucd-snmp/default_store.h>
- # endif
-
- /*
- * XXX - for now, we assume all versions of UCD SNMP have it.
- */
- # define HAVE_SPRINT_VALUE
-
- /*
- * Define values "sprint_value()" expects.
- */
- # define VALTYPE_INTEGER ASN_INTEGER
- # define VALTYPE_COUNTER ASN_COUNTER
- # define VALTYPE_GAUGE ASN_GAUGE
- # define VALTYPE_TIMETICKS ASN_TIMETICKS
- # define VALTYPE_STRING ASN_OCTET_STR
- # define VALTYPE_IPADDR ASN_IPADDRESS
- # define VALTYPE_OPAQUE ASN_OPAQUE
- # define VALTYPE_NSAP ASN_NSAP
- # define VALTYPE_OBJECTID ASN_OBJECT_ID
- # define VALTYPE_BITSTR ASN_BIT_STR
- # define VALTYPE_COUNTER64 ASN_COUNTER64
- # elif defined(HAVE_SNMP_SNMP_H)
- /*
- * CMU SNMP.
- */
- # include <snmp/snmp.h>
-
- /*
- * Some older versions of CMU SNMP may lack these values (e.g., the
- * "libsnmp3.6" package for Debian, which is based on some old
- * CMU SNMP, perhaps 1.0); for now, we assume they also lack
- * "sprint_value()".
- */
- # ifdef SMI_INTEGER
- # define HAVE_SPRINT_VALUE
- /*
- * Define values "sprint_value()" expects.
- */
- # define VALTYPE_INTEGER SMI_INTEGER
- # define VALTYPE_COUNTER SMI_COUNTER32
- # define VALTYPE_GAUGE SMI_GAUGE32
- # define VALTYPE_TIMETICKS SMI_TIMETICKS
- # define VALTYPE_STRING SMI_STRING
- # define VALTYPE_IPADDR SMI_IPADDRESS
- # define VALTYPE_OPAQUE SMI_OPAQUE
- # define VALTYPE_NSAP SMI_STRING
- # define VALTYPE_OBJECTID SMI_OBJID
- # define VALTYPE_BITSTR ASN_BIT_STR
- # define VALTYPE_COUNTER64 SMI_COUNTER64
- # endif
- /*
- * Now undo all the definitions they "helpfully" gave us, so we don't get
- * complaints about redefining them.
- *
- * Why, oh why, is there no library that provides code to
- *
- * 1) read MIB files;
- *
- * 2) translate object IDs into names;
- *
- * 3) let you find out, for a given object ID, what the type, enum
- * values, display hint, etc. are;
- *
- * in a *simple* fashion, without assuming that your code is part of an
- * SNMP agent or client that wants a pile of definitions of PDU types,
- * etc.? Is it just that 99 44/100% of the code that uses an SNMP library
- * *is* part of an agent or client, and really *does* need that stuff,
- * and *doesn't* need the interfaces we want?
- */
- # undef SNMP_ERR_NOERROR
- # undef SNMP_ERR_TOOBIG
- # undef SNMP_ERR_NOSUCHNAME
- # undef SNMP_ERR_BADVALUE
- # undef SNMP_ERR_READONLY
- # undef SNMP_ERR_NOACCESS
- # undef SNMP_ERR_WRONGTYPE
- # undef SNMP_ERR_WRONGLENGTH
- # undef SNMP_ERR_WRONGENCODING
- # undef SNMP_ERR_WRONGVALUE
- # undef SNMP_ERR_NOCREATION
- # undef SNMP_ERR_INCONSISTENTVALUE
- # undef SNMP_ERR_RESOURCEUNAVAILABLE
- # undef SNMP_ERR_COMMITFAILED
- # undef SNMP_ERR_UNDOFAILED
- # undef SNMP_ERR_AUTHORIZATIONERROR
- # undef SNMP_ERR_NOTWRITABLE
- # undef SNMP_ERR_INCONSISTENTNAME
- # undef SNMP_TRAP_COLDSTART
- # undef SNMP_TRAP_WARMSTART
- # undef SNMP_TRAP_LINKDOWN
- # undef SNMP_TRAP_LINKUP
- # undef SNMP_TRAP_EGPNEIGHBORLOSS
- # undef SNMP_TRAP_ENTERPRISESPECIFIC
- # endif
- #endif
-
#include "asn1.h"
#include "packet-snmp.h"
--- 45,61 ----
# include <netinet/in.h>
#endif
! #include <glib.h>
! #ifdef HAVE_SMI_H
! #include <smi.h>
! #else
! typedef void SmiNode;
#endif
#include "packet.h"
#include "etypes.h"
#include "packet-ipx.h"
#include "asn1.h"
#include "packet-snmp.h"
***************
*** 554,635 ****
dissect_data(pd, offset, fd, tree);
}
! static void
! format_oid(gchar *buf, subid_t *oid, guint oid_length)
{
! int i;
! int len;
len = sprintf(buf, "%lu", (unsigned long)oid[0]);
buf += len;
for (i = 1; i < oid_length;i++) {
len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
buf += len;
}
}
! #ifdef HAVE_SPRINT_VALUE
! static void
! format_value(gchar *buf, struct variable_list *variable, subid_t *variable_oid,
! guint variable_oid_length, gushort vb_type, guint vb_length)
{
! variable->next_variable = NULL;
! variable->name = variable_oid;
! variable->name_length = variable_oid_length;
switch (vb_type) {
case SNMP_INTEGER:
! variable->type = VALTYPE_INTEGER;
break;
case SNMP_COUNTER:
- variable->type = VALTYPE_COUNTER;
- break;
-
case SNMP_GAUGE:
- variable->type = VALTYPE_GAUGE;
- break;
-
case SNMP_TIMETICKS:
! variable->type = VALTYPE_TIMETICKS;
break;
case SNMP_OCTETSTR:
- variable->type = VALTYPE_STRING;
- break;
-
case SNMP_IPADDR:
- variable->type = VALTYPE_IPADDR;
- break;
-
case SNMP_OPAQUE:
- variable->type = VALTYPE_OPAQUE;
- break;
-
case SNMP_NSAP:
- variable->type = VALTYPE_NSAP;
- break;
-
- case SNMP_OBJECTID:
- variable->type = VALTYPE_OBJECTID;
- break;
-
case SNMP_BITSTR:
! variable->type = VALTYPE_BITSTR;
break;
! case SNMP_COUNTER64:
! variable->type = VALTYPE_COUNTER64;
break;
}
! variable->val_len = vb_length;
! sprint_value(buf, variable_oid, variable_oid_length, variable);
}
- #endif
static int
snmp_variable_decode(proto_tree *snmp_tree, subid_t *variable_oid,
! guint variable_oid_length, ASN1_SCK *asn1, int offset, guint *lengthp)
{
const guchar *start;
guint length;
--- 422,967 ----
dissect_data(pd, offset, fd, tree);
}
! static gint
! int_div(guchar *buffer, gint radix, gint *len, gint *nul)
{
! gint dividend, i, mod;
!
! *nul = 1;
! while (*len && (*buffer == 0))
! {
! for (i=1; i<*len; i++)
! buffer[i-1] = buffer[i];
! (*len)--;
! }
! if (!*len)
! return 0;
!
! dividend = 0;
! mod = 0;
! for (i=0; i<*len; i++)
! {
! dividend = mod * 256 + buffer[i];
! mod = dividend % radix;
! buffer[i] = dividend / radix;
! }
! while (*len && (*buffer == 0))
! {
! for (i=1; i<*len; i++)
! buffer[i-1] = buffer[i];
! (*len)--;
! }
! if (*len) *nul=0;
! return mod;
! }
!
! /**
! * print_radix:
! * @buffer: integer value
! * @len: length of integer
! * @radix: base
! * @shift: decimal shift
! *
! */
! static gchar *
! print_radix(gpointer buffer, gint len, gint radix, gboolean sign, gint shift)
! {
! guchar *result, *temp;
! gint size, neg, i, nul;
! gchar digit[] = "0123456789ABCDEF";
!
! if (radix<2) radix=2;
! if (radix>16) radix=16;
!
! size = len*8 + 2; /* worst case + sign + trailing 0 */
! if (shift) size++; /* decimal point */
! if (size<shift+4) size=shift+4; /* additional leading 0 */
!
! result = g_malloc(size+1);
! temp = g_malloc(len);
!
! neg = 0;
!
! g_memmove(temp, buffer, len);
!
! if (sign && (temp[0] & 0x80))
! {
! neg = 1;
! for (i=0; i<len; i++)
! temp[i] = ~temp[i];
! i=len-1;
! while (i>=0)
! {
! temp[i]++;
! if (temp[i]) break;
! i--;
! }
! }
! i=size;
! result[i--] = '\0';
! nul=0;
! while ((!nul || (shift && size-i-3 < shift)) && (i>=0))
! {
! if ((shift == size-i-1) && shift)
! result[i--] = '.';
! else
! result[i--] = digit[int_div(temp, radix, &len, &nul)];
! }
! if (i && neg)
! result[i--] = '-';
! g_free(temp);
! temp = g_strdup(result+i+1);
! g_free(result);
! return temp;
! }
!
! /**
! * format_integer:
! * @buffer: integer value as received from SNMP node
! * @len: length of integer
! * @format: Format as taken from DISPLAY HINT parameter of MIB file.
! *
! * Formats an INTEGER value according to a provided DISPLAY HINT.
! *
! * When the syntax has an underlying primitive type of INTEGER, the hint
! * consists of an integer-format specification, containing two parts.
! * The first part is a single character suggesting a display format,
! * either: `x' for hexadecimal, or `d' for decimal, or `o' for octal, or
! * `b' for binary. For all types, when rendering the value, leading
! * zeros are omitted, and for negative values, a minus sign is rendered
! * immediately before the digits. The second part is always omitted for
! * `x', `o' and `b', and need not be present for `d'. If present, the
! * second part starts with a hyphen and is followed by a decimal number,
! * which defines the implied decimal point when rendering the value.
! *
! * Return value: Formatted string.
! **/
! static gchar*
! format_integer(gpointer buffer, gint len, gboolean sign, gchar *format)
! {
! gint shift;
!
! shift = 0;
! switch(format[0])
! {
! case 'x':
! return print_radix(buffer, len, 16, sign, 0);
! break;
! case 'o':
! return print_radix(buffer, len, 8, sign, 0);
! break;
! case 'b':
! return print_radix(buffer, len, 2, sign, 0);
! break;
! case 'd':
! if (format[1] == '-')
! shift = atoi(&(format[2]));
! if (shift < 0)
! shift = 0;
! default:
! return print_radix(buffer, len, 10, sign, shift);
! }
! }
!
! /**
! * format_string:
! * @buffer: octet string as received from SNMP node
! * @len: length of octet string
! * @format: Format as taken from DISPLAY HINT parameter of MIB file.
! *
! * Formats an OCTET STRING value according to a provided DISPLAY HINT.
! *
! * When the syntax has an underlying primitive type of OCTET STRING, the
! * hint consists of one or more octet-format specifications. Each
! * specification consists of five parts, with each part using and
! * removing zero or more of the next octets from the value and producing
! * the next zero or more characters to be displayed. The octets within
! * the value are processed in order of significance, most significant
! * first.
! *
! * The five parts of a octet-format specification are:
! *
! * (1) the (optional) repeat indicator; if present, this part is a `*',
! * and indicates that the current octet of the value is to be used as
! * the repeat count. The repeat count is an unsigned integer (which
! * may be zero) which specifies how many times the remainder of this
! * octet-format specification should be successively applied. If the
! * repeat indicator is not present, the repeat count is one.
! *
! * (2) the octet length: one or more decimal digits specifying the number
! * of octets of the value to be used and formatted by this octet-
! * specification. Note that the octet length can be zero. If less
! * than this number of octets remain in the value, then the lesser
! * number of octets are used.
! *
! * (3) the display format, either: `x' for hexadecimal, `d' for decimal,
! * `o' for octal, `a' for ascii, or `t' for UTF-8. If the octet
! * length part is greater than one, and the display format part refers
! * to a numeric format, then network-byte ordering (big-endian
! * encoding) is used interpreting the octets in the value. The octets
! * processed by the `t' display format do not necessarily form an
! * integral number of UTF-8 characters. Trailing octets which do not
! * form a valid UTF-8 encoded character are discarded.
! *
! * (4) the (optional) display separator character; if present, this part
! * is a single character which is produced for display after each
! * application of this octet-specification; however, this character is
! * not produced for display if it would be immediately followed by the
! * display of the repeat terminator character for this octet-
! * specification. This character can be any character other than a
! * decimal digit and a `*'.
! *
! * (5) the (optional) repeat terminator character, which can be present
! * only if the display separator character is present and this octet-
! * specification begins with a repeat indicator; if present, this part
! * is a single character which is produced after all the zero or more
! * repeated applications (as given by the repeat count) of this
! * octet-specification. This character can be any character other
! * than a decimal digit and a `*'.
! *
! * Output of a display separator character or a repeat terminator
! * character is suppressed if it would occur as the last character of
! * the display.
! *
! * If the octets of the value are exhausted before all the octet-format
! * specification have been used, then the excess specifications are
! * ignored. If additional octets remain in the value after interpreting
! * all the octet-format specifications, then the last octet-format
! * specification is re-interpreted to process the additional octets,
! * until no octets remain in the value.
! *
! * Return value: Formatted string.
! **/
! static gchar*
! format_string(gpointer buffer, gint len, gchar *format)
! {
! int repeat, count, size;
! gchar seperator, terminator, formtype;
! gchar *ptr;
! guchar *bufptr;
! gchar *result;
! int pos;
! gchar *numstr;
! int numstrlen;
!
! if (!len)
! return g_strdup("NULL");
!
! ptr = format;
! bufptr = (guchar *)buffer;
!
! size = len * 3 * strlen(format);
! result = g_malloc(size);
!
! pos = 0;
!
! while (len)
! {
! /* Read format string */
! if (!*ptr)
! ptr = format;
! repeat = 1;
! count = 0;
! seperator = '\0';
! terminator = '\0';
! formtype = '\0';
! if (*ptr == '*')
! {
! repeat = *bufptr++;
! len--;
! ptr++;
! }
! while (*ptr >= '0' && *ptr <= '9')
! {
! count = 10 * count + (*ptr++ & 0xf);
! }
! if (count == 0)
! count = 1;
!
! if (*ptr && (*ptr != '*') && ((*ptr < '0') || (*ptr > '9')))
! formtype = *ptr++;
! if (*ptr && (*ptr != '*') && ((*ptr < '0') || (*ptr > '9')))
! seperator = *ptr++;
! if (*ptr && (*ptr != '*') && ((*ptr < '0') || (*ptr > '9')))
! terminator = *ptr++;
!
! while(repeat && len)
! {
! if (count > len) count = len;
! switch (formtype)
! {
! case 'x':
! numstr = print_radix(bufptr, count, 16, FALSE, 0);
! numstrlen = strlen(numstr);
! g_assert(pos + numstrlen < size);
! strcpy(result + pos, numstr);
! pos += numstrlen;
! g_free(numstr);
! break;
! case 'd':
! numstr = print_radix(bufptr, count, 10, FALSE, 0);
! numstrlen = strlen(numstr);
! g_assert(pos + numstrlen < size);
! strcpy(result + pos, numstr);
! pos += numstrlen;
! g_free(numstr);
! break;
! case 'o':
! numstr = print_radix(bufptr, count, 8, FALSE, 0);
! numstrlen = strlen(numstr);
! g_assert(pos + numstrlen < size);
! strcpy(result + pos, numstr);
! pos += numstrlen;
! g_free(numstr);
! break;
! case 'a':
! g_assert(pos + count < size);
! g_memmove(result + pos, bufptr, count);
! pos += count;
! break;
! }
!
! len = len - count;
! bufptr = bufptr + count;
! repeat--;
! if (!repeat && len)
! {
! if (terminator)
! {
! g_assert(pos + 1 < size);
! result[pos++] = terminator;
! }
! else if (seperator)
! {
! g_assert(pos + 1 < size);
! result[pos++] = seperator;
! }
! }
! else if (seperator && len)
! {
! g_assert(pos + 1 < size);
! result[pos++] = seperator;
! }
! }
! }
! result[pos] = 0;
! ptr = g_strdup(result);
! g_free(result);
! return ptr;
! }
+ static gchar *
+ format_oid(subid_t *oid, guint oid_length, SmiNode* node)
+ {
+ char *result;
+ int result_len;
+ int len, i;
+ char *buf;
+ #ifdef HAVE_SMI_H
+ SmiModule *module = NULL;
+ #endif
+
+ result_len = oid_length * 22;
+ #ifdef HAVE_SMI_H
+ if (node) {
+ module = smiGetNodeModule(node);
+ result_len += 5 + strlen(module->name) + strlen(node->name);
+ result_len += (oid_length - node->oidlen)*22;
+ }
+ #endif
+ result = g_malloc(result_len + 1);
+ buf = result;
len = sprintf(buf, "%lu", (unsigned long)oid[0]);
buf += len;
for (i = 1; i < oid_length;i++) {
len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
buf += len;
}
+
+ #ifdef HAVE_SMI_H
+ if (node) {
+ len = sprintf(buf, " (%s::%s", module->name, node->name);
+ buf += len;
+ for (i = node->oidlen; i < oid_length; i++) {
+ len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
+ buf += len;
+ }
+ strcpy(buf, ")");
+ }
+ #endif
+ return result;
}
! static gchar*
! format_var(gushort vb_type, guint8 *vb_octet_string, guint vb_length,
! SmiNode *node)
{
! #ifdef HAVE_SMI_H
! SmiType *typ;
! #endif
! gchar *string;
! char *format;
! int i;
! #ifdef HAVE_SMI_H
! SmiInteger32 integer32;
! SmiUnsigned32 unsigned32;
! SmiNamedNumber *named_number;
! gchar *enumstring;
! #endif
!
! #ifdef HAVE_SMI_H
! typ = smiGetNodeType(node);
! if (typ != NULL)
! format = typ->format;
! else
! format = NULL;
! #else
! format = NULL;
! #endif
!
! if (format == NULL) {
! switch (vb_type) {
!
! case SNMP_INTEGER:
! case SNMP_COUNTER:
! case SNMP_GAUGE:
! case SNMP_TIMETICKS:
! /* XXX - display as "(X) N days, HH:MM:SS.SS"? */
! case SNMP_COUNTER64:
! format = "d";
! break;
!
! case SNMP_OCTETSTR:
! case SNMP_OPAQUE:
! case SNMP_NSAP:
! case SNMP_BITSTR:
! format = "1a";
! for (i = 0; i < vb_length; i++) {
! if (!(isprint(vb_octet_string[i])
! || isspace(vb_octet_string[i]))) {
! /*
! * Oh, dear, it's binary.
! */
! format = "1x ";
! break;
! }
! }
! break;
!
! case SNMP_IPADDR:
! format = "d.";
! break;
!
! default:
! format = NULL;
! break;
! }
! }
!
switch (vb_type) {
case SNMP_INTEGER:
! string = format_integer(vb_octet_string, vb_length, TRUE,
! format);
! #ifdef HAVE_SMI_H
! if (typ != NULL && vb_length <= 4) {
! /*
! * OK, we have a module, and the number fits in
! * an "SmiInteger32". Check if there's an enum
! * for this.
! *
! * XXX - handle "SmiInteger64"?
! */
! integer32 = 0;
! i = 0;
! while (vb_length != 0) {
! integer32 =
! (integer32 << 8) | vb_octet_string[i];
! i++;
! vb_length--;
! }
! for (named_number = smiGetFirstNamedNumber(typ);
! named_number != NULL;
! named_number = smiGetNextNamedNumber(named_number)) {
! if (named_number->value.basetype == SMI_BASETYPE_INTEGER32
! && named_number->value.value.integer32 == integer32)
! break;
! }
! if (named_number != NULL) {
! enumstring = g_malloc(
! strlen(named_number->name) + 1 +
! strlen(string) + 1 + 1);
! sprintf(enumstring, "%s(%s)",
! named_number->name, string);
! g_free(string);
! string = enumstring;
! }
! }
! #endif
break;
case SNMP_COUNTER:
case SNMP_GAUGE:
case SNMP_TIMETICKS:
! case SNMP_COUNTER64:
! string = format_integer(vb_octet_string, vb_length, FALSE,
! format);
! #ifdef HAVE_SMI_H
! if (typ != NULL && vb_length <= 4) {
! /*
! * OK, we have a module, and the number fits in
! * an "SmiUnsigned32". Check if there's an enum
! * for this.
! *
! * XXX - handle "SmiUnsigned64"?
! */
! unsigned32 = 0;
! i = 0;
! while (vb_length != 0) {
! unsigned32 =
! (unsigned32 << 8) | vb_octet_string[i];
! i++;
! vb_length--;
! }
! for (named_number = smiGetFirstNamedNumber(typ);
! named_number != NULL;
! named_number = smiGetNextNamedNumber(named_number)) {
! if (named_number->value.basetype == SMI_BASETYPE_UNSIGNED32
! && named_number->value.value.unsigned32 == unsigned32)
! break;
! }
! if (named_number != NULL) {
! enumstring = g_malloc(
! strlen(named_number->name) + 1 +
! strlen(string) + 1 + 1);
! sprintf(enumstring, "%s(%s)",
! named_number->name, string);
! g_free(string);
! string = enumstring;
! }
! }
! #endif
break;
case SNMP_OCTETSTR:
case SNMP_IPADDR:
case SNMP_OPAQUE:
case SNMP_NSAP:
case SNMP_BITSTR:
! string = format_string(vb_octet_string, vb_length, format);
break;
! default:
! string = NULL;
break;
}
! return string;
}
static int
snmp_variable_decode(proto_tree *snmp_tree, subid_t *variable_oid,
! guint variable_oid_length, ASN1_SCK *asn1, int offset, guint *lengthp,
! SmiNode *node)
{
const guchar *start;
guint length;
***************
*** 640,665 ****
int ret;
guint cls, con, tag;
- gint32 vb_integer_value;
- guint32 vb_uinteger_value;
-
guint8 *vb_octet_string;
subid_t *vb_oid;
guint vb_oid_length;
! gchar vb_display_string[MAX_STRING_LEN]; /* TBC */
! #ifdef HAVE_SPRINT_VALUE
! struct variable_list variable;
! #if defined(HAVE_UCD_SNMP_SNMP_H)
! long value;
! #endif
! #else /* HAVE_SPRINT_VALUE */
! int i;
! gchar *buf;
! int len;
! #endif /* HAVE_SPRINT_VALUE */
/* parse the type of the object */
start = asn1->pointer;
--- 972,986 ----
int ret;
guint cls, con, tag;
guint8 *vb_octet_string;
subid_t *vb_oid;
guint vb_oid_length;
! gchar *vb_display_string;
! SmiNode *oid_node;
! gchar *oid_string;
/* parse the type of the object */
start = asn1->pointer;
***************
*** 684,796 ****
switch (vb_type) {
case SNMP_INTEGER:
- ret = asn1_int32_value_decode(asn1, vb_length,
- &vb_integer_value);
- if (ret != ASN1_ERR_NOERROR)
- return ret;
- length = asn1->pointer - start;
- if (snmp_tree) {
- #ifdef HAVE_SPRINT_VALUE
- #if defined(HAVE_UCD_SNMP_SNMP_H)
- value = vb_integer_value;
- variable.val.integer = &value;
- #elif defined(HAVE_SNMP_SNMP_H)
- variable.val.integer = &vb_integer_value;
- #endif
- format_value(vb_display_string, &variable,
- variable_oid, variable_oid_length, vb_type,
- vb_length);
- proto_tree_add_text(snmp_tree, NullTVB, offset, length,
- "Value: %s", vb_display_string);
- #else
- proto_tree_add_text(snmp_tree, NullTVB, offset, length,
- "Value: %s: %d (%#x)", vb_type_name,
- vb_integer_value, vb_integer_value);
- #endif
- }
- break;
-
case SNMP_COUNTER:
case SNMP_GAUGE:
case SNMP_TIMETICKS:
! ret = asn1_uint32_value_decode(asn1, vb_length,
! &vb_uinteger_value);
! if (ret != ASN1_ERR_NOERROR)
! return ret;
! length = asn1->pointer - start;
! if (snmp_tree) {
! #ifdef HAVE_SPRINT_VALUE
! #if defined(HAVE_UCD_SNMP_SNMP_H)
! value = vb_uinteger_value;
! variable.val.integer = &value;
! #elif defined(HAVE_SNMP_SNMP_H)
! variable.val.integer = &vb_uinteger_value;
! #endif
! format_value(vb_display_string, &variable,
! variable_oid, variable_oid_length, vb_type,
! vb_length);
! proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Value: %s", vb_display_string);
! #else
! proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Value: %s: %u (%#x)", vb_type_name,
! vb_uinteger_value, vb_uinteger_value);
! #endif
! }
! break;
!
case SNMP_OCTETSTR:
case SNMP_IPADDR:
case SNMP_OPAQUE:
case SNMP_NSAP:
case SNMP_BITSTR:
- case SNMP_COUNTER64:
ret = asn1_octet_string_value_decode (asn1, vb_length,
&vb_octet_string);
if (ret != ASN1_ERR_NOERROR)
return ret;
length = asn1->pointer - start;
if (snmp_tree) {
! #ifdef HAVE_SPRINT_VALUE
! variable.val.string = vb_octet_string;
! format_value(vb_display_string, &variable,
! variable_oid, variable_oid_length, vb_type,
! vb_length);
proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Value: %s", vb_display_string);
! #else
! /*
! * If some characters are not printable, display
! * the string as bytes.
! */
! for (i = 0; i < vb_length; i++) {
! if (!(isprint(vb_octet_string[i])
! || isspace(vb_octet_string[i])))
! break;
! }
! if (i < vb_length) {
! /*
! * We stopped, due to a non-printable
! * character, before we got to the end
! * of the string.
! */
! buf = &vb_display_string[0];
! len = sprintf(buf, "%03u", vb_octet_string[0]);
! buf += len;
! for (i = 1; i < vb_length; i++) {
! len = sprintf(buf, ".%03u",
! vb_octet_string[i]);
! buf += len;
! }
! proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Value: %s: %s", vb_type_name,
! vb_display_string);
! } else {
! proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Value: %s: %.*s", vb_type_name,
! (int)vb_length, vb_octet_string);
! }
! #endif
}
g_free(vb_octet_string);
break;
--- 1005,1031 ----
switch (vb_type) {
case SNMP_INTEGER:
case SNMP_COUNTER:
case SNMP_GAUGE:
case SNMP_TIMETICKS:
! case SNMP_COUNTER64:
case SNMP_OCTETSTR:
case SNMP_IPADDR:
case SNMP_OPAQUE:
case SNMP_NSAP:
case SNMP_BITSTR:
ret = asn1_octet_string_value_decode (asn1, vb_length,
&vb_octet_string);
if (ret != ASN1_ERR_NOERROR)
return ret;
length = asn1->pointer - start;
if (snmp_tree) {
! vb_display_string = format_var(vb_type, vb_octet_string,
! vb_length, node);
proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Value: %s: %s", vb_type_name,
! vb_display_string);
! g_free(vb_display_string);
}
g_free(vb_octet_string);
break;
***************
*** 813,830 ****
return ret;
length = asn1->pointer - start;
if (snmp_tree) {
! #ifdef HAVE_SPRINT_VALUE
! variable.val.objid = vb_oid;
! format_value(vb_display_string, &variable,
! variable_oid, variable_oid_length, vb_type,
! vb_length*sizeof (subid_t));
! proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Value: %s", vb_display_string);
#else
! format_oid(vb_display_string, vb_oid, vb_oid_length);
! proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Value: %s: %s", vb_type_name, vb_display_string);
#endif
}
g_free(vb_oid);
break;
--- 1048,1064 ----
return ret;
length = asn1->pointer - start;
if (snmp_tree) {
! #ifdef HAVE_SMI_H
! oid_node = smiGetNodeByOID(vb_oid_length,
! (SmiSubid *)vb_oid);
#else
! oid_node = NULL;
#endif
+ oid_string = format_oid(vb_oid, vb_oid_length,
+ oid_node);
+ proto_tree_add_text(snmp_tree, NullTVB, offset, length,
+ "Value: %s: %s", vb_type_name, oid_string);
+ g_free(oid_string);
}
g_free(vb_oid);
break;
***************
*** 890,896 ****
guint timestamp;
guint timestamp_length;
! gchar oid_string[MAX_STRING_LEN]; /* TBC */
guint variable_bindings_length;
--- 1124,1130 ----
guint timestamp;
guint timestamp_length;
! gchar *oid_string;
guint variable_bindings_length;
***************
*** 898,910 ****
guint variable_length;
subid_t *variable_oid;
guint variable_oid_length;
- #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
- gchar vb_oid_string[MAX_STRING_LEN]; /* TBC */
- #endif
int ret;
guint cls, con, tag;
pdu_type_string = val_to_str(pdu_type, pdu_types,
"Unknown PDU type %#x");
if (check_col(fd, COL_INFO))
--- 1132,1143 ----
guint variable_length;
subid_t *variable_oid;
guint variable_oid_length;
int ret;
guint cls, con, tag;
+ SmiNode *node;
+
pdu_type_string = val_to_str(pdu_type, pdu_types,
"Unknown PDU type %#x");
if (check_col(fd, COL_INFO))
***************
*** 993,1001 ****
return;
}
if (tree) {
! format_oid(oid_string, enterprise, enterprise_length);
proto_tree_add_text(tree, NullTVB, offset, length,
"Enterprise: %s", oid_string);
}
g_free(enterprise);
offset += length;
--- 1226,1242 ----
return;
}
if (tree) {
! #ifdef HAVE_SMI_H
! node = smiGetNodeByOID(enterprise_length,
! (SmiSubid *)enterprise);
! #else
! node = NULL;
! #endif
! oid_string = format_oid(enterprise, enterprise_length,
! node);
proto_tree_add_text(tree, NullTVB, offset, length,
"Enterprise: %s", oid_string);
+ g_free(oid_string);
}
g_free(enterprise);
offset += length;
***************
*** 1132,1160 ****
}
sequence_length += length;
! if (tree) {
! format_oid(oid_string, variable_oid,
! variable_oid_length);
!
! #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
! sprint_objid(vb_oid_string, variable_oid,
! variable_oid_length);
! proto_tree_add_text(tree, NullTVB, offset, sequence_length,
! "Object identifier %d: %s (%s)", vb_index,
! oid_string, vb_oid_string);
#else
!
! proto_tree_add_text(tree, NullTVB, offset, sequence_length,
! "Object identifier %d: %s", vb_index,
! oid_string);
#endif
}
offset += sequence_length;
variable_bindings_length -= sequence_length;
/* Parse the variable's value */
ret = snmp_variable_decode(tree, variable_oid,
! variable_oid_length, &asn1, offset, &length);
if (ret != ASN1_ERR_NOERROR) {
dissect_snmp_parse_error(pd, offset, fd, tree,
"variable", ret);
--- 1373,1398 ----
}
sequence_length += length;
! #ifdef HAVE_SMI_H
! node = smiGetNodeByOID(variable_oid_length,
! (SmiSubid *)variable_oid);
#else
! node = NULL;
#endif
+ if (tree) {
+ oid_string = format_oid(variable_oid,
+ variable_oid_length, node);
+ proto_tree_add_text(tree, NullTVB, offset,
+ sequence_length,
+ "Object identifier %d: %s", vb_index, oid_string);
+ g_free(oid_string);
}
offset += sequence_length;
variable_bindings_length -= sequence_length;
/* Parse the variable's value */
ret = snmp_variable_decode(tree, variable_oid,
! variable_oid_length, &asn1, offset, &length, node);
if (ret != ASN1_ERR_NOERROR) {
dissect_snmp_parse_error(pd, offset, fd, tree,
"variable", ret);
***************
*** 1205,1210 ****
--- 1443,1453 ----
int authpar_length;
int privpar_length;
+ guchar *cengineid_string;
+ guchar *aengineid_string;
+ guchar *authpar_string;
+ guchar *privpar_string;
+
guint pdu_type;
guint pdu_length;
***************
*** 1410,1418 ****
return;
}
if (secur_tree) {
proto_tree_add_text(secur_tree, NullTVB, offset,
length, "Authoritative Engine ID: %s",
! bytes_to_str(aengineid, aengineid_length));
}
g_free(aengineid);
offset += length;
--- 1653,1664 ----
return;
}
if (secur_tree) {
+ aengineid_string = format_string(aengineid,
+ aengineid_length, "1x ");
proto_tree_add_text(secur_tree, NullTVB, offset,
length, "Authoritative Engine ID: %s",
! aengineid_string);
! g_free(aengineid_string);
}
g_free(aengineid);
offset += length;
***************
*** 1462,1470 ****
return;
}
if (secur_tree) {
proto_tree_add_text(secur_tree, NullTVB, offset,
length, "Authentication Parameter: %s",
! bytes_to_str(authpar, authpar_length));
}
g_free(authpar);
offset += length;
--- 1708,1719 ----
return;
}
if (secur_tree) {
+ authpar_string = format_string(authpar,
+ authpar_length, "1x ");
proto_tree_add_text(secur_tree, NullTVB, offset,
length, "Authentication Parameter: %s",
! authpar_string);
! g_free(authpar_string);
}
g_free(authpar);
offset += length;
***************
*** 1476,1484 ****
return;
}
if (secur_tree) {
proto_tree_add_text(secur_tree, NullTVB, offset,
length, "Privacy Parameter: %s",
! bytes_to_str(privpar, privpar_length));
}
g_free(privpar);
offset += length;
--- 1725,1736 ----
return;
}
if (secur_tree) {
+ privpar_string = format_string(privpar,
+ privpar_length, "1x ");
proto_tree_add_text(secur_tree, NullTVB, offset,
length, "Privacy Parameter: %s",
! privpar_string);
! g_free(privpar_string);
}
g_free(privpar);
offset += length;
***************
*** 1532,1540 ****
return;
}
if (snmp_tree) {
proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Context Engine ID: %s",
! bytes_to_str(cengineid, cengineid_length));
}
g_free(cengineid);
offset += length;
--- 1784,1794 ----
return;
}
if (snmp_tree) {
+ cengineid_string = format_string(cengineid,
+ cengineid_length, "1x ");
proto_tree_add_text(snmp_tree, NullTVB, offset, length,
! "Context Engine ID: %s", cengineid_string);
! g_free(cengineid_string);
}
g_free(cengineid);
offset += length;
***************
*** 1602,1614 ****
subid_t *regid;
guint regid_length;
! gchar oid_string[MAX_STRING_LEN]; /* TBC */
proto_tree *smux_tree = NULL;
proto_item *item = NULL;
int ret;
guint cls, con;
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "SMUX");
--- 1856,1870 ----
subid_t *regid;
guint regid_length;
! gchar *oid_string;
proto_tree *smux_tree = NULL;
proto_item *item = NULL;
int ret;
guint cls, con;
+ SmiNode *node;
+
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "SMUX");
***************
*** 1663,1671 ****
return;
}
if (tree) {
! format_oid(oid_string, regid, regid_length);
proto_tree_add_text(smux_tree, NullTVB, offset, length,
"Registration: %s", oid_string);
}
g_free(regid);
offset += length;
--- 1919,1934 ----
return;
}
if (tree) {
! #ifdef HAVE_SMI_H
! node = smiGetNodeByOID(regid_length,
! (SmiSubid *)regid);
! #else
! node = NULL;
! #endif
! oid_string = format_oid(regid, regid_length, node);
proto_tree_add_text(smux_tree, NullTVB, offset, length,
"Registration: %s", oid_string);
+ g_free(oid_string);
}
g_free(regid);
offset += length;
***************
*** 1744,1752 ****
return;
}
if (tree) {
! format_oid(oid_string, regid, regid_length);
proto_tree_add_text(smux_tree, NullTVB, offset, length,
"Registration: %s", oid_string);
}
g_free(regid);
offset += length;
--- 2007,2022 ----
return;
}
if (tree) {
! #ifdef HAVE_SMI_H
! node = smiGetNodeByOID(regid_length,
! (SmiSubid *)regid);
! #else
! node = NULL;
! #endif
! oid_string = format_oid(regid, regid_length, node);
proto_tree_add_text(smux_tree, NullTVB, offset, length,
"Registration: %s", oid_string);
+ g_free(oid_string);
}
g_free(regid);
offset += length;
***************
*** 1853,1864 ****
void
proto_register_snmp(void)
{
- #ifdef linux
- void *libsnmp_handle;
- int (*snmp_set_suffix_only_p)(int);
- int (*ds_set_int_p)(int, int, int);
- #endif
-
static hf_register_info hf[] = {
{ &hf_snmpv3_flags,
{ "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
--- 2123,2128 ----
***************
*** 1881,1979 ****
&ett_secur,
};
! #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
! /* UCD or CMU SNMP */
! init_mib();
! #ifdef HAVE_UCD_SNMP_SNMP_H
! #ifdef linux
! /* As per the comment near the beginning of the file, UCD SNMP 4.1.1
! changed "snmp_set_suffix_only()" from a function to a macro,
! removing "snmp_set_suffix_only()" from the library; this means
! that binaries that call "snmp_set_suffix_only()" and
! that are linked against shared libraries from earlier versions
! of the UCD SNMP library won't run with shared libraries from
! 4.1.1.
!
! This is a problem on Red Hat Linux, as pre-6.2 releases
! came with pre-4.1.1 UCD SNMP, while 6.2 comes the 4.1.1.
! Versions of Ethereal built on pre-6.2 releases don't run
! on 6.2, and the current Ethereal RPMs are built on pre-6.2
! releases, causing problems when users running 6.2 download
! them and try to use them.
!
! Building the releases on 6.2 isn't necessarily the answer,
! as "snmp_set_suffix_only()" expands to a call to "ds_set_int()"
! with a second argument not supported by at least some pre-4.1.1
! versions of the library - it appears that the 4.0.1 library,
! at least, checks for invalid arguments and returns an error
! rather than stomping random memory, but that means that you
! won't get get OIDs displayed as module-name::sub-OID.
!
! So we use a trick similar to one I've seen mentioned as
! used in Windows applications to let you build binaries
! that run on many different versions of Windows 9x and
! Windows NT, that use features present on later versions
! if run on those later versions, but that avoid calling,
! when run on older versions, routines not present on those
! older versions.
!
! I.e., we load "libsnmp.so" with "dlopen()", and call
! "dlsym()" to try to find "snmp_set_suffix_only()"; if we
! don't find it, we make the appropriate call to
! "ds_set_int()" instead.
!
! We do this only on Linux, for now, as we've only seen the
! problem on Red Hat; it may show up on other OSes that bundle
! UCD SNMP, or on OSes where it's not bundled but for which
! binary packages are built that link against a shared version
! of the UCD SNMP library. If we run into one of those, we
! can do this under those OSes as well, *if* "dlopen()" makes
! the run-time linker use the same search rules as it uses when
! loading libraries with which the application is linked.
!
! (Perhaps we could use the GLib wrappers for run-time linking,
! *if* they're thin enough; however, as this code is currently
! used only on Linux, we don't worry about that for now.) */
!
! libsnmp_handle = dlopen("libsnmp.so", RTLD_LAZY|RTLD_GLOBAL);
! if (libsnmp_handle == NULL) {
! /* We didn't find "libsnmp.so"; we may be linked
! statically, in which case whatever call the following
! line of code makes will presumably work, as
! we have the routine it calls wired into our binary. */
! snmp_set_suffix_only(2);
! } else {
! /* OK, we have it loaded. Do we have
! "snmp_set_suffix_only()"? */
! snmp_set_suffix_only_p = dlsym(libsnmp_handle,
! "snmp_set_suffix_only");
! if (snmp_set_suffix_only_p != NULL) {
! /* Yes - call it. */
! (*snmp_set_suffix_only_p)(2);
! } else {
! /* No; do we have "ds_set_int()"? */
! ds_set_int_p = dlsym(libsnmp_handle, "ds_set_int");
! if (ds_set_int_p != NULL) {
! /* Yes - cal it with DS_LIBRARY_ID,
! DS_LIB_PRINT_SUFFIX_ONLY, and 2 as
! arguments.
!
! We do *not* use DS_LIBRARY_ID or
! DS_LIB_PRINT_SUFFIX_ONLY by name, so that
! we don't require that Ethereal be built
! with versions of UCD SNMP that include
! that value; instead, we use their values
! in UCD SNMP 4.1.1, which are 0 and 4,
! respectively. */
! (*ds_set_int_p)(0, 4, 2);
! }
! }
! }
! #else /* linux */
! snmp_set_suffix_only(2);
! #endif /* linux */
! #endif /* HAVE_UCD_SNMP_SNMP_H */
! #endif /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
proto_snmp = proto_register_protocol("Simple Network Management Protocol", "snmp");
proto_smux = proto_register_protocol("SNMP Multiplex Protocol", "smux");
proto_register_field_array(proto_snmp, hf, array_length(hf));
--- 2145,2153 ----
&ett_secur,
};
! #ifdef HAVE_SMI_H
! smiInit("ethereal");
! #endif
proto_snmp = proto_register_protocol("Simple Network Management Protocol", "snmp");
proto_smux = proto_register_protocol("SNMP Multiplex Protocol", "smux");
proto_register_field_array(proto_snmp, hf, array_length(hf));
- Follow-Ups:
- Re: [ethereal-dev] packet-snmp.c and libsmi
- From: Juergen Schoenwaelder
- Re: [ethereal-dev] packet-snmp.c and libsmi
- References:
- Re: [ethereal-dev] packet-snmp.c and libsmi
- From: Guy Harris
- Re: [ethereal-dev] packet-snmp.c and libsmi
- From: Jochen Friedrich
- Re: [ethereal-dev] packet-snmp.c and libsmi
- From: Guy Harris
- Re: [ethereal-dev] packet-snmp.c and libsmi
- From: Guy Harris
- Re: [ethereal-dev] packet-snmp.c and libsmi
- Prev by Date: Re: [ethereal-dev] SNMP Bug Report
- Next by Date: Re: [ethereal-dev] Possible crash problem in file.c
- Previous by thread: Re: [ethereal-dev] packet-snmp.c and libsmi
- Next by thread: Re: [ethereal-dev] packet-snmp.c and libsmi
- Index(es):





