1999-05-12 05:56:42 +00:00
|
|
|
/* packet-snmp.c
|
|
|
|
* Routines for SNMP (simple network management protocol)
|
2001-06-10 09:50:20 +00:00
|
|
|
* Copyright (C) 1998 Didier Jorand
|
1999-05-12 05:56:42 +00:00
|
|
|
*
|
2001-01-30 02:13:43 +00:00
|
|
|
* See RFC 1157 for SNMPv1.
|
|
|
|
*
|
|
|
|
* See RFCs 1901, 1905, and 1906 for SNMPv2c.
|
|
|
|
*
|
|
|
|
* See RFCs 1905, 1906, 1909, and 1910 for SNMPv2u.
|
|
|
|
*
|
2002-03-11 01:51:37 +00:00
|
|
|
* $Id: packet-snmp.c,v 1.87 2002/03/11 01:51:37 guy Exp $
|
1999-05-12 05:56:42 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
2001-06-10 09:50:20 +00:00
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
|
|
* Copyright 1998 Gerald Combs
|
1999-05-12 05:56:42 +00:00
|
|
|
*
|
1999-12-10 09:49:29 +00:00
|
|
|
* Some stuff from:
|
1999-05-12 05:56:42 +00:00
|
|
|
*
|
1999-12-10 09:49:29 +00:00
|
|
|
* GXSNMP -- An snmp mangament application
|
|
|
|
* Copyright (C) 1998 Gregory McLean & Jochen Friedrich
|
|
|
|
* Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
|
|
|
|
*
|
1999-05-12 05:56:42 +00:00
|
|
|
* 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
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
# include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
|
|
# include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
|
Instead of calling "snmp_set_full_objid()" to cause OIDs to be displayed
symbolically as full sequences, call "snmp_set_suffix_only(2)" to cause
them to be displayed symbolically as a module name and a name within
that module, as that might make it easier to find the RFC or whatever
that describes the object in question.
Don't just statically call it, though, on Linux, as that causes binaries
built on Red Hat releases prior to 6.2 to fail to run on 6.2, due to the
UCD SNMP 4.1.1 library used in RH 6.2 not being 100% binary-compatible
with the UCD SNMP libraries used in those prior releases. Instead, on
Linux, try to "dlopen()" the "libsnmp.so" library and, if that succeeds,
try to find "snmp_set_suffix_only()" in that library - if that succeeds,
call it, otherwise try to find "ds_set_int()" in that library and, if
*that* succeeds, call it with the arguments that, in UCD SNMP 4.1.1, the
"snmp_set_suffix_only()" macro passes to it.
svn path=/trunk/; revision=2077
2000-06-17 05:56:22 +00:00
|
|
|
#ifdef linux
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#endif
|
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
#include <glib.h>
|
1999-12-12 01:51:47 +00:00
|
|
|
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
|
|
|
#include <epan/strutil.h>
|
|
|
|
#include <epan/conversation.h>
|
Change the sub-dissector handoff registration routines so that the
sub-dissector table is not stored in the header_field_info struct, but
in a separate namespace. Dissector tables are now registered by name
and not by field ID. For example:
udp_dissector_table = register_dissector_table("udp.port");
Because of this different namespace, dissector tables can have names
that are not field names. This is useful for ethertype, since multiple
fields are "ethertypes".
packet-ethertype.c replaces ethertype.c (the name was changed so that it
would be named in the same fashion as all the filenames passed to make-reg-dotc)
Although it registers no protocol or field, it registers one dissector table:
ethertype_dissector_table = register_dissector_table("ethertype");
All protocols that can be called because of an ethertype field now register
that fact with dissector_add() calls.
In this way, one dissector_table services all ethertype fields
(hf_eth_type, hf_llc_type, hf_null_etype, hf_vlan_etype)
Furthermore, the code allows for names of protocols to exist in the
etype_vals, yet a dissector for that protocol doesn't exist. The name
of the dissector is printed in COL_INFO. You're welcome, Richard. :-)
svn path=/trunk/; revision=1848
2000-04-13 18:18:56 +00:00
|
|
|
#include "etypes.h"
|
2000-05-30 03:35:55 +00:00
|
|
|
#include "packet-ipx.h"
|
1999-12-12 01:51:47 +00:00
|
|
|
|
2002-03-10 22:18:12 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
|
|
|
# include <ucd-snmp/asn1.h>
|
|
|
|
# include <ucd-snmp/snmp_api.h>
|
|
|
|
# include <ucd-snmp/snmp_impl.h>
|
|
|
|
# include <ucd-snmp/mib.h>
|
|
|
|
# include <ucd-snmp/default_store.h>
|
|
|
|
# include <ucd-snmp/tools.h>
|
1999-12-14 10:16:11 +00:00
|
|
|
|
1999-12-14 05:59:16 +00:00
|
|
|
/*
|
2002-03-10 22:18:12 +00:00
|
|
|
* Define values "sprint_realloc_value()" expects.
|
1999-12-12 01:51:47 +00:00
|
|
|
*/
|
2002-03-10 22:18:12 +00:00
|
|
|
# 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
|
1999-12-12 01:51:47 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
#include "asn1.h"
|
1999-05-16 04:13:29 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
#include "packet-snmp.h"
|
2002-03-11 01:48:08 +00:00
|
|
|
#include "format-oid.h"
|
1999-05-16 04:13:29 +00:00
|
|
|
|
2000-07-02 07:10:16 +00:00
|
|
|
/* Null string of type "guchar[]". */
|
|
|
|
static const guchar nullstring[] = "";
|
|
|
|
|
|
|
|
/* Take a pointer that may be null and return a pointer that's not null
|
|
|
|
by turning null pointers into pointers to the above null string. */
|
|
|
|
#define SAFE_STRING(s) (((s) != NULL) ? (s) : nullstring)
|
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
static int proto_snmp = -1;
|
2000-05-15 03:15:12 +00:00
|
|
|
static int proto_smux = -1;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
static gint ett_snmp = -1;
|
2000-05-15 03:15:12 +00:00
|
|
|
static gint ett_smux = -1;
|
2001-01-30 02:13:43 +00:00
|
|
|
static gint ett_parameters = -1;
|
|
|
|
static gint ett_parameters_qos = -1;
|
2000-05-15 03:15:12 +00:00
|
|
|
static gint ett_global = -1;
|
|
|
|
static gint ett_flags = -1;
|
|
|
|
static gint ett_secur = -1;
|
|
|
|
|
|
|
|
static int hf_snmpv3_flags = -1;
|
|
|
|
static int hf_snmpv3_flags_auth = -1;
|
|
|
|
static int hf_snmpv3_flags_crypt = -1;
|
|
|
|
static int hf_snmpv3_flags_report = -1;
|
|
|
|
|
2001-11-27 07:13:32 +00:00
|
|
|
static dissector_handle_t snmp_handle;
|
2001-11-26 04:52:51 +00:00
|
|
|
static dissector_handle_t data_handle;
|
|
|
|
|
2000-05-15 03:15:12 +00:00
|
|
|
#define TH_AUTH 0x01
|
|
|
|
#define TH_CRYPT 0x02
|
|
|
|
#define TH_REPORT 0x04
|
|
|
|
|
|
|
|
static const true_false_string flags_set_truth = {
|
|
|
|
"Set",
|
|
|
|
"Not set"
|
|
|
|
};
|
1999-05-12 05:56:42 +00:00
|
|
|
|
2000-04-08 07:07:42 +00:00
|
|
|
#define UDP_PORT_SNMP 161
|
|
|
|
#define UDP_PORT_SNMP_TRAP 162
|
2000-05-15 03:15:12 +00:00
|
|
|
#define TCP_PORT_SMUX 199
|
2000-04-08 07:07:42 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* Protocol version numbers */
|
|
|
|
#define SNMP_VERSION_1 0
|
|
|
|
#define SNMP_VERSION_2c 1
|
|
|
|
#define SNMP_VERSION_2u 2
|
|
|
|
#define SNMP_VERSION_3 3
|
1999-05-12 05:56:42 +00:00
|
|
|
|
1999-06-12 04:17:19 +00:00
|
|
|
static const value_string versions[] = {
|
1999-12-10 09:49:29 +00:00
|
|
|
{ SNMP_VERSION_1, "1" },
|
|
|
|
{ SNMP_VERSION_2c, "2C" },
|
|
|
|
{ SNMP_VERSION_2u, "2U" },
|
|
|
|
{ SNMP_VERSION_3, "3" },
|
1999-06-12 04:17:19 +00:00
|
|
|
{ 0, NULL },
|
|
|
|
};
|
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* 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
|
|
|
|
|
1999-06-12 04:17:19 +00:00
|
|
|
static const value_string pdu_types[] = {
|
|
|
|
{ SNMP_MSG_GET, "GET" },
|
|
|
|
{ SNMP_MSG_GETNEXT, "GET-NEXT" },
|
|
|
|
{ SNMP_MSG_SET, "SET" },
|
|
|
|
{ SNMP_MSG_RESPONSE, "RESPONSE" },
|
|
|
|
{ SNMP_MSG_TRAP, "TRAP-V1" },
|
|
|
|
{ SNMP_MSG_GETBULK, "GETBULK" },
|
|
|
|
{ SNMP_MSG_INFORM, "INFORM" },
|
|
|
|
{ SNMP_MSG_TRAP2, "TRAP-V2" },
|
|
|
|
{ SNMP_MSG_REPORT, "REPORT" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2000-05-15 03:15:12 +00:00
|
|
|
/* SMUX PDU types */
|
|
|
|
#define SMUX_MSG_OPEN 0
|
|
|
|
#define SMUX_MSG_CLOSE 1
|
|
|
|
#define SMUX_MSG_RREQ 2
|
|
|
|
#define SMUX_MSG_RRSP 3
|
|
|
|
#define SMUX_MSG_SOUT 4
|
|
|
|
|
|
|
|
static const value_string smux_types[] = {
|
|
|
|
{ SMUX_MSG_OPEN, "Open" },
|
|
|
|
{ SMUX_MSG_CLOSE, "Close" },
|
|
|
|
{ SMUX_MSG_RREQ, "Registration Request" },
|
|
|
|
{ SMUX_MSG_RRSP, "Registration Response" },
|
|
|
|
{ SMUX_MSG_SOUT, "Commit Or Rollback" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* SMUX Closing causes */
|
|
|
|
#define SMUX_CLOSE_DOWN 0
|
|
|
|
#define SMUX_CLOSE_VERSION 1
|
|
|
|
#define SMUX_CLOSE_PACKET 2
|
|
|
|
#define SMUX_CLOSE_PROTOCOL 3
|
|
|
|
#define SMUX_CLOSE_INTERNAL 4
|
|
|
|
#define SMUX_CLOSE_NOAUTH 5
|
|
|
|
|
|
|
|
static const value_string smux_close[] = {
|
|
|
|
{ SMUX_CLOSE_DOWN, "Going down" },
|
|
|
|
{ SMUX_CLOSE_VERSION, "Unsupported Version" },
|
|
|
|
{ SMUX_CLOSE_PACKET, "Packet Format Error" },
|
|
|
|
{ SMUX_CLOSE_PROTOCOL, "Protocol Error" },
|
|
|
|
{ SMUX_CLOSE_INTERNAL, "Internal Error" },
|
|
|
|
{ SMUX_CLOSE_NOAUTH, "Unauthorized" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* SMUX Request codes */
|
|
|
|
#define SMUX_RREQ_DELETE 0
|
|
|
|
#define SMUX_RREQ_READONLY 1
|
|
|
|
#define SMUX_RREQ_READWRITE 2
|
|
|
|
|
|
|
|
static const value_string smux_rreq[] = {
|
|
|
|
{ SMUX_RREQ_DELETE, "Delete" },
|
|
|
|
{ SMUX_RREQ_READONLY, "Read Only" },
|
|
|
|
{ SMUX_RREQ_READWRITE, "Read Write" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string smux_prio[] = {
|
|
|
|
{ -1, "Failure" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* SMUX SOut codes */
|
|
|
|
#define SMUX_SOUT_COMMIT 0
|
|
|
|
#define SMUX_SOUT_ROLLBACK 1
|
|
|
|
|
|
|
|
static const value_string smux_sout[] = {
|
|
|
|
{ SMUX_SOUT_COMMIT, "Commit" },
|
2001-01-03 16:41:08 +00:00
|
|
|
{ SMUX_SOUT_ROLLBACK, "Rollback" },
|
|
|
|
{ 0, NULL }
|
2000-05-15 03:15:12 +00:00
|
|
|
};
|
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* 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
|
|
|
|
|
1999-06-12 04:17:19 +00:00
|
|
|
static const value_string error_statuses[] = {
|
|
|
|
{ SNMP_ERR_NOERROR, "NO ERROR" },
|
1999-12-10 09:49:29 +00:00
|
|
|
{ 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" },
|
1999-06-12 04:17:19 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* 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
|
|
|
|
|
1999-06-12 04:17:19 +00:00
|
|
|
static const value_string trap_types[] = {
|
|
|
|
{ SNMP_TRAP_COLDSTART, "COLD START" },
|
|
|
|
{ SNMP_TRAP_WARMSTART, "WARM START" },
|
|
|
|
{ SNMP_TRAP_LINKDOWN, "LINK DOWN" },
|
|
|
|
{ SNMP_TRAP_LINKUP, "LINK UP" },
|
|
|
|
{ SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
|
|
|
|
{ SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
|
|
|
|
{ SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2000-05-15 03:15:12 +00:00
|
|
|
/* Security Models */
|
|
|
|
|
|
|
|
#define SNMP_SEC_ANY 0
|
|
|
|
#define SNMP_SEC_V1 1
|
|
|
|
#define SNMP_SEC_V2C 2
|
|
|
|
#define SNMP_SEC_USM 3
|
|
|
|
|
|
|
|
static const value_string sec_models[] = {
|
|
|
|
{ SNMP_SEC_ANY, "Any" },
|
|
|
|
{ SNMP_SEC_V1, "V1" },
|
|
|
|
{ SNMP_SEC_V2C, "V2C" },
|
|
|
|
{ SNMP_SEC_USM, "USM" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* 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
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
1999-12-10 09:49:29 +00:00
|
|
|
proto_tree *tree, const char *field_name, int ret)
|
|
|
|
{
|
2002-03-01 02:48:10 +00:00
|
|
|
char *errstr;
|
1999-12-10 09:49:29 +00:00
|
|
|
|
2002-03-01 02:48:10 +00:00
|
|
|
errstr = asn1_err_to_str(ret);
|
2001-04-06 23:12:33 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)) {
|
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO,
|
1999-12-10 09:49:29 +00:00
|
|
|
"ERROR: Couldn't parse %s: %s", field_name, errstr);
|
|
|
|
}
|
2001-04-06 23:12:33 +00:00
|
|
|
if (tree != NULL) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, 0,
|
2001-04-06 23:12:33 +00:00
|
|
|
"ERROR: Couldn't parse %s: %s", field_name, errstr);
|
2002-03-01 02:48:10 +00:00
|
|
|
call_dissector(data_handle,
|
|
|
|
tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
|
2001-04-06 23:12:33 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
|
|
|
|
1999-06-12 04:17:19 +00:00
|
|
|
static void
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
1999-06-12 04:17:19 +00:00
|
|
|
proto_tree *tree, const char *message)
|
1999-05-12 05:56:42 +00:00
|
|
|
{
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, message);
|
1999-05-12 05:56:42 +00:00
|
|
|
|
2001-04-06 23:12:33 +00:00
|
|
|
if (tree != NULL) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
|
2001-11-26 04:52:51 +00:00
|
|
|
call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, tree);
|
2001-04-06 23:12:33 +00:00
|
|
|
}
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
|
|
|
|
2002-03-11 01:48:08 +00:00
|
|
|
gchar *
|
2000-06-28 05:15:13 +00:00
|
|
|
format_oid(subid_t *oid, guint oid_length)
|
1999-12-10 09:49:29 +00:00
|
|
|
{
|
2000-06-28 05:15:13 +00:00
|
|
|
char *result;
|
|
|
|
int result_len;
|
2001-09-03 08:19:12 +00:00
|
|
|
int len;
|
|
|
|
unsigned int i;
|
2000-06-28 05:15:13 +00:00
|
|
|
char *buf;
|
2002-03-11 01:48:08 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
|
|
|
u_char *oid_string;
|
|
|
|
size_t oid_string_len;
|
|
|
|
size_t oid_out_len;
|
|
|
|
#endif
|
2000-06-28 05:15:13 +00:00
|
|
|
|
|
|
|
result_len = oid_length * 22;
|
2002-03-11 01:48:08 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
|
|
|
/*
|
|
|
|
* Get the decoded form of the OID, and add its length to the
|
|
|
|
* length of the result string.
|
|
|
|
*
|
|
|
|
* XXX - check for "malloc" and "sprint_realloc_objid()" failure.
|
|
|
|
*/
|
|
|
|
oid_string_len = 256;
|
|
|
|
oid_string = malloc(oid_string_len);
|
|
|
|
*oid_string = '\0';
|
|
|
|
oid_out_len = 0;
|
|
|
|
sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
|
|
|
|
oid, oid_length);
|
|
|
|
result_len += strlen(oid_string) + 3;
|
|
|
|
#endif
|
|
|
|
|
2000-06-28 05:15:13 +00:00
|
|
|
result = g_malloc(result_len + 1);
|
|
|
|
buf = result;
|
1999-12-10 09:49:29 +00:00
|
|
|
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;
|
|
|
|
}
|
2002-03-11 01:48:08 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
|
|
|
/*
|
|
|
|
* Append the decoded form of the OID.
|
|
|
|
*/
|
|
|
|
sprintf(buf, " (%s)", oid_string);
|
|
|
|
free(oid_string);
|
|
|
|
#endif
|
|
|
|
|
2000-06-28 05:15:13 +00:00
|
|
|
return result;
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
|
|
|
|
2002-03-10 22:18:12 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
|
|
|
static u_char *
|
2002-03-06 03:52:13 +00:00
|
|
|
check_var_length(guint vb_length, guint required_length)
|
|
|
|
{
|
2002-03-10 22:18:12 +00:00
|
|
|
u_char *buf;
|
2002-03-06 03:52:13 +00:00
|
|
|
static const char badlen_fmt[] = "Length is %u, should be %u";
|
|
|
|
|
|
|
|
if (vb_length != required_length) {
|
|
|
|
/* Enough room for the largest "Length is XXX,
|
|
|
|
should be XXX" message - 10 digits for each
|
|
|
|
XXX. */
|
2002-03-10 22:18:12 +00:00
|
|
|
buf = malloc(sizeof badlen_fmt + 10 + 10);
|
2002-03-06 03:52:13 +00:00
|
|
|
sprintf(buf, badlen_fmt, vb_length, required_length);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
return NULL; /* length is OK */
|
|
|
|
}
|
|
|
|
|
2002-03-10 22:18:12 +00:00
|
|
|
static u_char *
|
2000-06-26 00:13:21 +00:00
|
|
|
format_var(struct variable_list *variable, subid_t *variable_oid,
|
2002-03-11 01:40:28 +00:00
|
|
|
guint variable_oid_length, gushort vb_type, guint val_len)
|
1999-12-12 01:51:47 +00:00
|
|
|
{
|
2002-03-10 22:18:12 +00:00
|
|
|
u_char *buf;
|
|
|
|
size_t buf_len;
|
|
|
|
size_t out_len;
|
2000-06-26 00:13:21 +00:00
|
|
|
|
|
|
|
switch (vb_type) {
|
|
|
|
|
|
|
|
case SNMP_IPADDR:
|
2002-03-06 03:52:13 +00:00
|
|
|
/* Length has to be 4 bytes. */
|
2002-03-11 01:40:28 +00:00
|
|
|
buf = check_var_length(val_len, 4);
|
2002-03-06 03:52:13 +00:00
|
|
|
if (buf != NULL)
|
|
|
|
return buf; /* it's not 4 bytes */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_COUNTER64:
|
|
|
|
/* Length has to be 8 bytes. */
|
2002-03-11 01:40:28 +00:00
|
|
|
buf = check_var_length(val_len, 8);
|
2002-03-06 03:52:13 +00:00
|
|
|
if (buf != NULL)
|
|
|
|
return buf; /* it's not 8 bytes */
|
2000-06-26 00:13:21 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-12-12 01:51:47 +00:00
|
|
|
variable->next_variable = NULL;
|
|
|
|
variable->name = variable_oid;
|
|
|
|
variable->name_length = variable_oid_length;
|
|
|
|
switch (vb_type) {
|
|
|
|
|
|
|
|
case SNMP_INTEGER:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_INTEGER;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_COUNTER:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_COUNTER;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_GAUGE:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_GAUGE;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_TIMETICKS:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_TIMETICKS;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_OCTETSTR:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_STRING;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_IPADDR:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_IPADDR;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_OPAQUE:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_OPAQUE;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_NSAP:
|
1999-12-14 10:16:11 +00:00
|
|
|
variable->type = VALTYPE_NSAP;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_OBJECTID:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_OBJECTID;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_BITSTR:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_BITSTR;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_COUNTER64:
|
1999-12-14 05:59:16 +00:00
|
|
|
variable->type = VALTYPE_COUNTER64;
|
1999-12-12 01:51:47 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-03-11 01:40:28 +00:00
|
|
|
variable->val_len = val_len;
|
2000-06-26 00:13:21 +00:00
|
|
|
|
2002-03-10 22:18:12 +00:00
|
|
|
/*
|
|
|
|
* XXX - check for "malloc" and "sprint_realloc_objid()" failure.
|
|
|
|
*/
|
|
|
|
buf_len = 256;
|
|
|
|
buf = malloc(buf_len);
|
|
|
|
*buf = '\0';
|
|
|
|
out_len = 0;
|
|
|
|
sprint_realloc_value(&buf, &buf_len, &out_len, 1, variable_oid,
|
2001-12-12 05:26:53 +00:00
|
|
|
variable_oid_length, variable);
|
2000-06-26 00:13:21 +00:00
|
|
|
return buf;
|
1999-12-12 01:51:47 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
static int
|
1999-12-12 01:51:47 +00:00
|
|
|
snmp_variable_decode(proto_tree *snmp_tree, subid_t *variable_oid,
|
2002-03-10 22:18:12 +00:00
|
|
|
guint variable_oid_length, ASN1_SCK *asn1, int offset, guint *lengthp)
|
1999-12-10 09:49:29 +00:00
|
|
|
{
|
2001-04-15 07:30:03 +00:00
|
|
|
int start;
|
1999-12-10 09:49:29 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
subid_t *vb_oid;
|
|
|
|
guint vb_oid_length;
|
|
|
|
|
2000-06-26 00:13:21 +00:00
|
|
|
gchar *vb_display_string;
|
1999-12-12 01:51:47 +00:00
|
|
|
|
2002-03-10 22:18:12 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
1999-12-12 01:51:47 +00:00
|
|
|
struct variable_list variable;
|
|
|
|
long value;
|
2002-03-10 22:18:12 +00:00
|
|
|
#endif /* HAVE_UCD_SNMP_SNMP_H */
|
2001-09-03 08:19:12 +00:00
|
|
|
unsigned int i;
|
1999-12-10 09:49:29 +00:00
|
|
|
gchar *buf;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
/* parse the type of the object */
|
2001-04-15 07:30:03 +00:00
|
|
|
start = asn1->offset;
|
1999-12-10 09:49:29 +00:00
|
|
|
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);
|
1999-12-12 01:51:47 +00:00
|
|
|
if (vb_type_name == NULL) {
|
|
|
|
/*
|
|
|
|
* Unsupported type.
|
|
|
|
* Dissect the value as an opaque string of octets.
|
|
|
|
*/
|
|
|
|
vb_type_name = "unsupported type";
|
|
|
|
vb_type = SNMP_OPAQUE;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
|
|
|
|
/* 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;
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1->offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (snmp_tree) {
|
2002-03-10 22:18:12 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
|
|
|
value = vb_integer_value;
|
|
|
|
variable.val.integer = &value;
|
|
|
|
vb_display_string = format_var(&variable,
|
|
|
|
variable_oid, variable_oid_length, vb_type,
|
|
|
|
vb_length);
|
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset,
|
|
|
|
length,
|
|
|
|
"Value: %s", vb_display_string);
|
2002-03-11 01:51:37 +00:00
|
|
|
free(vb_display_string);
|
2002-03-10 22:18:12 +00:00
|
|
|
#else /* HAVE_UCD_SNMP_SNMP_H */
|
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset,
|
|
|
|
length,
|
1999-12-12 01:51:47 +00:00
|
|
|
"Value: %s: %d (%#x)", vb_type_name,
|
1999-12-10 09:49:29 +00:00
|
|
|
vb_integer_value, vb_integer_value);
|
2002-03-10 22:18:12 +00:00
|
|
|
#endif /* HAVE_UCD_SNMP_SNMP_H */
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
|
|
|
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;
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1->offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (snmp_tree) {
|
2002-03-10 22:18:12 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
|
|
|
value = vb_uinteger_value;
|
|
|
|
variable.val.integer = &value;
|
|
|
|
vb_display_string = format_var(&variable,
|
|
|
|
variable_oid, variable_oid_length, vb_type,
|
|
|
|
vb_length);
|
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset,
|
|
|
|
length,
|
|
|
|
"Value: %s", vb_display_string);
|
2002-03-11 01:51:37 +00:00
|
|
|
free(vb_display_string);
|
2002-03-10 22:18:12 +00:00
|
|
|
#else /* HAVE_UCD_SNMP_SNMP_H */
|
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset,
|
|
|
|
length,
|
1999-12-12 01:51:47 +00:00
|
|
|
"Value: %s: %u (%#x)", vb_type_name,
|
1999-12-11 06:58:41 +00:00
|
|
|
vb_uinteger_value, vb_uinteger_value);
|
2002-03-10 22:18:12 +00:00
|
|
|
#endif /* HAVE_UCD_SNMP_SNMP_H */
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_OCTETSTR:
|
|
|
|
case SNMP_IPADDR:
|
|
|
|
case SNMP_OPAQUE:
|
|
|
|
case SNMP_NSAP:
|
1999-12-12 01:51:47 +00:00
|
|
|
case SNMP_BITSTR:
|
|
|
|
case SNMP_COUNTER64:
|
2000-12-24 09:10:12 +00:00
|
|
|
ret = asn1_string_value_decode (asn1, vb_length,
|
1999-12-10 09:49:29 +00:00
|
|
|
&vb_octet_string);
|
|
|
|
if (ret != ASN1_ERR_NOERROR)
|
|
|
|
return ret;
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1->offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (snmp_tree) {
|
2002-03-10 22:18:12 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
|
|
|
variable.val.string = vb_octet_string;
|
|
|
|
vb_display_string = format_var(&variable,
|
|
|
|
variable_oid, variable_oid_length, vb_type,
|
|
|
|
vb_length);
|
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset,
|
|
|
|
length,
|
|
|
|
"Value: %s", vb_display_string);
|
2002-03-11 01:51:37 +00:00
|
|
|
free(vb_display_string);
|
2002-03-10 22:18:12 +00:00
|
|
|
#else /* HAVE_UCD_SNMP_SNMP_H */
|
1999-12-10 09:49:29 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2000-06-26 00:13:21 +00:00
|
|
|
vb_display_string = g_malloc(4*vb_length);
|
1999-12-12 01:51:47 +00:00
|
|
|
buf = &vb_display_string[0];
|
1999-12-10 09:49:29 +00:00
|
|
|
len = sprintf(buf, "%03u", vb_octet_string[0]);
|
1999-12-11 06:58:41 +00:00
|
|
|
buf += len;
|
1999-12-10 09:49:29 +00:00
|
|
|
for (i = 1; i < vb_length; i++) {
|
|
|
|
len = sprintf(buf, ".%03u",
|
|
|
|
vb_octet_string[i]);
|
|
|
|
buf += len;
|
|
|
|
}
|
2002-03-10 22:18:12 +00:00
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset,
|
|
|
|
length,
|
1999-12-12 01:51:47 +00:00
|
|
|
"Value: %s: %s", vb_type_name,
|
|
|
|
vb_display_string);
|
2000-06-26 00:13:21 +00:00
|
|
|
g_free(vb_display_string);
|
1999-12-10 09:49:29 +00:00
|
|
|
} else {
|
2002-03-10 22:18:12 +00:00
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset,
|
|
|
|
length,
|
2000-05-09 17:45:02 +00:00
|
|
|
"Value: %s: %.*s", vb_type_name,
|
2001-04-07 00:52:07 +00:00
|
|
|
(int)vb_length,
|
|
|
|
SAFE_STRING(vb_octet_string));
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
2002-03-10 22:18:12 +00:00
|
|
|
#endif /* HAVE_UCD_SNMP_SNMP_H */
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
|
|
|
g_free(vb_octet_string);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_NULL:
|
|
|
|
ret = asn1_null_decode (asn1, vb_length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR)
|
|
|
|
return ret;
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1->offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
|
1999-12-12 01:51:47 +00:00
|
|
|
"Value: %s", vb_type_name);
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_OBJECTID:
|
|
|
|
ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
|
|
|
|
&vb_oid_length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR)
|
|
|
|
return ret;
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1->offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (snmp_tree) {
|
2002-03-10 22:18:12 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
|
|
|
variable.val.objid = vb_oid;
|
|
|
|
vb_display_string = format_var(&variable,
|
|
|
|
variable_oid, variable_oid_length, vb_type,
|
2002-03-11 01:40:28 +00:00
|
|
|
vb_oid_length * sizeof (subid_t));
|
2002-03-10 22:18:12 +00:00
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset,
|
|
|
|
length,
|
|
|
|
"Value: %s", vb_display_string);
|
2002-03-11 01:51:37 +00:00
|
|
|
free(vb_display_string);
|
2002-03-10 22:18:12 +00:00
|
|
|
#else /* HAVE_UCD_SNMP_SNMP_H */
|
2000-06-28 05:15:13 +00:00
|
|
|
vb_display_string = format_oid(vb_oid, vb_oid_length);
|
2002-03-10 22:18:12 +00:00
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset,
|
|
|
|
length,
|
1999-12-12 01:51:47 +00:00
|
|
|
"Value: %s: %s", vb_type_name, vb_display_string);
|
2000-06-26 00:13:21 +00:00
|
|
|
g_free(vb_display_string);
|
2002-03-11 01:51:37 +00:00
|
|
|
#endif /* HAVE_UCD_SNMP_SNMP_H */
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
|
|
|
g_free(vb_oid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_NOSUCHOBJECT:
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1->offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
|
1999-12-12 01:51:47 +00:00
|
|
|
"Value: %s: no such object", vb_type_name);
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_NOSUCHINSTANCE:
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1->offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
|
1999-12-12 01:51:47 +00:00
|
|
|
"Value: %s: no such instance", vb_type_name);
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_ENDOFMIBVIEW:
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1->offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
|
1999-12-12 01:51:47 +00:00
|
|
|
"Value: %s: end of mib view", vb_type_name);
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
1999-12-12 01:51:47 +00:00
|
|
|
g_assert_not_reached();
|
|
|
|
return ASN1_ERR_WRONG_TYPE;
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
|
|
|
*lengthp = length;
|
|
|
|
return ASN1_ERR_NOERROR;
|
|
|
|
}
|
|
|
|
|
2000-05-15 03:15:12 +00:00
|
|
|
static void
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|
|
|
proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
|
1999-05-12 05:56:42 +00:00
|
|
|
{
|
1999-12-10 09:49:29 +00:00
|
|
|
gboolean def;
|
|
|
|
guint length;
|
|
|
|
guint sequence_length;
|
1999-06-12 04:17:19 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
guint32 request_id;
|
|
|
|
|
|
|
|
guint32 error_status;
|
|
|
|
|
|
|
|
guint32 error_index;
|
|
|
|
|
2000-05-15 03:15:12 +00:00
|
|
|
char *pdu_type_string;
|
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
subid_t *enterprise;
|
|
|
|
guint enterprise_length;
|
|
|
|
|
|
|
|
guint8 *agent_address;
|
|
|
|
guint agent_address_length;
|
|
|
|
|
|
|
|
guint32 trap_type;
|
1999-06-12 04:17:19 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
guint32 specific_type;
|
|
|
|
|
|
|
|
guint timestamp;
|
|
|
|
guint timestamp_length;
|
|
|
|
|
2000-06-28 05:15:13 +00:00
|
|
|
gchar *oid_string;
|
1999-12-10 09:49:29 +00:00
|
|
|
|
|
|
|
guint variable_bindings_length;
|
|
|
|
|
|
|
|
int vb_index;
|
|
|
|
guint variable_length;
|
|
|
|
subid_t *variable_oid;
|
|
|
|
guint variable_oid_length;
|
|
|
|
|
|
|
|
int ret;
|
|
|
|
guint cls, con, tag;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
pdu_type_string = val_to_str(pdu_type, pdu_types,
|
|
|
|
"Unknown PDU type %#x");
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1.offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, length,
|
1999-12-10 09:49:29 +00:00
|
|
|
"PDU type: %s", pdu_type_string);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
|
1999-05-12 05:56:42 +00:00
|
|
|
/* get the fields in the PDU preceeding the variable-bindings sequence */
|
1999-12-10 09:49:29 +00:00
|
|
|
switch (pdu_type) {
|
|
|
|
|
|
|
|
case SNMP_MSG_GET:
|
|
|
|
case SNMP_MSG_GETNEXT:
|
|
|
|
case SNMP_MSG_RESPONSE:
|
|
|
|
case SNMP_MSG_SET:
|
|
|
|
case SNMP_MSG_GETBULK:
|
|
|
|
case SNMP_MSG_INFORM:
|
2000-03-15 07:05:10 +00:00
|
|
|
case SNMP_MSG_TRAP2:
|
2000-05-15 03:15:12 +00:00
|
|
|
case SNMP_MSG_REPORT:
|
1999-12-10 09:49:29 +00:00
|
|
|
/* request id */
|
|
|
|
ret = asn1_uint32_decode (&asn1, &request_id, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"request ID", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, length,
|
1999-12-10 09:49:29 +00:00
|
|
|
"Request Id: %#x", request_id);
|
|
|
|
}
|
|
|
|
offset += length;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
2000-03-15 07:12:55 +00:00
|
|
|
/* error status, or getbulk non-repeaters */
|
1999-12-10 09:49:29 +00:00
|
|
|
ret = asn1_uint32_decode (&asn1, &error_status, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
2000-03-15 07:12:55 +00:00
|
|
|
(pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
|
|
|
|
: "error status",
|
|
|
|
ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
if (tree) {
|
2000-03-15 07:12:55 +00:00
|
|
|
if (pdu_type == SNMP_MSG_GETBULK) {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Non-repeaters: %u", error_status);
|
2000-03-15 07:12:55 +00:00
|
|
|
} else {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Error Status: %s",
|
2000-03-15 07:12:55 +00:00
|
|
|
val_to_str(error_status, error_statuses,
|
|
|
|
"Unknown (%d)"));
|
|
|
|
}
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
offset += length;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
2000-03-15 07:12:55 +00:00
|
|
|
/* error index, or getbulk max-repetitions */
|
1999-12-10 09:49:29 +00:00
|
|
|
ret = asn1_uint32_decode (&asn1, &error_index, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
2000-03-15 07:12:55 +00:00
|
|
|
(pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
|
|
|
|
: "error index",
|
|
|
|
ret);
|
1999-12-10 09:49:29 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-07-29 05:47:07 +00:00
|
|
|
if (tree) {
|
2000-03-15 07:12:55 +00:00
|
|
|
if (pdu_type == SNMP_MSG_GETBULK) {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Max repetitions: %u", error_index);
|
2000-03-15 07:12:55 +00:00
|
|
|
} else {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Error Index: %u", error_index);
|
2000-03-15 07:12:55 +00:00
|
|
|
}
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
offset += length;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SNMP_MSG_TRAP:
|
|
|
|
/* enterprise */
|
|
|
|
ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
|
|
|
|
&length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"enterprise OID", ret);
|
|
|
|
return;
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
if (tree) {
|
2000-06-28 05:15:13 +00:00
|
|
|
oid_string = format_oid(enterprise, enterprise_length);
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, length,
|
1999-12-10 09:49:29 +00:00
|
|
|
"Enterprise: %s", oid_string);
|
2000-06-28 05:15:13 +00:00
|
|
|
g_free(oid_string);
|
1999-12-10 09:49:29 +00:00
|
|
|
}
|
|
|
|
g_free(enterprise);
|
|
|
|
offset += length;
|
|
|
|
|
|
|
|
/* agent address */
|
2001-04-15 07:30:03 +00:00
|
|
|
start = asn1.offset;
|
1999-12-10 09:49:29 +00:00
|
|
|
ret = asn1_header_decode (&asn1, &cls, &con, &tag,
|
|
|
|
&def, &agent_address_length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"agent address", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
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" */
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"agent_address", ASN1_ERR_WRONG_TYPE);
|
|
|
|
return;
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
if (agent_address_length != 4) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
|
|
|
|
return;
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
2000-12-24 09:10:12 +00:00
|
|
|
ret = asn1_string_value_decode (&asn1,
|
1999-12-10 09:49:29 +00:00
|
|
|
agent_address_length, &agent_address);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"agent address", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1.offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (tree) {
|
2001-04-07 00:52:07 +00:00
|
|
|
if (agent_address_length != 4) {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset,
|
2001-04-07 00:52:07 +00:00
|
|
|
length,
|
|
|
|
"Agent address: <length is %u, not 4>",
|
|
|
|
agent_address_length);
|
|
|
|
} else {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset,
|
2001-04-07 00:52:07 +00:00
|
|
|
length,
|
|
|
|
"Agent address: %s",
|
|
|
|
ip_to_str(agent_address));
|
|
|
|
}
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
g_free(agent_address);
|
|
|
|
offset += length;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* generic trap type */
|
|
|
|
ret = asn1_uint32_decode (&asn1, &trap_type, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"generic trap type", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, length,
|
1999-12-10 09:49:29 +00:00
|
|
|
"Trap type: %s",
|
|
|
|
val_to_str(trap_type, trap_types, "Unknown (%u)"));
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
offset += length;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* specific trap type */
|
|
|
|
ret = asn1_uint32_decode (&asn1, &specific_type, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"specific trap type", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, length,
|
1999-12-10 09:49:29 +00:00
|
|
|
"Specific trap type: %u (%#x)",
|
|
|
|
specific_type, specific_type);
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
offset += length;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* timestamp */
|
2001-04-15 07:30:03 +00:00
|
|
|
start = asn1.offset;
|
1999-12-10 09:49:29 +00:00
|
|
|
ret = asn1_header_decode (&asn1, &cls, &con, &tag,
|
|
|
|
&def, ×tamp_length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"timestamp", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
|
|
|
|
(cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"timestamp", ASN1_ERR_WRONG_TYPE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ret = asn1_uint32_value_decode(&asn1, timestamp_length,
|
|
|
|
×tamp);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"timestamp", ret);
|
|
|
|
return;
|
|
|
|
}
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1.offset - start;
|
1999-12-10 09:49:29 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, length,
|
1999-12-10 09:49:29 +00:00
|
|
|
"Timestamp: %u", timestamp);
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
offset += length;
|
|
|
|
break;
|
1999-06-12 04:17:19 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
|
1999-05-12 05:56:42 +00:00
|
|
|
/* variable bindings */
|
1999-12-10 09:49:29 +00:00
|
|
|
/* get header for variable-bindings sequence */
|
|
|
|
ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"variable bindings header", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
offset += length;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
|
|
|
/* loop on variable bindings */
|
1999-12-10 09:49:29 +00:00
|
|
|
vb_index = 0;
|
|
|
|
while (variable_bindings_length > 0) {
|
1999-05-12 05:56:42 +00:00
|
|
|
vb_index++;
|
1999-12-10 09:49:29 +00:00
|
|
|
sequence_length = 0;
|
|
|
|
|
1999-05-12 05:56:42 +00:00
|
|
|
/* parse type */
|
1999-12-10 09:49:29 +00:00
|
|
|
ret = asn1_sequence_decode(&asn1, &variable_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"variable binding header", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
sequence_length += length;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* parse object identifier */
|
|
|
|
ret = asn1_oid_decode (&asn1, &variable_oid,
|
|
|
|
&variable_oid_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"variable binding OID", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
sequence_length += length;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
if (tree) {
|
2000-06-28 05:15:13 +00:00
|
|
|
oid_string = format_oid(variable_oid,
|
1999-12-10 09:49:29 +00:00
|
|
|
variable_oid_length);
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(tree, tvb, offset, sequence_length,
|
2002-03-11 01:48:08 +00:00
|
|
|
"Object identifier %d: %s", vb_index, oid_string);
|
2000-06-28 05:15:13 +00:00
|
|
|
g_free(oid_string);
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
offset += sequence_length;
|
|
|
|
variable_bindings_length -= sequence_length;
|
1999-05-12 05:56:42 +00:00
|
|
|
|
1999-12-10 09:49:29 +00:00
|
|
|
/* Parse the variable's value */
|
2000-05-15 03:15:12 +00:00
|
|
|
ret = snmp_variable_decode(tree, variable_oid,
|
2002-03-10 22:18:12 +00:00
|
|
|
variable_oid_length, &asn1, offset, &length);
|
1999-12-10 09:49:29 +00:00
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
1999-12-10 09:49:29 +00:00
|
|
|
"variable", ret);
|
1999-05-12 05:56:42 +00:00
|
|
|
return;
|
|
|
|
}
|
1999-12-10 09:49:29 +00:00
|
|
|
offset += length;
|
|
|
|
variable_bindings_length -= length;
|
1999-05-12 05:56:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-01-30 02:13:43 +00:00
|
|
|
static const value_string qos_vals[] = {
|
|
|
|
{ 0x0, "No authentication or privacy" },
|
|
|
|
{ 0x1, "Authentication, no privacy" },
|
|
|
|
{ 0x2, "Authentication and privacy" },
|
|
|
|
{ 0x3, "Authentication and privacy" },
|
|
|
|
{ 0, NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2001-04-15 07:51:11 +00:00
|
|
|
dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
|
2001-01-30 02:13:43 +00:00
|
|
|
guchar *parameters, int parameters_length)
|
|
|
|
{
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *parameters_tree;
|
|
|
|
proto_tree *qos_tree;
|
|
|
|
guint8 model;
|
|
|
|
guint8 qos;
|
|
|
|
guint8 len;
|
|
|
|
|
2001-04-15 07:51:11 +00:00
|
|
|
item = proto_tree_add_text(tree, tvb, offset, length,
|
2001-01-30 02:13:43 +00:00
|
|
|
"Parameters");
|
|
|
|
parameters_tree = proto_item_add_subtree(item, ett_parameters);
|
|
|
|
offset += length - parameters_length;
|
|
|
|
|
|
|
|
if (parameters_length < 1)
|
|
|
|
return;
|
|
|
|
model = *parameters;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, 1,
|
2001-01-30 02:13:43 +00:00
|
|
|
"model: %u", model);
|
|
|
|
offset += 1;
|
|
|
|
parameters += 1;
|
|
|
|
parameters_length -= 1;
|
|
|
|
if (model != 1) {
|
|
|
|
/* Unknown model. */
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset,
|
2001-01-30 02:13:43 +00:00
|
|
|
parameters_length, "parameters: %s",
|
|
|
|
bytes_to_str(parameters, parameters_length));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parameters_length < 1)
|
|
|
|
return;
|
|
|
|
qos = *parameters;
|
2001-04-15 07:51:11 +00:00
|
|
|
item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
|
2001-01-30 02:13:43 +00:00
|
|
|
"qoS: 0x%x", qos);
|
|
|
|
qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
|
2001-01-30 02:13:43 +00:00
|
|
|
decode_boolean_bitfield(qos, 0x04,
|
|
|
|
8, "Generation of report PDU allowed",
|
|
|
|
"Generation of report PDU not allowed"));
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
|
2001-01-30 02:13:43 +00:00
|
|
|
decode_enumerated_bitfield(qos, 0x03,
|
|
|
|
8, qos_vals, "%s"));
|
|
|
|
offset += 1;
|
|
|
|
parameters += 1;
|
|
|
|
parameters_length -= 1;
|
|
|
|
|
|
|
|
if (parameters_length < 12)
|
|
|
|
return;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, 12,
|
2001-01-30 02:13:43 +00:00
|
|
|
"agentID: %s", bytes_to_str(parameters, 12));
|
|
|
|
offset += 12;
|
|
|
|
parameters += 12;
|
|
|
|
parameters_length -= 12;
|
|
|
|
|
|
|
|
if (parameters_length < 4)
|
|
|
|
return;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, 4,
|
2001-01-30 02:13:43 +00:00
|
|
|
"agentBoots: %u", pntohl(parameters));
|
|
|
|
offset += 4;
|
|
|
|
parameters += 4;
|
|
|
|
parameters_length -= 4;
|
|
|
|
|
|
|
|
if (parameters_length < 4)
|
|
|
|
return;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, 4,
|
2001-01-30 02:13:43 +00:00
|
|
|
"agentTime: %u", pntohl(parameters));
|
|
|
|
offset += 4;
|
|
|
|
parameters += 4;
|
|
|
|
parameters_length -= 4;
|
|
|
|
|
|
|
|
if (parameters_length < 2)
|
|
|
|
return;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, 2,
|
2001-01-30 02:13:43 +00:00
|
|
|
"maxSize: %u", pntohs(parameters));
|
|
|
|
offset += 2;
|
|
|
|
parameters += 2;
|
|
|
|
parameters_length -= 2;
|
|
|
|
|
|
|
|
if (parameters_length < 1)
|
|
|
|
return;
|
|
|
|
len = *parameters;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, 1,
|
2001-01-30 02:13:43 +00:00
|
|
|
"userLen: %u", len);
|
|
|
|
offset += 1;
|
|
|
|
parameters += 1;
|
|
|
|
parameters_length -= 1;
|
|
|
|
|
|
|
|
if (parameters_length < len)
|
|
|
|
return;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, len,
|
2001-01-30 02:13:43 +00:00
|
|
|
"userName: %.*s", len, parameters);
|
|
|
|
offset += len;
|
|
|
|
parameters += len;
|
|
|
|
parameters_length -= len;
|
|
|
|
|
|
|
|
if (parameters_length < 1)
|
|
|
|
return;
|
|
|
|
len = *parameters;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, 1,
|
2001-01-30 02:13:43 +00:00
|
|
|
"authLen: %u", len);
|
|
|
|
offset += 1;
|
|
|
|
parameters += 1;
|
|
|
|
parameters_length -= 1;
|
|
|
|
|
|
|
|
if (parameters_length < len)
|
|
|
|
return;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, len,
|
2001-01-30 02:13:43 +00:00
|
|
|
"authDigest: %s", bytes_to_str(parameters, len));
|
|
|
|
offset += len;
|
|
|
|
parameters += len;
|
|
|
|
parameters_length -= len;
|
|
|
|
|
|
|
|
if (parameters_length < 1)
|
|
|
|
return;
|
2001-04-15 07:51:11 +00:00
|
|
|
proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
|
2001-01-30 02:13:43 +00:00
|
|
|
"contextSelector: %s", bytes_to_str(parameters, parameters_length));
|
|
|
|
}
|
|
|
|
|
2000-05-15 03:15:12 +00:00
|
|
|
void
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
2000-05-15 03:15:12 +00:00
|
|
|
proto_tree *tree, char *proto_name, int proto, gint ett)
|
|
|
|
{
|
|
|
|
ASN1_SCK asn1;
|
2001-04-15 07:30:03 +00:00
|
|
|
int start;
|
2000-05-15 03:15:12 +00:00
|
|
|
gboolean def;
|
|
|
|
gboolean encrypted;
|
|
|
|
guint length;
|
|
|
|
guint message_length;
|
|
|
|
guint global_length;
|
|
|
|
|
|
|
|
guint32 version;
|
|
|
|
guint32 msgid;
|
|
|
|
guint32 msgmax;
|
|
|
|
guint32 msgsec;
|
|
|
|
guint32 engineboots;
|
|
|
|
guint32 enginetime;
|
|
|
|
|
|
|
|
guchar *msgflags;
|
|
|
|
guchar *community;
|
|
|
|
guchar *secparm;
|
|
|
|
guchar *cengineid;
|
|
|
|
guchar *cname;
|
|
|
|
guchar *cryptpdu;
|
|
|
|
guchar *aengineid;
|
|
|
|
guchar *username;
|
|
|
|
guchar *authpar;
|
|
|
|
guchar *privpar;
|
|
|
|
int msgflags_length;
|
|
|
|
int community_length;
|
|
|
|
int secparm_length;
|
|
|
|
int cengineid_length;
|
|
|
|
int cname_length;
|
|
|
|
int cryptpdu_length;
|
|
|
|
int aengineid_length;
|
|
|
|
int username_length;
|
|
|
|
int authpar_length;
|
|
|
|
int privpar_length;
|
|
|
|
|
|
|
|
guint pdu_type;
|
|
|
|
guint pdu_length;
|
|
|
|
|
|
|
|
proto_tree *snmp_tree = NULL;
|
|
|
|
proto_tree *global_tree = NULL;
|
|
|
|
proto_tree *flags_tree = NULL;
|
|
|
|
proto_tree *secur_tree = NULL;
|
|
|
|
proto_item *item = NULL;
|
|
|
|
int ret;
|
|
|
|
guint cls, con, tag;
|
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
|
|
col_add_str(pinfo->cinfo, COL_PROTOCOL, proto_name);
|
2000-05-15 03:15:12 +00:00
|
|
|
|
|
|
|
if (tree) {
|
2002-01-24 09:20:54 +00:00
|
|
|
item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
|
2000-05-15 03:15:12 +00:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
/* parse the SNMP header */
|
2001-04-15 07:30:03 +00:00
|
|
|
asn1_open(&asn1, tvb, offset);
|
2000-05-15 03:15:12 +00:00
|
|
|
ret = asn1_sequence_decode(&asn1, &message_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"message header", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
|
|
|
|
ret = asn1_uint32_decode (&asn1, &version, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2001-04-06 23:12:33 +00:00
|
|
|
"version number", ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"Version: %s",
|
|
|
|
val_to_str(version, versions, "Unknown version %#x"));
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
|
|
|
|
|
|
|
|
switch (version) {
|
|
|
|
case SNMP_VERSION_1:
|
|
|
|
case SNMP_VERSION_2c:
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &community,
|
|
|
|
&community_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"community", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, tvb, offset, length,
|
2000-07-02 07:10:16 +00:00
|
|
|
"Community: %.*s", community_length,
|
|
|
|
SAFE_STRING(community));
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
g_free(community);
|
|
|
|
offset += length;
|
|
|
|
break;
|
|
|
|
case SNMP_VERSION_2u:
|
2001-01-30 02:13:43 +00:00
|
|
|
ret = asn1_octet_string_decode (&asn1, &community,
|
|
|
|
&community_length, &length);
|
|
|
|
if (tree) {
|
2001-04-15 07:51:11 +00:00
|
|
|
dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
|
2001-01-30 02:13:43 +00:00
|
|
|
community, community_length);
|
|
|
|
}
|
|
|
|
g_free(community);
|
|
|
|
offset += length;
|
2000-05-15 03:15:12 +00:00
|
|
|
break;
|
|
|
|
case SNMP_VERSION_3:
|
|
|
|
ret = asn1_sequence_decode(&asn1, &global_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"message global header", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
item = proto_tree_add_text(snmp_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
global_length + length, "Message Global Header");
|
|
|
|
global_tree = proto_item_add_subtree(item, ett_global);
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(global_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length,
|
|
|
|
"Message Global Header Length: %d", global_length);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_uint32_decode (&asn1, &msgid, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"message id", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (global_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(global_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Message ID: %d", msgid);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_uint32_decode (&asn1, &msgmax, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"message max size", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (global_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(global_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Message Max Size: %d", msgmax);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &msgflags,
|
|
|
|
&msgflags_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"message flags", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (msgflags_length != 1) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"message flags wrong length", ret);
|
|
|
|
g_free(msgflags);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (global_tree) {
|
|
|
|
item = proto_tree_add_uint_format(global_tree,
|
2001-04-15 07:30:03 +00:00
|
|
|
hf_snmpv3_flags, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
msgflags[0], "Flags: 0x%02x", msgflags[0]);
|
|
|
|
flags_tree = proto_item_add_subtree(item, ett_flags);
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
|
2001-04-15 07:30:03 +00:00
|
|
|
tvb, offset, length, msgflags[0]);
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
|
2001-04-15 07:30:03 +00:00
|
|
|
tvb, offset, length, msgflags[0]);
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
|
2001-04-15 07:30:03 +00:00
|
|
|
tvb, offset, length, msgflags[0]);
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
encrypted = msgflags[0] & TH_CRYPT;
|
|
|
|
g_free(msgflags);
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_uint32_decode (&asn1, &msgsec, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"message security model", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (global_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(global_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Message Security Model: %s",
|
|
|
|
val_to_str(msgsec, sec_models,
|
|
|
|
"Unknown model %#x"));
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
switch(msgsec) {
|
|
|
|
case SNMP_SEC_USM:
|
2001-04-15 07:30:03 +00:00
|
|
|
start = asn1.offset;
|
2000-05-15 03:15:12 +00:00
|
|
|
ret = asn1_header_decode (&asn1, &cls, &con, &tag,
|
|
|
|
&def, &secparm_length);
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1.offset - start;
|
2000-05-15 03:15:12 +00:00
|
|
|
if (cls != ASN1_UNI && con != ASN1_PRI &&
|
|
|
|
tag != ASN1_OTS) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "Message Security Parameters",
|
2000-05-15 03:15:12 +00:00
|
|
|
ASN1_ERR_WRONG_TYPE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
item = proto_tree_add_text(snmp_tree, tvb,
|
2000-05-15 03:15:12 +00:00
|
|
|
offset, secparm_length + length,
|
|
|
|
"Message Security Parameters");
|
|
|
|
secur_tree = proto_item_add_subtree(item,
|
|
|
|
ett_secur);
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(secur_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length,
|
|
|
|
"Message Security Parameters Length: %d",
|
|
|
|
secparm_length);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_sequence_decode(&asn1, &secparm_length,
|
|
|
|
&length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "USM sequence header", ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &aengineid,
|
|
|
|
&aengineid_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "authoritative engine id", ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (secur_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(secur_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Authoritative Engine ID: %s",
|
|
|
|
bytes_to_str(aengineid, aengineid_length));
|
|
|
|
}
|
|
|
|
g_free(aengineid);
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_uint32_decode (&asn1, &engineboots, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "engine boots", ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (secur_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(secur_tree, tvb,
|
2000-05-15 03:15:12 +00:00
|
|
|
offset, length, "Engine Boots: %d",
|
|
|
|
engineboots);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_uint32_decode (&asn1, &enginetime, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "engine time", ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (secur_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(secur_tree, tvb,
|
2000-05-15 03:15:12 +00:00
|
|
|
offset, length, "Engine Time: %d",
|
|
|
|
enginetime);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &username,
|
|
|
|
&username_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "user name", ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (secur_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(secur_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "User Name: %.*s",
|
2000-07-02 07:10:16 +00:00
|
|
|
username_length,
|
|
|
|
SAFE_STRING(username));
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
g_free(username);
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &authpar,
|
|
|
|
&authpar_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "authentication parameter", ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (secur_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(secur_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Authentication Parameter: %s",
|
|
|
|
bytes_to_str(authpar, authpar_length));
|
|
|
|
}
|
|
|
|
g_free(authpar);
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &privpar,
|
|
|
|
&privpar_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "privacy parameter", ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (secur_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(secur_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length, "Privacy Parameter: %s",
|
|
|
|
bytes_to_str(privpar, privpar_length));
|
|
|
|
}
|
|
|
|
g_free(privpar);
|
|
|
|
offset += length;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = asn1_octet_string_decode (&asn1,
|
|
|
|
&secparm, &secparm_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "Message Security Parameters",
|
|
|
|
ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
length,
|
|
|
|
"Message Security Parameters Data"
|
|
|
|
" (%d bytes)", secparm_length);
|
|
|
|
}
|
|
|
|
g_free(secparm);
|
|
|
|
offset += length;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* PDU starts here */
|
|
|
|
if (encrypted) {
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &cryptpdu,
|
|
|
|
&cryptpdu_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo,
|
2001-04-06 23:12:33 +00:00
|
|
|
snmp_tree, "encrypted PDU header", ret);
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"Encrypted PDU (%d bytes)", length);
|
|
|
|
g_free(cryptpdu);
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_set_str(pinfo->cinfo, COL_INFO, "Encrypted PDU");
|
2000-05-15 03:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ret = asn1_sequence_decode(&asn1, &global_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU header", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &cengineid,
|
|
|
|
&cengineid_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"context engine id", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"Context Engine ID: %s",
|
|
|
|
bytes_to_str(cengineid, cengineid_length));
|
|
|
|
}
|
|
|
|
g_free(cengineid);
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &cname,
|
|
|
|
&cname_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"context name", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (snmp_tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(snmp_tree, tvb, offset, length,
|
2000-07-02 07:10:16 +00:00
|
|
|
"Context Name: %.*s", cname_length,
|
|
|
|
SAFE_STRING(cname));
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
g_free(cname);
|
|
|
|
offset += length;
|
|
|
|
break;
|
|
|
|
default:
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU for unknown version of SNMP");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-04-15 07:30:03 +00:00
|
|
|
start = asn1.offset;
|
2000-05-15 03:15:12 +00:00
|
|
|
ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
|
|
|
|
&pdu_length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU type", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cls != ASN1_CTX || con != ASN1_CON) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU type", ASN1_ERR_WRONG_TYPE);
|
|
|
|
return;
|
|
|
|
}
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
2000-05-19 07:00:04 +00:00
|
|
|
proto_tree *tree, int proto, gint ett)
|
2000-05-15 03:15:12 +00:00
|
|
|
{
|
|
|
|
ASN1_SCK asn1;
|
2001-04-15 07:30:03 +00:00
|
|
|
int start;
|
2000-05-15 03:15:12 +00:00
|
|
|
gboolean def;
|
|
|
|
guint length;
|
|
|
|
|
|
|
|
guint pdu_type;
|
|
|
|
char *pdu_type_string;
|
|
|
|
guint pdu_length;
|
|
|
|
|
|
|
|
guint32 version;
|
|
|
|
guint32 cause;
|
|
|
|
guint32 priority;
|
|
|
|
guint32 operation;
|
|
|
|
guint32 commit;
|
|
|
|
|
|
|
|
guchar *password;
|
|
|
|
int password_length;
|
|
|
|
|
|
|
|
guchar *application;
|
|
|
|
int application_length;
|
|
|
|
|
|
|
|
subid_t *regid;
|
|
|
|
guint regid_length;
|
|
|
|
|
2000-06-28 05:15:13 +00:00
|
|
|
gchar *oid_string;
|
2000-05-15 03:15:12 +00:00
|
|
|
|
|
|
|
proto_tree *smux_tree = NULL;
|
|
|
|
proto_item *item = NULL;
|
|
|
|
int ret;
|
|
|
|
guint cls, con;
|
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
|
2000-05-15 03:15:12 +00:00
|
|
|
|
|
|
|
if (tree) {
|
2002-01-24 09:20:54 +00:00
|
|
|
item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
|
2000-05-15 03:15:12 +00:00
|
|
|
smux_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.
|
|
|
|
*/
|
|
|
|
/* parse the SNMP header */
|
2001-04-15 07:30:03 +00:00
|
|
|
asn1_open(&asn1, tvb, offset);
|
|
|
|
start = asn1.offset;
|
2000-05-15 03:15:12 +00:00
|
|
|
ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
|
|
|
|
&pdu_length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU type", ret);
|
|
|
|
return;
|
|
|
|
}
|
2000-06-28 05:15:13 +00:00
|
|
|
|
2000-05-15 03:15:12 +00:00
|
|
|
/* 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,
|
|
|
|
"Unknown PDU type %#x");
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1.offset - start;
|
2000-05-15 03:15:12 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU type: %s", pdu_type_string);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_uint32_decode (&asn1, &version, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"version", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"Version: %d", version);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
|
|
|
|
ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"registration OID", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2000-06-28 05:15:13 +00:00
|
|
|
oid_string = format_oid(regid, regid_length);
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"Registration: %s", oid_string);
|
2000-06-28 05:15:13 +00:00
|
|
|
g_free(oid_string);
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
g_free(regid);
|
|
|
|
offset += length;
|
|
|
|
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &application,
|
|
|
|
&application_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"application", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"Application: %.*s", application_length,
|
2000-07-02 07:10:16 +00:00
|
|
|
SAFE_STRING(application));
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
g_free(application);
|
|
|
|
offset += length;
|
|
|
|
|
|
|
|
ret = asn1_octet_string_decode (&asn1, &password,
|
|
|
|
&password_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"password", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-07-02 07:10:16 +00:00
|
|
|
"Password: %.*s", password_length,
|
|
|
|
SAFE_STRING(password));
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
g_free(password);
|
|
|
|
offset += length;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
|
|
|
|
pdu_type_string = val_to_str(pdu_type, smux_types,
|
|
|
|
"Unknown PDU type %#x");
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1.offset - start;
|
2000-05-15 03:15:12 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU type: %s", pdu_type_string);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"cause", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
pdu_length, "Cause: %s",
|
|
|
|
val_to_str(cause, smux_close,
|
|
|
|
"Unknown cause %#x"));
|
|
|
|
}
|
|
|
|
offset += pdu_length;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
|
|
|
|
pdu_type_string = val_to_str(pdu_type, smux_types,
|
|
|
|
"Unknown PDU type %#x");
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1.offset - start;
|
2000-05-15 03:15:12 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU type: %s", pdu_type_string);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"registration subtree", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2000-06-28 05:15:13 +00:00
|
|
|
oid_string = format_oid(regid, regid_length);
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"Registration: %s", oid_string);
|
2000-06-28 05:15:13 +00:00
|
|
|
g_free(oid_string);
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
g_free(regid);
|
|
|
|
offset += length;
|
|
|
|
|
|
|
|
ret = asn1_uint32_decode (&asn1, &priority, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"priority", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"Priority: %d", priority);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
|
|
|
|
ret = asn1_uint32_decode (&asn1, &operation, &length);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"operation", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"Operation: %s",
|
|
|
|
val_to_str(operation, smux_rreq,
|
|
|
|
"Unknown operation %#x"));
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
|
|
|
|
pdu_type_string = val_to_str(pdu_type, smux_types,
|
|
|
|
"Unknown PDU type %#x");
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1.offset - start;
|
2000-05-15 03:15:12 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU type: %s", pdu_type_string);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"priority", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
pdu_length, "%s",
|
|
|
|
val_to_str(priority, smux_prio,
|
|
|
|
"Priority: %#x"));
|
|
|
|
}
|
|
|
|
offset += pdu_length;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
|
|
|
|
pdu_type_string = val_to_str(pdu_type, smux_types,
|
|
|
|
"Unknown PDU type %#x");
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
|
2001-04-15 07:30:03 +00:00
|
|
|
length = asn1.offset - start;
|
2000-05-15 03:15:12 +00:00
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset, length,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU type: %s", pdu_type_string);
|
|
|
|
}
|
|
|
|
offset += length;
|
|
|
|
ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"commit", ret);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (tree) {
|
2001-04-15 07:30:03 +00:00
|
|
|
proto_tree_add_text(smux_tree, tvb, offset,
|
2000-05-15 03:15:12 +00:00
|
|
|
pdu_length, "%s",
|
|
|
|
val_to_str(commit, smux_sout,
|
|
|
|
"Unknown SOUT Value: %#x"));
|
|
|
|
}
|
|
|
|
offset += pdu_length;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cls != ASN1_CTX || con != ASN1_CON) {
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
|
2000-05-15 03:15:12 +00:00
|
|
|
"PDU type", ASN1_ERR_WRONG_TYPE);
|
|
|
|
return;
|
|
|
|
}
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
|
2000-05-30 03:35:55 +00:00
|
|
|
static void
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
1999-12-05 02:33:52 +00:00
|
|
|
{
|
2000-10-21 18:52:17 +00:00
|
|
|
conversation_t *conversation;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The first SNMP packet goes to the SNMP port; the second one
|
|
|
|
* may come from some *other* port, but goes back to the same
|
|
|
|
* IP address and port as the ones from which the first packet
|
|
|
|
* came; all subsequent packets presumably go between those two
|
|
|
|
* IP addresses and ports.
|
|
|
|
*
|
|
|
|
* If this packet went to the SNMP port, we check to see if
|
2001-06-10 09:50:20 +00:00
|
|
|
* there's already a conversation with one address/port pair
|
|
|
|
* matching the source IP address and port of this packet,
|
|
|
|
* the other address matching the destination IP address of this
|
|
|
|
* packet, and any destination port.
|
|
|
|
*
|
|
|
|
* If not, we create one, with its address 1/port 1 pair being
|
|
|
|
* the source address/port of this packet, its address 2 being
|
|
|
|
* the destination address of this packet, and its port 2 being
|
|
|
|
* wildcarded, and give it the SNMP dissector as a dissector.
|
2000-10-21 18:52:17 +00:00
|
|
|
*/
|
2001-04-15 07:30:03 +00:00
|
|
|
if (pinfo->destport == UDP_PORT_SNMP) {
|
|
|
|
conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
|
2001-06-10 09:50:20 +00:00
|
|
|
pinfo->srcport, 0, NO_PORT_B);
|
2000-10-21 18:52:17 +00:00
|
|
|
if (conversation == NULL) {
|
2001-04-15 07:30:03 +00:00
|
|
|
conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
|
2001-09-03 10:33:12 +00:00
|
|
|
pinfo->srcport, 0, NO_PORT2);
|
2001-11-27 07:13:32 +00:00
|
|
|
conversation_set_dissector(conversation, snmp_handle);
|
2000-10-21 18:52:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_snmp_pdu(tvb, 0, pinfo, tree, "SNMP", proto_snmp, ett_snmp);
|
1999-12-05 02:33:52 +00:00
|
|
|
}
|
|
|
|
|
2000-05-15 03:15:12 +00:00
|
|
|
static void
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
2000-05-15 03:15:12 +00:00
|
|
|
{
|
2001-04-15 07:30:03 +00:00
|
|
|
dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
|
2000-05-15 03:15:12 +00:00
|
|
|
}
|
|
|
|
|
1999-07-29 05:47:07 +00:00
|
|
|
void
|
|
|
|
proto_register_snmp(void)
|
|
|
|
{
|
2000-05-15 03:15:12 +00:00
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{ &hf_snmpv3_flags,
|
|
|
|
{ "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
|
2001-06-18 02:18:27 +00:00
|
|
|
0x0, "", HFILL }},
|
2000-05-15 03:15:12 +00:00
|
|
|
{ &hf_snmpv3_flags_auth,
|
|
|
|
{ "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
|
2001-06-18 02:18:27 +00:00
|
|
|
TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
|
2000-05-15 03:15:12 +00:00
|
|
|
{ &hf_snmpv3_flags_crypt,
|
|
|
|
{ "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
|
2001-06-18 02:18:27 +00:00
|
|
|
TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
|
2000-05-15 03:15:12 +00:00
|
|
|
{ &hf_snmpv3_flags_report,
|
|
|
|
{ "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
|
2001-06-18 02:18:27 +00:00
|
|
|
TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
|
2000-05-15 03:15:12 +00:00
|
|
|
};
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_snmp,
|
2000-05-15 03:15:12 +00:00
|
|
|
&ett_smux,
|
2001-01-30 02:13:43 +00:00
|
|
|
&ett_parameters,
|
|
|
|
&ett_parameters_qos,
|
2000-05-15 03:15:12 +00:00
|
|
|
&ett_global,
|
|
|
|
&ett_flags,
|
|
|
|
&ett_secur,
|
1999-11-16 11:44:20 +00:00
|
|
|
};
|
1999-07-29 05:47:07 +00:00
|
|
|
|
1999-12-12 01:51:47 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_SNMP_H
|
2002-03-10 22:18:12 +00:00
|
|
|
init_mib();
|
2002-03-10 23:17:00 +00:00
|
|
|
ds_set_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY, 2);
|
Instead of calling "snmp_set_full_objid()" to cause OIDs to be displayed
symbolically as full sequences, call "snmp_set_suffix_only(2)" to cause
them to be displayed symbolically as a module name and a name within
that module, as that might make it easier to find the RFC or whatever
that describes the object in question.
Don't just statically call it, though, on Linux, as that causes binaries
built on Red Hat releases prior to 6.2 to fail to run on 6.2, due to the
UCD SNMP 4.1.1 library used in RH 6.2 not being 100% binary-compatible
with the UCD SNMP libraries used in those prior releases. Instead, on
Linux, try to "dlopen()" the "libsnmp.so" library and, if that succeeds,
try to find "snmp_set_suffix_only()" in that library - if that succeeds,
call it, otherwise try to find "ds_set_int()" in that library and, if
*that* succeeds, call it with the arguments that, in UCD SNMP 4.1.1, the
"snmp_set_suffix_only()" macro passes to it.
svn path=/trunk/; revision=2077
2000-06-17 05:56:22 +00:00
|
|
|
#endif /* HAVE_UCD_SNMP_SNMP_H */
|
2001-01-03 06:56:03 +00:00
|
|
|
proto_snmp = proto_register_protocol("Simple Network Management Protocol",
|
|
|
|
"SNMP", "snmp");
|
|
|
|
proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
|
|
|
|
"SMUX", "smux");
|
2000-05-15 03:15:12 +00:00
|
|
|
proto_register_field_array(proto_snmp, hf, array_length(hf));
|
1999-12-05 02:33:52 +00:00
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2001-11-27 07:13:32 +00:00
|
|
|
snmp_handle = create_dissector_handle(dissect_snmp, proto_snmp);
|
1999-10-27 02:05:09 +00:00
|
|
|
}
|
2000-04-08 07:07:42 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_snmp(void)
|
|
|
|
{
|
2001-12-03 04:00:26 +00:00
|
|
|
dissector_handle_t smux_handle;
|
|
|
|
|
|
|
|
dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
|
|
|
|
dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
|
|
|
|
smux_handle = create_dissector_handle(dissect_smux, proto_smux);
|
|
|
|
dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);
|
|
|
|
dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
|
|
|
|
dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
|
|
|
|
dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
|
2001-11-26 04:52:51 +00:00
|
|
|
data_handle = find_dissector("data");
|
2000-04-08 07:07:42 +00:00
|
|
|
}
|