diff options
Diffstat (limited to 'packet-snmp.c')
-rw-r--r-- | packet-snmp.c | 1428 |
1 files changed, 711 insertions, 717 deletions
diff --git a/packet-snmp.c b/packet-snmp.c index 82f22f4ee2..b4e058a565 100644 --- a/packet-snmp.c +++ b/packet-snmp.c @@ -2,13 +2,18 @@ * Routines for SNMP (simple network management protocol) * D.Jorand (c) 1998 * - * $Id: packet-snmp.c,v 1.15 1999/12/05 02:32:38 guy Exp $ + * $Id: packet-snmp.c,v 1.16 1999/12/10 09:49:27 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@unicom.net> * Copyright 1998 Didier Jorand * + * Some stuff from: * + * GXSNMP -- An snmp mangament application + * Copyright (C) 1998 Gregory McLean & Jochen Friedrich + * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -28,12 +33,6 @@ # include "config.h" #endif -#if defined(HAVE_UCD_SNMP_SNMP_H) -# define WITH_SNMP_UCD 1 -#elif defined(HAVE_SNMP_SNMP_H) -# define WITH_SNMP_CMU 1 -#endif - #include <stdio.h> #include <string.h> #include <ctype.h> @@ -46,184 +45,50 @@ # include <netinet/in.h> #endif -#include <glib.h> -#include "packet.h" - -#include "packet-snmp.h" - -static int proto_snmp = -1; - -static gint ett_snmp = -1; - -#if defined(WITH_SNMP_CMU) || defined(WITH_SNMP_UCD) - -#define in_addr_t u_int - -#ifdef WITH_SNMP_UCD -/* should be defined only if supported in ucd-snmp */ -#define OPAQUE_SPECIAL_TYPES 1 +#if defined(HAVE_UCD_SNMP_SNMP_H) #include <ucd-snmp/asn1.h> -#include <ucd-snmp/snmp.h> -#include <ucd-snmp/snmp_api.h> -#include <ucd-snmp/snmp_impl.h> #include <ucd-snmp/mib.h> - -typedef long SNMP_INT; -typedef unsigned long SNMP_UINT; -#define OID_FORMAT_STRING "%ld" -#define OID_FORMAT_STRING1 ".%ld" -#endif - -#ifdef WITH_SNMP_CMU +#include <ucd-snmp/parse.h> +#elif defined(HAVE_SNMP_SNMP_H) #include <snmp/snmp.h> -#include <snmp/snmp_impl.h> - -#ifndef MAX_NAME_LEN -#define MAX_NAME_LEN SNMP_MAX_LEN -#endif - -#define SNMP_MSG_GET GET_REQ_MSG -#define SNMP_MSG_GETNEXT GETNEXT_REQ_MSG -#define SNMP_MSG_RESPONSE GET_RSP_MSG -#define SNMP_MSG_SET SET_REQ_MSG -#define SNMP_MSG_TRAP TRP_REQ_MSG - -#ifdef GETBULK_REQ_MSG -#define SNMP_MSG_GETBULK GETBULK_REQ_MSG -#else -#define SNMP_MSG_GETBULK SNMP_PDU_GETBULK -#endif - -#ifdef INFORM_REQ_MSG -#define SNMP_MSG_INFORM INFORM_REQ_MSG -#else -#define SNMP_MSG_INFORM SNMP_PDU_INFORM -#endif - -#ifdef TRP2_REQ_MSG -#define SNMP_MSG_TRAP2 TRP2_REQ_MSG -#else -#define SNMP_MSG_TRAP2 SNMP_PDU_V2TRAP -#endif - -#ifdef REPORT_MSG -#define SNMP_MSG_REPORT REPORT_MSG -#else -#define SNMP_MSG_REPORT SNMP_PDU_REPORT -#endif - -#ifndef SNMP_VERSION_2c -#define SNMP_VERSION_2c 1 -#endif -#ifndef SNMP_VERSION_2u -#define SNMP_VERSION_2u 2 -#endif -#ifndef SNMP_VERSION_3 -#define SNMP_VERSION_3 3 -#endif - -#ifdef SNMP_TRAP_AUTHENTICATIONFAILURE -#define SNMP_TRAP_AUTHFAIL SNMP_TRAP_AUTHENTICATIONFAILURE -#endif - -#ifndef COMMUNITY_MAX_LEN -#define COMMUNITY_MAX_LEN 256 -#endif - -#ifndef ASN_INTEGER -#define ASN_INTEGER SMI_INTEGER -#endif -#ifndef ASN_OCTET_STR -#define ASN_OCTET_STR SMI_STRING -#endif -#ifndef ASN_OBJECT_ID -#define ASN_OBJECT_ID SMI_OBJID -#endif -#ifndef ASN_NULL -#define ASN_NULL SMI_NULLOBJ -#endif - -#ifndef ASN_IPADDRESS - #ifdef IPADDRESS - #define ASN_IPADDRESS IPADDRESS - #else - #define ASN_IPADDRESS SMI_IPADDRESS - #endif -#endif - -#ifndef ASN_COUNTER - #ifdef COUNTER - #define ASN_COUNTER COUNTER - #else - #define ASN_COUNTER SMI_COUNTER32 - #endif -#endif - -#ifndef ASN_GAUGE - #ifdef GAUGE - #define ASN_GAUGE GAUGE - #else - #define ASN_GAUGE SMI_GAUGE32 - #endif #endif -#ifndef ASN_TIMETICKS - #ifdef TIMETICKS - #define ASN_TIMETICKS TIMETICKS - #else - #define ASN_TIMETICKS SMI_TIMETICKS - #endif -#endif - -#ifndef ASN_OPAQUE - #ifdef OPAQUE - #define ASN_OPAQUE OPAQUE - #else - #define ASN_OPAQUE SMI_OPAQUE - #endif -#endif +#include <glib.h> +#include "packet.h" +#include "asn1.h" -#ifndef ASN_COUNTER64 - #ifdef COUNTER64 - #define ASN_COUNTER64 COUNTER64 - #else - #define ASN_COUNTER64 SMI_COUNTER64 - #endif -#endif +#include "packet-snmp.h" -#ifndef ASN_UINTEGER -/* historic: should not be used! */ -#define ASN_UINTEGER (ASN_APPLICATION | 7) -#endif -#ifndef ASN_NSAP -/* historic: should not be used! */ -#define ASN_NSAP (ASN_APPLICATION | 5) -#endif -#ifndef SNMP_NOSUCHOBJECT -#define SNMP_NOSUCHOBJECT SMI_NOSUCHOBJECT -#endif -#ifndef SNMP_NOSUCHINSTANCE -#define SNMP_NOSUCHINSTANCE SMI_NOSUCHINSTANCE -#endif -#ifndef SNMP_ENDOFMIBVIEW -#define SNMP_ENDOFMIBVIEW SMI_ENDOFMIBVIEW -#endif +static int proto_snmp = -1; -typedef int SNMP_INT; -typedef unsigned int SNMP_UINT; -#define OID_FORMAT_STRING "%d" -#define OID_FORMAT_STRING1 ".%d" +static gint ett_snmp = -1; -#endif /* WITH_SNMP_CMU */ +/* Protocol version numbers */ +#define SNMP_VERSION_1 0 +#define SNMP_VERSION_2c 1 +#define SNMP_VERSION_2u 2 +#define SNMP_VERSION_3 3 static const value_string versions[] = { - { SNMP_VERSION_1, "VERSION 1" }, - { SNMP_VERSION_2c, "VERSION 2C" }, - { SNMP_VERSION_2u, "VERSION 2U" }, - { SNMP_VERSION_3, "VERSION 3" }, + { SNMP_VERSION_1, "1" }, + { SNMP_VERSION_2c, "2C" }, + { SNMP_VERSION_2u, "2U" }, + { SNMP_VERSION_3, "3" }, { 0, NULL }, }; +/* PDU types */ +#define SNMP_MSG_GET 0 +#define SNMP_MSG_GETNEXT 1 +#define SNMP_MSG_RESPONSE 2 +#define SNMP_MSG_SET 3 +#define SNMP_MSG_TRAP 4 + +#define SNMP_MSG_GETBULK 5 +#define SNMP_MSG_INFORM 6 +#define SNMP_MSG_TRAP2 7 +#define SNMP_MSG_REPORT 8 + static const value_string pdu_types[] = { { SNMP_MSG_GET, "GET" }, { SNMP_MSG_GETNEXT, "GET-NEXT" }, @@ -237,29 +102,61 @@ static const value_string pdu_types[] = { { 0, NULL } }; +/* Error status values */ +#define SNMP_ERR_NOERROR 0 +#define SNMP_ERR_TOOBIG 1 +#define SNMP_ERR_NOSUCHNAME 2 +#define SNMP_ERR_BADVALUE 3 +#define SNMP_ERR_READONLY 4 +#define SNMP_ERR_GENERROR 5 + +#define SNMP_ERR_NOACCESS 6 +#define SNMP_ERR_WRONGTYPE 7 +#define SNMP_ERR_WRONGLENGTH 8 +#define SNMP_ERR_WRONGENCODING 9 +#define SNMP_ERR_WRONGVALUE 10 +#define SNMP_ERR_NOCREATION 11 +#define SNMP_ERR_INCONSISTENTVALUE 12 +#define SNMP_ERR_RESOURCEUNAVAILABLE 13 +#define SNMP_ERR_COMMITFAILED 14 +#define SNMP_ERR_UNDOFAILED 15 +#define SNMP_ERR_AUTHORIZATIONERROR 16 +#define SNMP_ERR_NOTWRITABLE 17 +#define SNMP_ERR_INCONSISTENTNAME 18 + static const value_string error_statuses[] = { { SNMP_ERR_NOERROR, "NO ERROR" }, - { SNMP_ERR_TOOBIG, "ERROR: TOOBIG" }, - { SNMP_ERR_NOSUCHNAME, "ERROR: NO SUCH NAME" }, - { SNMP_ERR_BADVALUE, "ERROR: BAD VALUE" }, - { SNMP_ERR_READONLY, "ERROR: READ ONLY" }, - { SNMP_ERR_GENERR, "ERROR: GENERIC ERROR" }, - { SNMP_ERR_NOACCESS, "ERROR: NO ACCESS" }, - { SNMP_ERR_WRONGTYPE, "ERROR: WRONG TYPE" }, - { SNMP_ERR_WRONGLENGTH, "ERROR: WRONG LENGTH" }, - { SNMP_ERR_WRONGENCODING, "ERROR: WRONG ENCODING" }, - { SNMP_ERR_WRONGVALUE, "ERROR: WRONG VALUE" }, - { SNMP_ERR_NOCREATION, "ERROR: NO CREATION" }, - { SNMP_ERR_INCONSISTENTVALUE, "ERROR: INCONSISTENT VALUE" }, - { SNMP_ERR_RESOURCEUNAVAILABLE, "ERROR: RESOURCE UNAVAILABLE" }, - { SNMP_ERR_COMMITFAILED, "ERROR: COMMIT FAILED" }, - { SNMP_ERR_UNDOFAILED, "ERROR: UNDO FAILED" }, - { SNMP_ERR_AUTHORIZATIONERROR, "ERROR: AUTHORIZATION ERROR" }, - { SNMP_ERR_NOTWRITABLE, "ERROR: NOT WRITABLE" }, - { SNMP_ERR_INCONSISTENTNAME, "ERROR: INCONSISTENT NAME" }, + { SNMP_ERR_TOOBIG, "TOOBIG" }, + { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" }, + { SNMP_ERR_BADVALUE, "BAD VALUE" }, + { SNMP_ERR_READONLY, "READ ONLY" }, + { SNMP_ERR_GENERROR, "GENERIC ERROR" }, + { SNMP_ERR_NOACCESS, "NO ACCESS" }, + { SNMP_ERR_WRONGTYPE, "WRONG TYPE" }, + { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" }, + { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" }, + { SNMP_ERR_WRONGVALUE, "WRONG VALUE" }, + { SNMP_ERR_NOCREATION, "NO CREATION" }, + { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" }, + { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" }, + { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" }, + { SNMP_ERR_UNDOFAILED, "UNDO FAILED" }, + { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" }, + { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" }, + { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" }, { 0, NULL } }; +/* General SNMP V1 Traps */ + +#define SNMP_TRAP_COLDSTART 0 +#define SNMP_TRAP_WARMSTART 1 +#define SNMP_TRAP_LINKDOWN 2 +#define SNMP_TRAP_LINKUP 3 +#define SNMP_TRAP_AUTHFAIL 4 +#define SNMP_TRAP_EGPNEIGHBORLOSS 5 +#define SNMP_TRAP_ENTERPRISESPECIFIC 6 + static const value_string trap_types[] = { { SNMP_TRAP_COLDSTART, "COLD START" }, { SNMP_TRAP_WARMSTART, "WARM START" }, @@ -271,6 +168,151 @@ static const value_string trap_types[] = { { 0, NULL } }; +/* SNMP Tags */ + +#define SNMP_IPA 0 /* IP Address */ +#define SNMP_CNT 1 /* Counter (Counter32) */ +#define SNMP_GGE 2 /* Gauge (Gauge32) */ +#define SNMP_TIT 3 /* TimeTicks */ +#define SNMP_OPQ 4 /* Opaque */ +#define SNMP_NSP 5 /* NsapAddress */ +#define SNMP_C64 6 /* Counter64 */ +#define SNMP_U32 7 /* Uinteger32 */ + +#define SERR_NSO 0 +#define SERR_NSI 1 +#define SERR_EOM 2 + +/* SNMPv1 Types */ + +#define SNMP_NULL 0 +#define SNMP_INTEGER 1 /* l */ +#define SNMP_OCTETSTR 2 /* c */ +#define SNMP_DISPLAYSTR 2 /* c */ +#define SNMP_OBJECTID 3 /* ul */ +#define SNMP_IPADDR 4 /* uc */ +#define SNMP_COUNTER 5 /* ul */ +#define SNMP_GAUGE 6 /* ul */ +#define SNMP_TIMETICKS 7 /* ul */ +#define SNMP_OPAQUE 8 /* c */ + +/* additional SNMPv2 Types */ + +#define SNMP_UINTEGER 5 /* ul */ +#define SNMP_BITSTR 9 /* uc */ +#define SNMP_NSAP 10 /* uc */ +#define SNMP_COUNTER64 11 /* ul */ +#define SNMP_NOSUCHOBJECT 12 +#define SNMP_NOSUCHINSTANCE 13 +#define SNMP_ENDOFMIBVIEW 14 + +typedef struct _SNMP_CNV SNMP_CNV; + +struct _SNMP_CNV +{ + guint class; + guint tag; + gint syntax; + gchar *name; +}; + +static SNMP_CNV SnmpCnv [] = +{ + {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"}, + {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"}, + {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"}, + {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"}, + {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"}, + {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */ + {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */ + {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"}, + {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"}, + +/* SNMPv2 data types and errors */ + + {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"}, + {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"}, + {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"}, + {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"}, + {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"}, + {0, 0, -1, NULL} +}; + +/* + * NAME: g_snmp_tag_cls2syntax + * SYNOPSIS: gboolean g_snmp_tag_cls2syntax + * ( + * guint tag, + * guint cls, + * gushort *syntax + * ) + * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name. + * See SnmpCnv for conversion. + * RETURNS: name on success, NULL on failure + */ + +static gchar * +snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax) +{ + SNMP_CNV *cnv; + + cnv = SnmpCnv; + while (cnv->syntax != -1) + { + if (cnv->tag == tag && cnv->class == cls) + { + *syntax = cnv->syntax; + return cnv->name; + } + cnv++; + } + return NULL; +} + +static void +dissect_snmp_parse_error(const u_char *pd, int offset, frame_data *fd, + proto_tree *tree, const char *field_name, int ret) +{ + const gchar *errstr; + + if (check_col(fd, COL_INFO)) { + switch (ret) { + + case ASN1_ERR_EMPTY: + errstr = "Ran out of data"; + break; + + case ASN1_ERR_EOC_MISMATCH: + errstr = "EOC mismatch"; + break; + + case ASN1_ERR_WRONG_TYPE: + errstr = "Wrong type for that item"; + break; + + case ASN1_ERR_LENGTH_NOT_DEFINITE: + errstr = "Length was indefinite"; + break; + + case ASN1_ERR_LENGTH_MISMATCH: + errstr = "Length mismatch"; + break; + + case ASN1_ERR_WRONG_LENGTH_FOR_TYPE: + errstr = "Wrong length for that item's type"; + break; + + default: + errstr = "Unknown error"; + break; + } + col_add_fstr(fd, COL_INFO, + "ERROR: Couldn't parse %s: %s", field_name, errstr); + } + + dissect_data(pd, offset, fd, tree); +} + static void dissect_snmp_error(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, const char *message) @@ -281,640 +323,592 @@ dissect_snmp_error(const u_char *pd, int offset, frame_data *fd, 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; + } +} + +static int +snmp_variable_decode(proto_tree *snmp_tree, ASN1_SCK *asn1, int offset, + guint *lengthp) +{ + const guchar *start; + guint length; + gboolean def; + guint vb_length; + gushort vb_type; + gchar *vb_type_name; + int ret; + guint cls, con, tag; + + gint32 vb_integer_value; + guint32 vb_uinteger_value; + + guint8 *vb_octet_string; + gchar vb_string[MAX_NAME_LEN*6]; /* TBC */ + + subid_t *vb_oid; + guint vb_oid_length; + + int i; + gchar *buf; + int len; + + /* parse the type of the object */ + start = asn1->pointer; + ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length); + if (ret != ASN1_ERR_NOERROR) + return ret; + if (!def) + return ASN1_ERR_LENGTH_NOT_DEFINITE; + + /* Convert the class, constructed flag, and tag to a type. */ + vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type); + if (vb_type_name == NULL) + return -1; /* XXX - do something here */ + + /* parse the value */ + 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) { + proto_tree_add_text(snmp_tree, offset, length, + "Value: <%s> %d (%#x)", vb_type_name, + vb_integer_value, vb_integer_value); + } + 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) { + proto_tree_add_text(snmp_tree, offset, length, + "Value: <%s> %u (%#x)", vb_type_name, + vb_integer_value, vb_uinteger_value); + } + break; + + case SNMP_OCTETSTR: + case SNMP_IPADDR: + case SNMP_OPAQUE: + case SNMP_NSAP: + 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) { + /* + * 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_string[0]; + len = sprintf(buf, "%03u", vb_octet_string[0]); + for (i = 1; i < vb_length; i++) { + len = sprintf(buf, ".%03u", + vb_octet_string[i]); + buf += len; + } + proto_tree_add_text(snmp_tree, offset, length, + "Value: <%s> %s", vb_type_name, vb_string); + } else { + proto_tree_add_text(snmp_tree, offset, length, + "Value: <%s> %.*s", vb_type_name, vb_length, + vb_octet_string); + } + } + g_free(vb_octet_string); + break; + + case SNMP_NULL: + ret = asn1_null_decode (asn1, vb_length); + if (ret != ASN1_ERR_NOERROR) + return ret; + length = asn1->pointer - start; + if (snmp_tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Value: <%s>", vb_type_name); + } + break; + + case SNMP_OBJECTID: + ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid, + &vb_oid_length); + if (ret != ASN1_ERR_NOERROR) + return ret; + length = asn1->pointer - start; + if (snmp_tree) { + format_oid(vb_string, vb_oid, vb_oid_length); + proto_tree_add_text(snmp_tree, offset, length, + "Value: <%s> %s", vb_type_name); + } + g_free(vb_oid); + break; + + case SNMP_NOSUCHOBJECT: + length = asn1->pointer - start; + if (snmp_tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Value: <err> no such object"); + } + break; + + case SNMP_NOSUCHINSTANCE: + length = asn1->pointer - start; + if (snmp_tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Value: <err> no such instance"); + } + break; + + case SNMP_ENDOFMIBVIEW: + length = asn1->pointer - start; + if (snmp_tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Value: <err> end of mib view"); + } + break; + + default: + length = asn1->pointer - start; + if (snmp_tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Value: <unsupported type>"); + } + } + *lengthp = length; + return ASN1_ERR_NOERROR; +} + void dissect_snmp_pdu(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, char *proto_name, int proto, gint ett) { - int length=fd->pkt_len-offset; - u_char *data, *tmp_data; - - int all_length, header_length; - u_char type, pdu_type; - int pdu_type_length; - SNMP_INT request_id, error_status, error_index; - int request_id_length, error_status_length, error_index_length; - - SNMP_INT version; - u_char community[COMMUNITY_MAX_LEN]; - int community_length = COMMUNITY_MAX_LEN; - - oid enterprise[MAX_NAME_LEN]; - int enterprise_length; - SNMP_INT trap_type, specific_type; - SNMP_UINT timestamp; - - int tmp_length; - oid vb_name[MAX_NAME_LEN]; - int vb_name_length; - int vb_index; - u_char vb_type; - char vb_string[MAX_NAME_LEN*6]; /* TBC */ - char vb_string2[2048]; /* TBC */ - char tmp_string[12]; - SNMP_INT vb_integer_value; - SNMP_UINT vb_unsigned_value; -#ifdef WITH_SNMP_UCD - struct counter64 vb_counter64_value; -#endif - oid vb_oid_value[MAX_NAME_LEN]; - int vb_oid_value_length; - unsigned char vb_string_value[128]; - int vb_string_value_length; -#ifdef WITH_SNMP_UCD - float vb_float_value; - double vb_double_value; -#endif - - int i; + ASN1_SCK asn1; + const guchar *start; + gboolean def; + guint length; + guint sequence_length; + guint message_length; + + guint32 version; + + guchar *community; + int community_length; + + guint pdu_type; char *pdu_type_string; + guint pdu_length; + + guint32 request_id; + + guint32 error_status; + + guint32 error_index; + + subid_t *enterprise; + guint enterprise_length; + + guint8 *agent_address; + guint agent_address_length; + + guint32 trap_type; - proto_tree *snmp_tree=NULL; - proto_item *item=NULL; + guint32 specific_type; + + guint timestamp; + guint timestamp_length; + + gchar oid_string[MAX_NAME_LEN*6]; /* TBC */ + + guint variable_bindings_length; + + int vb_index; + guint variable_length; + subid_t *variable_oid; + guint variable_oid_length; + gchar vb_oid_string[MAX_NAME_LEN*6]; /* TBC */ + + proto_tree *snmp_tree = NULL; + proto_item *item = NULL; + int ret; + guint cls, con, tag; if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, proto_name); + if (tree) { + item = proto_tree_add_item(tree, proto, offset, END_OF_FRAME, NULL); + snmp_tree = proto_item_add_subtree(item, ett); + } + /* NOTE: we have to parse the message piece by piece, since the * capture length may be less than the message length: a 'global' * parsing is likely to fail. */ - -#ifdef WITH_SNMP_UCD /* parse the SNMP header */ - if(NULL == asn_parse_header((u_char*)&pd[offset], &length, &type)) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse SNMP header"); + asn1_open(&asn1, &pd[offset], END_OF_FRAME); + ret = asn1_sequence_decode(&asn1, &message_length, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "message header", ret); return; } - - if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { - dissect_snmp_error(pd, offset, fd, tree, "Not an SNMP PDU"); + offset += length; + + ret = asn1_uint32_decode (&asn1, &version, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, "version number", + ret); return; } - - /* authenticates message */ - length=fd->pkt_len-offset; - header_length=length; - data = snmp_comstr_parse((u_char*)&pd[offset], &length, community, &community_length, (long*)&version); - if(NULL == data) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse authentication"); - return; + if (tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Version: %s", + val_to_str(version, versions, "Unknown version %#x")); } -#endif /* WITH_SNMP_UCD */ -#ifdef WITH_SNMP_CMU - /* initialize length variables */ - /* length=fd->pkt_len-offset; */ - header_length=length; + offset += length; - /* parse the SNMP header */ - data = asn_parse_header((u_char*)&pd[offset], &length, &type); - if(NULL == data) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse SNMP header"); + ret = asn1_octet_string_decode (&asn1, &community, &community_length, + &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, "community", + ret); return; } - - if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { - dissect_snmp_error(pd, offset, fd, tree, "Not an SNMP PDU"); - return; + if (tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Community: %.*s", community_length, community); } + g_free(community); + offset += length; - data = asn_parse_int(data, &length, &type, &version, sizeof(SNMP_INT)); - if(NULL == data) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse SNMP version number"); - return; - } - data = asn_parse_string(data, &length, &type, community, &community_length); - if(NULL == data) { + switch (version) { + + case SNMP_VERSION_1: + case SNMP_VERSION_2c: + case SNMP_VERSION_2u: + case SNMP_VERSION_3: + break; + + default: dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse SNMP community"); + "PDU for unknown version of SNMP"); return; } - community[community_length] = '\0'; -#endif /* WITH_SNMP_CMU */ - header_length-=length; - /* printf("Community is %s, version is %d (header length is %d)\n", community, version, header_length); */ - if(version != SNMP_VERSION_1) { - dissect_snmp_error(pd, offset, fd, tree, - "Non-version-1 SNMP PDU"); + start = asn1.pointer; + ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def, + &pdu_length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "PDU type", ret); return; } - - pdu_type_length=length; - data = asn_parse_header(data, &length, &pdu_type); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse PDU type"); + if (cls != ASN1_CTX || con != ASN1_CON) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "PDU type", ASN1_ERR_WRONG_TYPE); return; } - pdu_type_length-=length; - /* printf("pdu type is %#x (length is %d)\n", type, pdu_type_length); */ - + pdu_type_string = val_to_str(pdu_type, pdu_types, + "Unknown PDU type %#x"); + if (check_col(fd, COL_INFO)) + col_add_str(fd, COL_INFO, pdu_type_string); + length = asn1.pointer - start; + if (tree) { + proto_tree_add_text(snmp_tree, offset, length, + "PDU type: %s", pdu_type_string); + } + offset += length; + /* get the fields in the PDU preceeding the variable-bindings sequence */ - if (pdu_type != SNMP_MSG_TRAP) { - - /* request id */ - request_id_length=length; - data = asn_parse_int(data, &length, &type, &request_id, sizeof(request_id)); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse request ID"); + switch (pdu_type) { + + case SNMP_MSG_GET: + case SNMP_MSG_GETNEXT: + case SNMP_MSG_RESPONSE: + case SNMP_MSG_SET: +#if 0 + /* XXX - are they like V1 non-trap PDUs? */ + case SNMP_MSG_GETBULK: + case SNMP_MSG_INFORM: +#endif + /* request id */ + ret = asn1_uint32_decode (&asn1, &request_id, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "request ID", ret); return; } - request_id_length-=length; - /* printf("request id is %#lx (length is %d)\n", request_id, request_id_length); */ + if (tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Request Id: %#x", request_id); + } + offset += length; - /* error status (getbulk non-repeaters) */ - error_status_length=length; - data = asn_parse_int(data, &length, &type, &error_status, sizeof(error_status)); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse error status"); + /* error status (getbulk non-repeaters) */ + ret = asn1_uint32_decode (&asn1, &error_status, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "error status", ret); return; } - error_status_length-=length; - - /* error index (getbulk max-repetitions) */ - error_index_length=length; - data = asn_parse_int(data, &length, &type, &error_index, sizeof(error_index)); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse error index"); - return; + if (tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Error Status: %s", + val_to_str(error_status, error_statuses, + "Unknown (%d)")); } - error_index_length-=length; + offset += length; - pdu_type_string = val_to_str(pdu_type, pdu_types, - "Unknown PDU type %#x"); - if (check_col(fd, COL_INFO)) - col_add_str(fd, COL_INFO, pdu_type_string); + /* error index (getbulk max-repetitions) */ + ret = asn1_uint32_decode (&asn1, &error_index, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "error index", ret); + return; + } if (tree) { - /* all_length=header_length+pdu_type_length+request_id_length+error_status_length+error_index_length; */ - all_length=fd->pkt_len-offset; - item = proto_tree_add_item(tree, proto, offset, all_length, NULL); - snmp_tree = proto_item_add_subtree(item, ett); - proto_tree_add_text(snmp_tree, offset, header_length, "Community: \"%s\", Version: %s", community, val_to_str(version, versions, "Unknown version %#x")); - offset+=header_length; - proto_tree_add_text(snmp_tree, offset, pdu_type_length, "%s", pdu_type_string); - offset+=pdu_type_length; - proto_tree_add_text(snmp_tree, offset, request_id_length, "Request Id.: %#x", (unsigned int)request_id); - offset+=request_id_length; - proto_tree_add_text(snmp_tree, offset, error_status_length, "Error Status: %s", val_to_str(error_status, error_statuses, "Unknown (%d)")); - offset+=error_status_length; - proto_tree_add_text(snmp_tree, offset, error_index_length, "Error Index: %d", (int)error_index); - offset+=error_index_length; - } else { - offset+=header_length; - offset+=pdu_type_length; - offset+=request_id_length; - offset+=error_status_length; - offset+=error_index_length; + proto_tree_add_text(snmp_tree, offset, length, + "Error Index: %u", error_index); } - - } else { - /* an SNMPv1 trap PDU */ - pdu_type_string = val_to_str(pdu_type, pdu_types, - "Unknown PDU type %#x"); - if (check_col(fd, COL_INFO)) - col_add_str(fd, COL_INFO, pdu_type_string); - if(tree) { - all_length=fd->pkt_len-offset; - item = proto_tree_add_item(tree, proto, offset, all_length, NULL); - snmp_tree = proto_item_add_subtree(item, ett); - proto_tree_add_text(snmp_tree, offset, header_length, "Community: \"%s\", Version: %s", community, val_to_str(version, versions, "Unknown version %#x")); - offset+=header_length; - proto_tree_add_text(snmp_tree, offset, pdu_type_length, "Pdu type: %s", pdu_type_string); - offset+=pdu_type_length; - } else { - offset+=header_length; - offset+=pdu_type_length; + offset += length; + break; + + case SNMP_MSG_TRAP: + /* enterprise */ + ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length, + &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "enterprise OID", ret); + return; } - - /* enterprise */ - enterprise_length = MAX_NAME_LEN; - tmp_length=length; - data = asn_parse_objid(data, &length, &type, enterprise, &enterprise_length); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse enterprise OID"); + if (tree) { + format_oid(oid_string, enterprise, enterprise_length); + proto_tree_add_text(snmp_tree, offset, length, + "Enterprise: %s", oid_string); + } + g_free(enterprise); + offset += length; + + /* agent address */ + start = asn1.pointer; + ret = asn1_header_decode (&asn1, &cls, &con, &tag, + &def, &agent_address_length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "agent address", ret); return; } - tmp_length-=length; - - sprintf(vb_string, OID_FORMAT_STRING, enterprise[0]); - for(i=1; i<enterprise_length;i++) { - sprintf(tmp_string, OID_FORMAT_STRING1, enterprise[i]); - strcat(vb_string,tmp_string); + if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) || + (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) { + /* GXSNMP 0.0.15 says the latter is "needed for + Banyan" */ + dissect_snmp_parse_error(pd, offset, fd, tree, + "agent_address", ASN1_ERR_WRONG_TYPE); + return; } - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Enterprise: %s", vb_string); + if (agent_address_length != 4) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE); + return; } - offset+=tmp_length; - - /* agent address */ - vb_string_value_length = 4; - tmp_length=length; - data = asn_parse_string(data, &length, &type, vb_string_value, &vb_string_value_length); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse agent address"); + ret = asn1_octet_string_value_decode (&asn1, + agent_address_length, &agent_address); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "agent address", ret); return; } - tmp_length-=length; - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Agent address: %d.%d.%d.%d", - vb_string_value[0],vb_string_value[1],vb_string_value[2],vb_string_value[3]); + length = asn1.pointer - start; + if (tree) { + proto_tree_add_text(snmp_tree, offset, agent_address_length, + "Agent address: %s", ip_to_str(agent_address)); } - offset+=tmp_length; + g_free(agent_address); + offset += length; - /* generic trap */ - tmp_length=length; - data = asn_parse_int(data, &length, &type, &trap_type, sizeof(trap_type)); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse trap type"); + /* generic trap type */ + ret = asn1_uint32_decode (&asn1, &trap_type, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "generic trap type", ret); return; } - tmp_length-=length; - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Trap type: %s", val_to_str(trap_type, trap_types, "Unknown (%d)")); + if (tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Trap type: %s", + val_to_str(trap_type, trap_types, "Unknown (%u)")); } - offset+=tmp_length; + offset += length; - /* specific trap */ - tmp_length=length; - data = asn_parse_int(data, &length, &type, &specific_type, sizeof(specific_type)); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse specific trap type"); + /* specific trap type */ + ret = asn1_uint32_decode (&asn1, &specific_type, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "specific trap type", ret); return; } - tmp_length-=length; - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Specific trap type: %ld (%#lx)", (long)specific_type, (long)specific_type); + if (tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Specific trap type: %u (%#x)", + specific_type, specific_type); } - offset+=tmp_length; + offset += length; - /* timestamp */ - tmp_length=length; - data = asn_parse_unsigned_int(data, &length, &type, ×tamp, sizeof(timestamp)); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse time stamp"); + /* timestamp */ + start = asn1.pointer; + ret = asn1_header_decode (&asn1, &cls, &con, &tag, + &def, ×tamp_length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "timestamp", ret); return; } - tmp_length-=length; - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Timestamp: %lu", (unsigned long)timestamp); + if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) || + (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "timestamp", ASN1_ERR_WRONG_TYPE); + return; + } + ret = asn1_uint32_value_decode(&asn1, timestamp_length, + ×tamp); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "timestamp", ret); + return; + } + length = asn1.pointer - start; + if (tree) { + proto_tree_add_text(snmp_tree, offset, length, + "Timestamp: %u", timestamp); } - offset+=tmp_length; + offset += length; + break; } - + /* variable bindings */ - /* get header for variable-bindings sequence */ - tmp_length=length; - data = asn_parse_header(data, &length, &type); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't variable-bindings header"); - return; - } - tmp_length-=length; - if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) { - dissect_snmp_error(pd, offset, fd, tree, - "Bad type for variable-bindings header"); + /* get header for variable-bindings sequence */ + ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "variable bindings header", ret); return; } - offset+=tmp_length; - /* printf("VB header: offset is %d; length is %d.\n", offset, tmp_length); */ + offset += length; /* loop on variable bindings */ - vb_index=0; - while(length>0) { + vb_index = 0; + while (variable_bindings_length > 0) { vb_index++; - /* printf("VB index is %d (offset=%d; length=%d).\n", vb_index, offset, length); */ + sequence_length = 0; + /* parse type */ - tmp_length=length; - tmp_data=data; - data = asn_parse_header(data, &tmp_length, &type); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse variable-binding header"); - return; - } - if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) { - dissect_snmp_error(pd, offset, fd, tree, - "Bad type for variable-binding header"); - return; - } - tmp_length=(int)(data-tmp_data); - length-=tmp_length; - offset+=tmp_length; - - /* parse object identifier */ - vb_name_length=MAX_NAME_LEN; - tmp_length=length; - data = asn_parse_objid(data, &length, &type, vb_name, &vb_name_length); - if (data == NULL) { - dissect_snmp_error(pd, offset, fd, tree, - "No object-identifier for variable-binding"); + ret = asn1_sequence_decode(&asn1, &variable_length, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "variable binding header", ret); return; } + sequence_length += length; - if (type != (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID)) { - dissect_snmp_error(pd, offset, fd, tree, - "Bad type for variable-binding"); + /* parse object identifier */ + ret = asn1_oid_decode (&asn1, &variable_oid, + &variable_oid_length, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "variable binding OID", ret); return; } - tmp_length-=length; + sequence_length += length; - if(tree) { - sprintf(vb_string, OID_FORMAT_STRING, vb_name[0]); - for(i=1; i<vb_name_length;i++) { - sprintf(tmp_string, OID_FORMAT_STRING1, vb_name[i]); - strcat(vb_string,tmp_string); - } + if (tree) { + format_oid(oid_string, variable_oid, + variable_oid_length); - sprint_objid(vb_string2, vb_name, vb_name_length); +#if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) + sprint_objid(vb_oid_string, variable_oid, + variable_oid_length); +#endif - proto_tree_add_text(snmp_tree, offset, tmp_length, "Object identifier %d: %s (%s)", vb_index, vb_string, vb_string2); + proto_tree_add_text(snmp_tree, offset, sequence_length, +#if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) || defined(HAVE_SMI_H) + "Object identifier %d: %s (%s)", vb_index, + oid_string, vb_oid_string); +#else + "Object identifier %d: %s", vb_index, + oid_string); +#endif } - offset+=tmp_length; + offset += sequence_length; + variable_bindings_length -= sequence_length; - /* parse the type of the object */ - tmp_length=length; - if (NULL == asn_parse_header(data, &tmp_length, &vb_type)){ - dissect_snmp_error(pd, offset, fd, tree, - "Bad type for variable-binding value"); + /* Parse the variable's value */ + ret = snmp_variable_decode(snmp_tree, &asn1, offset, &length); + if (ret != ASN1_ERR_NOERROR) { + dissect_snmp_parse_error(pd, offset, fd, tree, + "variable", ret); return; } - - /* parse the value */ - switch(vb_type) { - case ASN_NULL: - tmp_length=length; - data=asn_parse_null(data, &length, &type); - tmp_length-=length; - if (data == NULL){ - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse null value"); - return; - } - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: NULL"); - } - offset+=tmp_length; - break; - - case ASN_INTEGER: - tmp_length=length; - data=asn_parse_int(data, &length, &type, &vb_integer_value, sizeof(vb_integer_value)); - tmp_length-=length; - if (data == NULL){ - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse integer value"); - return; - } - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <i> %ld (%#lx)", (long)vb_integer_value, (long)vb_integer_value); - } - offset+=tmp_length; - break; - - case ASN_COUNTER: - case ASN_GAUGE: - case ASN_TIMETICKS: - case ASN_UINTEGER: - tmp_length=length; - data=asn_parse_unsigned_int(data, &length, &type, &vb_unsigned_value, sizeof(vb_unsigned_value)); - tmp_length-=length; - if (data == NULL){ - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse unsigned value"); - return; - } - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <u> %lu (%#lx)", (unsigned long)vb_unsigned_value, (unsigned long)vb_unsigned_value); - } - offset+=tmp_length; - break; - -#ifdef WITH_SNMP_UCD - /* only ucd support 64bits types */ - case ASN_COUNTER64: -#ifdef OPAQUE_SPECIAL_TYPES - case ASN_OPAQUE_COUNTER64: - case ASN_OPAQUE_U64: -#endif /* OPAQUE_SPECIAL_TYPES */ - tmp_length=length; - data=asn_parse_unsigned_int64(data, &length, &type, &vb_counter64_value, sizeof(vb_counter64_value)); - tmp_length-=length; - if (data == NULL){ - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse counter64 value"); - return; - } - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <i64> %lu:%lu (%#lx:%lx)", - vb_counter64_value.high, - vb_counter64_value.low, - vb_counter64_value.high, - vb_counter64_value.low); - } - offset+=tmp_length; - break; -#endif /* WITH_SNMP_UCD */ - - case ASN_OBJECT_ID: - vb_oid_value_length = MAX_NAME_LEN; - tmp_length=length; - data=asn_parse_objid(data, &length, &type, vb_oid_value, &vb_oid_value_length); - tmp_length-=length; - if (data == NULL){ - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse OID value"); - return; - } - if(tree) { - sprintf(vb_string, OID_FORMAT_STRING, vb_oid_value[0]); - for(i=1; i<vb_oid_value_length;i++) { - sprintf(tmp_string, OID_FORMAT_STRING1, vb_oid_value[i]); - strcat(vb_string,tmp_string); - } - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <oid> %s", vb_string); - } - offset+=tmp_length; - break; - case ASN_OCTET_STR: - case ASN_IPADDRESS: - case ASN_OPAQUE: - case ASN_NSAP: - vb_string_value_length=128; - tmp_length=length; - data=asn_parse_string(data, &length, &type, vb_string_value, &vb_string_value_length); - tmp_length-=length; - if (data == NULL){ - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse octet string value"); - return; - } - if(tree) { - vb_string_value[vb_string_value_length]=0; - /* if some characters are not printable, display the string as - * bytes */ - for(i=0; i<vb_string_value_length; i++) { - if(!(isprint(vb_string_value[i]) || isspace(vb_string_value[i]))) break; - } - if(i<vb_string_value_length) { - sprintf(vb_string, "%03d", (int)vb_string_value[0]); - for(i=1; i<vb_string_value_length; i++) { - sprintf(tmp_string, ".%03d", (int)vb_string_value[i]); - strcat(vb_string,tmp_string); - } - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <str> %s", vb_string); - }else { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <str> %s", vb_string_value); - } - } - offset+=tmp_length; - break; - -#ifdef OPAQUE_SPECIAL_TYPES - case ASN_OPAQUE_I64: - tmp_length=length; - data=asn_parse_signed_int64(data, &length, &type, &vb_counter64_value, sizeof(vb_counter64_value)); - tmp_length-=length; - if (data == NULL){ - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse integer64 value"); - return; - } - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <i64> %ld:%lu (%#lx:%lx)", - vb_counter64_value.high, - vb_counter64_value.low, - vb_counter64_value.high, - vb_counter64_value.low); - } - offset+=tmp_length; - break; - break; - - case ASN_OPAQUE_FLOAT: - tmp_length=length; - data=asn_parse_float(data, &length, &type,&vb_float_value, sizeof(vb_float_value)); - tmp_length-=length; - if (data == NULL){ - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse float value"); - return; - } - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <f> %f", (double)vb_float_value); - } - offset+=tmp_length; - break; - - case ASN_OPAQUE_DOUBLE: - tmp_length=length; - data=asn_parse_double(data, &length, &type,&vb_double_value, sizeof(vb_double_value)); - tmp_length-=length; - if (data == NULL){ - dissect_snmp_error(pd, offset, fd, tree, - "Couldn't parse double value"); - return; - } - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <d> %f", vb_double_value); - } - offset+=tmp_length; - break; -#endif /* OPAQUE_SPECIAL_TYPES */ - - case SNMP_NOSUCHOBJECT: - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <err> no such object"); - } - break; - case SNMP_NOSUCHINSTANCE: - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <err> no such instance"); - } - break; - case SNMP_ENDOFMIBVIEW: - if(tree) { - proto_tree_add_text(snmp_tree, offset, tmp_length, "Value: <err> end of mib view"); - } - break; - - default: - dissect_snmp_error(pd, offset, fd, tree, - "Unsupported type for variable-binding value"); - return; - } + offset += length; + variable_bindings_length -= length; } } -#else /* WITH_SNMP: CMU or UCD */ - -/* Stub dissector, for use when there's no SNMP library. */ -void -dissect_snmp_pdu(const u_char *pd, int offset, frame_data *fd, - proto_tree *tree, char *proto_name, int proto, gint ett) -{ - proto_item *item; - proto_tree *snmp_tree; - - if (check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, proto_name); - if (check_col(fd, COL_INFO)) - col_add_str(fd, COL_INFO, "SNMP request or reply"); - if (tree) { - item = proto_tree_add_item(tree, proto, offset, END_OF_FRAME, - NULL); - snmp_tree = proto_item_add_subtree(item, ett); - dissect_data(pd, offset, fd, snmp_tree); - } -} - -#endif /* WITH_SNMP: CMU or UCD */ - void dissect_snmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { dissect_snmp_pdu(pd, offset, fd, tree, "SNMP", proto_snmp, ett_snmp); } -/* - * Allow the stuff that builds "register.c" to scan "packet-snmp.c" even - * if we're not enabling SNMP decoding (for "canned" source distributions - * such as BSD ports, it may be a pain to arrange that it be scanned only - * if SNMP is being used), by having "proto_register_snmp()" always be - * defined, but not do anything if SNMP decoding isn't enabled. - */ void proto_register_snmp(void) { -#if defined(WITH_SNMP_CMU) || defined(WITH_SNMP_UCD) /* static hf_register_info hf[] = { { &variable, { "Name", "snmp.abbreviation", TYPE, VALS_POINTER }}, };*/ -#endif /* WITH_SNMP: CMU or UCD */ static gint *ett[] = { &ett_snmp, }; -#if defined(WITH_SNMP_CMU) || defined(WITH_SNMP_UCD) +#if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) + /* UCD or CMU SNMP */ init_mib(); -#endif /* WITH_SNMP: CMU or UCD */ +#endif proto_snmp = proto_register_protocol("Simple Network Management Protocol", "snmp"); -#if defined(WITH_SNMP_CMU) || defined(WITH_SNMP_UCD) /* proto_register_field_array(proto_snmp, hf, array_length(hf));*/ -#endif /* WITH_SNMP: CMU or UCD */ proto_register_subtree_array(ett, array_length(ett)); } |