Ethereal-dev: Re: [ethereal-dev] SNMP dissector
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, 14 May 2000 21:34:18 -0700
On Fri, Apr 21, 2000 at 04:52:57PM +0200, Jochen Friedrich wrote: > Hi Guy, > > > It currently appears to display the OID 1.3.6.1.2.1 as ":iso" in the > > decode of a GET-NEXT request asking for that object, rather than as, > > say, ".iso.org.dod.internet.mgmt.mib-2", as a version using the UCD SNMP > > library does. > > > > Is there any way to fix that? > > The appended patch should fix that one. The later version you sent does even better, but would it be better to 1) give the OID, with every component that has a name shown with the name, and every other component shown numerically, e.g. displaying 1.3.6.1.4.1.789.1.8.1.1.0 (which I think is in one of NetApp's MIBs) as iso.org.dod.internet.private.enterprises.789.1.8.1.1.0 or to 2) display all the stuff that can be displayed symbolically as "module:name", e.g. displaying that OID as SNMPv2-SMI:enterprises.789.1.8.1.1.0 ? I.e., is it more obvious what "iso.org.dod.internet.private.enterprises" is or what "SNMPv2-SMI:enterprises" is? Also, there appears to be a memory leak in "format_oid_name()" - when it calls itself, it passes its "name" argument along as the "name" argument, which, I think, means that all strings allocated by "format_oid_name()", except for the one allocated by the call to "format_oid_name()" from "format_oid()", will be leaked. > Additionally, you might have to add the appended smi.conf to /usr/etc > (if you use the RPM) or /usr/local/etc. That's a bit of an unfortunate requirement - I'd prefer it if users could just configure/make/make install both libsmi and Ethereal, without having to install or tweak a configuration file by hand. > > In addition, are there a significant number of systems that might have > > libsmi 0.1 installed? If so, we should either > > > > 1) make it compile with libsmi 0.1 or 0.2, depending on which is > > installed > > I wouldn't mess with 0.1 anymore. I'm not sure if many people did already > install libsmi, at all. OK; as I remember, I saw some note on the tcpdump-workers list about tcpdump not working with libsmi 0.2, and was worried that this might be an issue. Is the API (and the ABI!) likely to change in an incompatible fashion in a future release? If so, that could cause this problem to show up again. > However, loading all possible MIBs into ethereal will take some time. But > it's the same with UCD... ...except that it takes significantly *more* time with libsmi than with UCD SNMP; perhaps that's just because there are fewer MIBs that come with UCD SNMP, but, on my 450 MHz PII/128MB memory machine, it takes several seconds longer for an Ethereal linked against libsmi to start up than it takes for an Ethereal linked against UCD SNMP to start up (even after all the pages of the executable and the MIB files are cached in memory after having run both programs once). Also, Ethereal should at least build and run on systems without libsmi, even if it can't do as good a job of dissecting SNMP as on systems with libsmi; I've attached a patch, against the current CVS tree (which already has your SMUX and SNMPv3 changes, so those changes *aren't* in this patch, just changes to that code to use libsmi), which 1) allows it to compile if libsmi isn't available; 2) moves "g_snmp_tag_cls2syntax()" back next to the table it uses, and moves a couple of other high-level routines with it; 3) makes the SMUX dissector static (it's not called outside "packet-snmp.c"), which means that no change to "packet-snmp.h" is needed.
Index: packet-snmp.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-snmp.c,v retrieving revision 1.31 diff -c -r1.31 packet-snmp.c *** packet-snmp.c 2000/05/15 03:15:11 1.31 --- packet-snmp.c 2000/05/15 04:00:26 *************** *** 48,188 **** #define MAX_STRING_LEN 1024 /* TBC */ #include <glib.h> #include "packet.h" #include "etypes.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[.x] makes "snmp_set_full_objid()" a macro - * that calls "ds_set_boolean()" with the first two arguments - * being DS_LIBRARY_ID and DS_LIB_PRINT_FULL_OID; this means that, - * when building with 4.1[.x], we need to arrange that - * <ucd-snmp/default_store.h> is included, to define those two values - * and to declare "ds_set_boolean()". - * - * 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_full_objid - # 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" --- 48,61 ---- #define MAX_STRING_LEN 1024 /* TBC */ #include <glib.h> + #ifdef HAVE_SMI_H + #include <smi.h> + #else + typedef void SmiNode; + #endif #include "packet.h" #include "etypes.h" #include "asn1.h" #include "packet-snmp.h" *************** *** 464,469 **** --- 337,669 ---- {0, 0, -1, NULL} }; + 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; + } + /* * NAME: g_snmp_tag_cls2syntax * SYNOPSIS: gboolean g_snmp_tag_cls2syntax *************** *** 550,560 **** } 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++) { --- 750,796 ---- } static void ! format_oid_name(subid_t *oid, guint oid_length, char **name, guint name_length, ! SmiNode *node) { ! #ifdef HAVE_SMI_H ! SmiNode *child; ! #endif ! int len, i; ! char *buf; + #ifdef HAVE_SMI_H + if (node) { + if (node->oidlen > 1) { + child = smiGetParentNode(node); + name_length += strlen(node->name) +1; + format_oid_name(oid, oid_length, name, name_length, + child); + strcat (*name, "."); + if (node->name) + strcat (*name, node->name); + else + strcat (*name, "<unnamed>"); + return; + } + *name = g_malloc(name_length); + buf = *name; + 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; + } + strcat(*name, " ("); + if (node->name) + strcat (*name, node->name); + else + strcat (*name, "<unnamed>"); + return; + } + #endif + *name = g_malloc(name_length); + buf = *name; len = sprintf(buf, "%lu", (unsigned long)oid[0]); buf += len; for (i = 1; i < oid_length;i++) { *************** *** 563,630 **** } } ! #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; --- 799,998 ---- } } ! gchar * ! format_oid(subid_t *oid, guint oid_length, SmiNode* node) { ! char *result; ! #ifdef HAVE_SMI_H ! int len, i; ! char *buf; ! #endif ! ! result = NULL; ! format_oid_name(oid, oid_length, &result, oid_length * 22 + 5, node); ! #ifdef HAVE_SMI_H ! if (node) { ! buf = result + strlen(result); ! for (i = node->oidlen; i < oid_length;i++) { ! len = sprintf(buf, ".%lu", (unsigned long)oid[i]); ! buf += len; ! } ! strcat(result, ")"); ! } ! #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; *************** *** 635,660 **** 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; --- 1003,1017 ---- 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; *************** *** 679,791 **** 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; --- 1036,1062 ---- 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; *************** *** 808,825 **** 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; --- 1079,1095 ---- 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; *************** *** 856,862 **** return ASN1_ERR_NOERROR; } ! static void dissect_common_pdu(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, ASN1_SCK asn1, guint pdu_type, const guchar *start) { --- 1126,1132 ---- return ASN1_ERR_NOERROR; } ! void dissect_common_pdu(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, ASN1_SCK asn1, guint pdu_type, const guchar *start) { *************** *** 885,891 **** guint timestamp; guint timestamp_length; ! gchar oid_string[MAX_STRING_LEN]; /* TBC */ guint variable_bindings_length; --- 1155,1161 ---- guint timestamp; guint timestamp_length; ! gchar *oid_string; guint variable_bindings_length; *************** *** 893,905 **** 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)) --- 1163,1174 ---- 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)) *************** *** 988,996 **** 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; --- 1257,1273 ---- 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; *************** *** 1127,1155 **** } 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(snmp_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); --- 1404,1429 ---- } 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); *************** *** 1200,1205 **** --- 1474,1484 ---- int authpar_length; int privpar_length; + guchar *cengineid_string; + guchar *aengineid_string; + guchar *authpar_string; + guchar *privpar_string; + guint pdu_type; guint pdu_length; *************** *** 1405,1413 **** 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; --- 1684,1695 ---- 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; *************** *** 1457,1465 **** 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; --- 1739,1750 ---- 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; *************** *** 1471,1479 **** 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; --- 1756,1767 ---- 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; *************** *** 1527,1535 **** 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; --- 1815,1825 ---- 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; *************** *** 1571,1577 **** static void dissect_smux_pdu(const u_char *pd, int offset, frame_data *fd, ! proto_tree *tree, char *proto_name, int proto, gint ett) { ASN1_SCK asn1; const guchar *start; --- 1861,1867 ---- static void dissect_smux_pdu(const u_char *pd, int offset, frame_data *fd, ! proto_tree *tree, int proto, gint ett) { ASN1_SCK asn1; const guchar *start; *************** *** 1597,1611 **** 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, proto_name); if (tree) { item = proto_tree_add_item(tree, proto, NullTVB, offset, --- 1887,1903 ---- 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"); if (tree) { item = proto_tree_add_item(tree, proto, NullTVB, offset, *************** *** 1627,1632 **** --- 1919,1925 ---- "PDU type", ret); return; } + /* Dissect SMUX here */ if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) { pdu_type_string = val_to_str(pdu_type, smux_types, *************** *** 1658,1666 **** 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; --- 1951,1966 ---- 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; *************** *** 1739,1747 **** 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; --- 2039,2054 ---- 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; *************** *** 1842,1848 **** static void dissect_smux(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { ! dissect_smux_pdu(pd, offset, fd, tree, "SMUX", proto_smux, ett_smux); } void --- 2149,2155 ---- static void dissect_smux(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { ! dissect_smux_pdu(pd, offset, fd, tree, proto_smux, ett_smux); } void *************** *** 1874,1885 **** &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 ! snmp_set_full_objid(TRUE); ! #endif #endif proto_snmp = proto_register_protocol("Simple Network Management Protocol", "snmp"); proto_smux = proto_register_protocol("SNMP Multiplex Protocol", "smux"); --- 2181,2188 ---- &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");
- Prev by Date: Re: [ethereal-dev] SNMP Patch
- Next by Date: Re: [ethereal-dev] Visual Studio Workspaces for Win32 port
- Previous by thread: Re: [ethereal-dev] SNMP Patch
- Next by thread: [ethereal-dev] Problem (feature?) after trying to stop a capture
- Index(es):