Convert asn1 template files proto_tree_add_item() 'encoding' arg for field types...
[obnox/wireshark/wip.git] / epan / dissectors / packet-snmp.c
index 4a3965a85ac1181e3a9c31ef6bd5460a503221d8..926ec8ea39bb931a151596fc2095519782e76604 100644 (file)
@@ -1,3 +1,11 @@
+/* Do not modify this file.                                                   */
+/* It is created automatically by the ASN.1 to Wireshark dissector compiler   */
+/* packet-snmp.c                                                              */
+/* ../../tools/asn2wrs.py -b -p snmp -c ./snmp.cnf -s ./packet-snmp-template -D . -O ../../epan/dissectors snmp.asn */
+
+/* Input file: packet-snmp-template.c */
+
+#line 1 "../../asn1/snmp/packet-snmp-template.c"
 /* packet-snmp.c
  * Routines for SNMP (simple network management protocol)
  * Copyright (C) 1998 Didier Jorand
  * See RFCs 1905, 1906, 1909, and 1910 for SNMPv2u [historic].
  *
  * See RFCs 2570-2576 for SNMPv3
+ * Updated to use the asn2wrs compiler made by Tomas Kukosa
+ * Copyright (C) 2005 - 2006 Anders Broman [AT] ericsson.com
+ *
+ * See RFC 3414 for User-based Security Model for SNMPv3
+ * See RFC 3826 for  (AES) Cipher Algorithm in the SNMP USM
+ * See RFC 2578 for Structure of Management Information Version 2 (SMIv2)
+ * Copyright (C) 2007 Luis E. Garcia Ontanon <luis@ontanon.org>
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * Some stuff from:
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#define D(args) do {printf args; fflush(stdout); } while(0)
+
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
 
-#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 
 #include <glib.h>
 
-#include "isprint.h"
-
 #include <epan/packet.h>
 #include <epan/strutil.h>
 #include <epan/conversation.h>
-#include "etypes.h"
+#include <epan/etypes.h>
 #include <epan/prefs.h>
+#include <epan/sminmpec.h>
+#include <epan/emem.h>
+#include <epan/next_tvb.h>
+#include <epan/uat.h>
+#include <epan/asn1.h>
 #include "packet-ipx.h"
 #include "packet-hpext.h"
-#include "packet-frame.h"
-
-#ifdef HAVE_SOME_SNMP
-
-#ifdef HAVE_NET_SNMP
-# include <net-snmp/net-snmp-config.h>
-# include <net-snmp/mib_api.h>
-# include <net-snmp/library/default_store.h>
-# include <net-snmp/config_api.h>
-#else /* HAVE_NET_SNMP */
-# include <ucd-snmp/ucd-snmp-config.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/read_config.h>
-# include <ucd-snmp/tools.h>
-#endif /* HAVE_NET_SNMP */
-
-#ifndef NETSNMP_DS_LIBRARY_ID
-# define NETSNMP_DS_LIBRARY_ID DS_LIBRARY_ID
-# define NETSNMP_DS_LIB_NO_TOKEN_WARNINGS DS_LIB_NO_TOKEN_WARNINGS
-# define NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY DS_LIB_PRINT_SUFFIX_ONLY
-# define netsnmp_ds_set_boolean ds_set_boolean
-# define netsnmp_ds_set_int ds_set_int
-#endif
 
-#ifdef _WIN32
-# include <epan/filesystem.h>
-#endif /* _WIN32 */
-
-   /*
-    * Define values "sprint_realloc_value()" expects.
-    */
-# define VALTYPE_INTEGER       ASN_INTEGER
-# define VALTYPE_COUNTER       ASN_COUNTER
-# define VALTYPE_GAUGE         ASN_GAUGE
-# define VALTYPE_TIMETICKS     ASN_TIMETICKS
-# define VALTYPE_STRING                ASN_OCTET_STR
-# define VALTYPE_IPADDR                ASN_IPADDRESS
-# define VALTYPE_OPAQUE                ASN_OPAQUE
-# define VALTYPE_NSAP          ASN_NSAP
-# define VALTYPE_OBJECTID      ASN_OBJECT_ID
-# define VALTYPE_BITSTR                ASN_BIT_STR
-# define VALTYPE_COUNTER64     ASN_COUNTER64
-
-#endif /* HAVE_SOME_SNMP */
-
-#include "asn1.h"
+
+#include "packet-ber.h"
 
 #include "packet-snmp.h"
-#include "format-oid.h"
+
+#include <epan/crypt/crypt-sha1.h>
+#include <epan/crypt/crypt-md5.h>
+#include <epan/expert.h>
+#include <epan/report_err.h>
+#include <epan/oids.h>
+
+
+#ifdef HAVE_LIBGCRYPT
+#include <gcrypt.h>
+#endif
 
 /* 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,
    non-printable characters in the string by escaping them. */
 #define        SAFE_STRING(s, l)       (((s) != NULL) ? format_text((s), (l)) : "")
 
-static int proto_snmp = -1;
-
-/* Default MIB modules to load */
-#define DEF_MIB_MODULES "IP-MIB:IF-MIB:TCP-MIB:UDP-MIB:SNMPv2-MIB:RFC1213-MIB:UCD-SNMP-MIB"
-
-static gchar *mib_modules = DEF_MIB_MODULES;
-static gboolean display_oid = TRUE;
-
-/* Subdissector tables */
-static dissector_table_t variable_oid_dissector_table;
+#define PNAME  "Simple Network Management Protocol"
+#define PSNAME "SNMP"
+#define PFNAME "snmp"
 
-static gint ett_snmp = -1;
-static gint ett_parameters = -1;
-static gint ett_parameters_qos = -1;
-static gint ett_global = -1;
-static gint ett_flags = -1;
-static gint ett_secur = -1;
-
-static int hf_snmp_version = -1;
-static int hf_snmp_community = -1;
-static int hf_snmp_request_id = -1;
-static int hf_snmp_pdutype = -1;
-static int hf_snmp_agent = -1;
-static int hf_snmp_enterprise = -1;
-static int hf_snmp_error_status = -1;
-static int hf_snmp_oid = -1;
-static int hf_snmp_traptype = -1;
-static int hf_snmp_spectraptype = -1;
-static int hf_snmp_timestamp = -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;
+#define UDP_PORT_SNMP          161
+#define UDP_PORT_SNMP_TRAP     162
+#define TCP_PORT_SNMP          161
+#define TCP_PORT_SNMP_TRAP     162
+#define TCP_PORT_SMUX          199
+#define UDP_PORT_SNMP_PATROL 8161
 
+/* Initialize the protocol and registered fields */
+static int proto_snmp = -1;
 static int proto_smux = -1;
 
-static gint ett_smux = -1;
+static gboolean display_oid = TRUE;
+static gboolean snmp_var_in_tree = TRUE;
 
-static int hf_smux_version = -1;
-static int hf_smux_pdutype = -1;
+static gboolean snmp_usm_auth_md5(snmp_usm_params_t* p, guint8**, guint*, gchar const**);
+static gboolean snmp_usm_auth_sha1(snmp_usm_params_t* p, guint8**, guint*, gchar const**);
 
-/* desegmentation of SNMP-over-TCP */
-static gboolean snmp_desegment = TRUE;
+static tvbuff_t* snmp_usm_priv_des(snmp_usm_params_t*, tvbuff_t*, gchar const**);
+static tvbuff_t* snmp_usm_priv_aes(snmp_usm_params_t*, tvbuff_t*, gchar const**);
 
-static dissector_handle_t snmp_handle;
-static dissector_handle_t data_handle;
 
-#define TH_AUTH   0x01
-#define TH_CRYPT  0x02
-#define TH_REPORT 0x04
+static void snmp_usm_password_to_key_md5(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
+static void snmp_usm_password_to_key_sha1(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
 
-#define UDP_PORT_SNMP          161
-#define UDP_PORT_SNMP_TRAP     162
-#define TCP_PORT_SNMP          161
-#define TCP_PORT_SNMP_TRAP     162
-#define TCP_PORT_SMUX          199
 
-/* 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,       "1" },
-       { SNMP_VERSION_2c,      "2C" },
-       { SNMP_VERSION_2u,      "2U" },
-       { SNMP_VERSION_3,       "3" },
-       { 0,                    NULL },
-};
+static snmp_usm_auth_model_t model_md5 = {snmp_usm_password_to_key_md5, snmp_usm_auth_md5, 16};
+static snmp_usm_auth_model_t model_sha1 = {snmp_usm_password_to_key_sha1, snmp_usm_auth_sha1, 20};
 
-/* defined in net-SNMP; include/net-snmp/library/snmp.h */
-#undef SNMP_MSG_GET
-#undef SNMP_MSG_SET
-#undef SNMP_MSG_GETNEXT
-#undef SNMP_MSG_RESPONSE
-#undef SNMP_MSG_TRAP
-#undef SNMP_MSG_GETBULK
-#undef SNMP_MSG_INFORM
-#undef SNMP_MSG_TRAP2
-#undef SNMP_MSG_REPORT
-#undef SNMP_NOSUCHOBJECT
-#undef SNMP_NOSUCHINSTANCE
-#undef SNMP_ENDOFMIBVIEW
-
-/* 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" },
-       { 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 }
+static const value_string auth_types[] = {
+       {0,"MD5"},
+       {1,"SHA1"},
+       {0,NULL}
 };
+static snmp_usm_auth_model_t* auth_models[] = {&model_md5,&model_sha1};
 
-/* 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 }
+static const value_string priv_types[] = {
+       {0,"DES"},
+       {1,"AES"},
+       {0,NULL}
 };
+static snmp_usm_decoder_t priv_protos[] = {snmp_usm_priv_des, snmp_usm_priv_aes};
 
-/* 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 }
-};
+static snmp_ue_assoc_t* ueas = NULL;
+static guint num_ueas = 0;
+static snmp_ue_assoc_t* localized_ues = NULL;
+static snmp_ue_assoc_t* unlocalized_ues = NULL;
+/****/
 
-/* SMUX Request codes */
-#define SMUX_RREQ_DELETE               0
-#define SMUX_RREQ_READONLY             1
-#define SMUX_RREQ_READWRITE            2
+/* Variabled used for handling enterprise spesific trap types */
+typedef struct _snmp_st_assoc_t {
+       char *enterprise;
+       guint trap;
+       char *desc;
+} snmp_st_assoc_t;
+static guint num_specific_traps = 0;
+static snmp_st_assoc_t *specific_traps = NULL;
+static const char *enterprise_oid = NULL;
+static guint generic_trap = 0;
 
-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 }
-};
+static snmp_usm_params_t usm_p = {FALSE,FALSE,0,0,0,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,FALSE};
 
-/* SMUX SOut codes */
-#define SMUX_SOUT_COMMIT               0
-#define SMUX_SOUT_ROLLBACK             1
+#define TH_AUTH   0x01
+#define TH_CRYPT  0x02
+#define TH_REPORT 0x04
 
-static const value_string smux_sout[] = {
-       { SMUX_SOUT_COMMIT,             "Commit" },
-       { SMUX_SOUT_ROLLBACK,           "Rollback" },
-       { 0,                            NULL }
-};
+/* desegmentation of SNMP-over-TCP */
+static gboolean snmp_desegment = TRUE;
 
-/* Error status values */
-#ifndef SNMP_ERR_NOERROR
-#define SNMP_ERR_NOERROR               0
-#endif
-#ifndef SNMP_ERR_TOOBIG
-#define SNMP_ERR_TOOBIG                        1
-#endif
-#ifndef SNMP_ERR_NOSUCHNAME
-#define SNMP_ERR_NOSUCHNAME            2
-#endif
-#ifndef SNMP_ERR_BADVALUE
-#define SNMP_ERR_BADVALUE              3
-#endif
-#ifndef SNMP_ERR_READONLY
-#define SNMP_ERR_READONLY              4
-#endif
-#ifndef SNMP_ERR_GENERR
-#define SNMP_ERR_GENERR                        5
-#endif
-#ifndef SNMP_ERR_NOACCESS
-#define SNMP_ERR_NOACCESS              6
-#endif
-#ifndef SNMP_ERR_WRONGTYPE
-#define SNMP_ERR_WRONGTYPE             7
-#endif
-#ifndef SNMP_ERR_WRONGLENGTH
-#define SNMP_ERR_WRONGLENGTH           8
-#endif
-#ifndef SNMP_ERR_WRONGENCODING
-#define SNMP_ERR_WRONGENCODING         9
-#endif
-#ifndef SNMP_ERR_WRONGVALUE
-#define SNMP_ERR_WRONGVALUE            10
-#endif
-#ifndef SNMP_ERR_NOCREATION
-#define SNMP_ERR_NOCREATION            11
-#endif
-#ifndef SNMP_ERR_INCONSISTENTVALUE
-#define SNMP_ERR_INCONSISTENTVALUE     12
-#endif
-#ifndef SNMP_ERR_RESOURCEUNAVAILABLE
-#define SNMP_ERR_RESOURCEUNAVAILABLE   13
-#endif
-#ifndef SNMP_ERR_COMMITFAILED
-#define SNMP_ERR_COMMITFAILED          14
-#endif
-#ifndef SNMP_ERR_UNDOFAILED
-#define SNMP_ERR_UNDOFAILED            15
-#endif
-#ifndef SNMP_ERR_AUTHORIZATIONERROR
-#define SNMP_ERR_AUTHORIZATIONERROR    16
-#endif
-#ifndef SNMP_ERR_NOTWRITABLE
-#define SNMP_ERR_NOTWRITABLE           17
-#endif
-#ifndef SNMP_ERR_INCONSISTENTNAME
-#define SNMP_ERR_INCONSISTENTNAME      18
-#endif
+/* Global variables */
 
-static const value_string error_statuses[] = {
-       { SNMP_ERR_NOERROR,             "NO ERROR" },
-       { SNMP_ERR_TOOBIG,              "TOOBIG" },
-       { SNMP_ERR_NOSUCHNAME,          "NO SUCH NAME" },
-       { SNMP_ERR_BADVALUE,            "BAD VALUE" },
-       { SNMP_ERR_READONLY,            "READ ONLY" },
-       { SNMP_ERR_GENERR,              "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 }
-};
+guint32 MsgSecurityModel;
+tvbuff_t *oid_tvb=NULL;
+tvbuff_t *value_tvb=NULL;
 
-/* General SNMP V1 Traps */
+static dissector_handle_t snmp_handle;
+static dissector_handle_t data_handle;
 
-#ifndef SNMP_TRAP_COLDSTART
-#define SNMP_TRAP_COLDSTART            0
-#endif
-#ifndef SNMP_TRAP_WARMSTART
-#define SNMP_TRAP_WARMSTART            1
-#endif
-#ifndef SNMP_TRAP_LINKDOWN
-#define SNMP_TRAP_LINKDOWN             2
-#endif
-#ifndef SNMP_TRAP_LINKUP
-#define SNMP_TRAP_LINKUP               3
-#endif
-#ifndef SNMP_TRAP_AUTHFAIL
-#define SNMP_TRAP_AUTHFAIL             4
-#endif
-#ifndef SNMP_TRAP_EGPNEIGHBORLOSS
-#define SNMP_TRAP_EGPNEIGHBORLOSS      5
-#endif
-#ifndef SNMP_TRAP_ENTERPRISESPECIFIC
-#define SNMP_TRAP_ENTERPRISESPECIFIC   6
-#endif
+static next_tvb_list_t var_list;
+
+static int hf_snmp_v3_flags_auth = -1;
+static int hf_snmp_v3_flags_crypt = -1;
+static int hf_snmp_v3_flags_report = -1;
+
+static int hf_snmp_engineid_conform = -1;
+static int hf_snmp_engineid_enterprise = -1;
+static int hf_snmp_engineid_format = -1;
+static int hf_snmp_engineid_ipv4 = -1;
+static int hf_snmp_engineid_ipv6 = -1;
+static int hf_snmp_engineid_cisco_type = -1;
+static int hf_snmp_engineid_mac = -1;
+static int hf_snmp_engineid_text = -1;
+static int hf_snmp_engineid_time = -1;
+static int hf_snmp_engineid_data = -1;
+static int hf_snmp_decryptedPDU = -1;
+static int hf_snmp_msgAuthentication = -1;
+
+static int hf_snmp_noSuchObject = -1;
+static int hf_snmp_noSuchInstance = -1;
+static int hf_snmp_endOfMibView = -1;
+static int hf_snmp_unSpecified = -1;
+
+static int hf_snmp_integer32_value = -1;
+static int hf_snmp_octetstring_value = -1;
+static int hf_snmp_oid_value = -1;
+static int hf_snmp_null_value = -1;
+static int hf_snmp_ipv4_value = -1;
+static int hf_snmp_ipv6_value = -1;
+static int hf_snmp_anyaddress_value = -1;
+static int hf_snmp_unsigned32_value = -1;
+static int hf_snmp_unknown_value = -1;
+static int hf_snmp_opaque_value = -1;
+static int hf_snmp_nsap_value = -1;
+static int hf_snmp_counter_value = -1;
+static int hf_snmp_timeticks_value = -1;
+static int hf_snmp_big_counter_value = -1;
+static int hf_snmp_gauge32_value = -1;
+
+static int hf_snmp_objectname = -1;
+static int hf_snmp_scalar_instance_index = -1;
+
+
+
+/*--- Included file: packet-snmp-hf.c ---*/
+#line 1 "../../asn1/snmp/packet-snmp-hf.c"
+static int hf_snmp_SMUX_PDUs_PDU = -1;            /* SMUX_PDUs */
+static int hf_snmp_version = -1;                  /* Version */
+static int hf_snmp_community = -1;                /* Community */
+static int hf_snmp_data = -1;                     /* PDUs */
+static int hf_snmp_parameters = -1;               /* OCTET_STRING */
+static int hf_snmp_datav2u = -1;                  /* T_datav2u */
+static int hf_snmp_v2u_plaintext = -1;            /* PDUs */
+static int hf_snmp_encrypted = -1;                /* OCTET_STRING */
+static int hf_snmp_msgAuthoritativeEngineID = -1;  /* T_msgAuthoritativeEngineID */
+static int hf_snmp_msgAuthoritativeEngineBoots = -1;  /* T_msgAuthoritativeEngineBoots */
+static int hf_snmp_msgAuthoritativeEngineTime = -1;  /* T_msgAuthoritativeEngineTime */
+static int hf_snmp_msgUserName = -1;              /* T_msgUserName */
+static int hf_snmp_msgAuthenticationParameters = -1;  /* T_msgAuthenticationParameters */
+static int hf_snmp_msgPrivacyParameters = -1;     /* T_msgPrivacyParameters */
+static int hf_snmp_msgVersion = -1;               /* Version */
+static int hf_snmp_msgGlobalData = -1;            /* HeaderData */
+static int hf_snmp_msgSecurityParameters = -1;    /* T_msgSecurityParameters */
+static int hf_snmp_msgData = -1;                  /* ScopedPduData */
+static int hf_snmp_msgID = -1;                    /* INTEGER_0_2147483647 */
+static int hf_snmp_msgMaxSize = -1;               /* INTEGER_484_2147483647 */
+static int hf_snmp_msgFlags = -1;                 /* T_msgFlags */
+static int hf_snmp_msgSecurityModel = -1;         /* T_msgSecurityModel */
+static int hf_snmp_plaintext = -1;                /* ScopedPDU */
+static int hf_snmp_encryptedPDU = -1;             /* T_encryptedPDU */
+static int hf_snmp_contextEngineID = -1;          /* SnmpEngineID */
+static int hf_snmp_contextName = -1;              /* OCTET_STRING */
+static int hf_snmp_get_request = -1;              /* GetRequest_PDU */
+static int hf_snmp_get_next_request = -1;         /* GetNextRequest_PDU */
+static int hf_snmp_get_response = -1;             /* GetResponse_PDU */
+static int hf_snmp_set_request = -1;              /* SetRequest_PDU */
+static int hf_snmp_trap = -1;                     /* Trap_PDU */
+static int hf_snmp_getBulkRequest = -1;           /* GetBulkRequest_PDU */
+static int hf_snmp_informRequest = -1;            /* InformRequest_PDU */
+static int hf_snmp_snmpV2_trap = -1;              /* SNMPv2_Trap_PDU */
+static int hf_snmp_report = -1;                   /* Report_PDU */
+static int hf_snmp_request_id = -1;               /* INTEGER */
+static int hf_snmp_error_status = -1;             /* T_error_status */
+static int hf_snmp_error_index = -1;              /* INTEGER */
+static int hf_snmp_variable_bindings = -1;        /* VarBindList */
+static int hf_snmp_bulkPDU_request_id = -1;       /* Integer32 */
+static int hf_snmp_non_repeaters = -1;            /* INTEGER_0_2147483647 */
+static int hf_snmp_max_repetitions = -1;          /* INTEGER_0_2147483647 */
+static int hf_snmp_enterprise = -1;               /* EnterpriseOID */
+static int hf_snmp_agent_addr = -1;               /* NetworkAddress */
+static int hf_snmp_generic_trap = -1;             /* GenericTrap */
+static int hf_snmp_specific_trap = -1;            /* SpecificTrap */
+static int hf_snmp_time_stamp = -1;               /* TimeTicks */
+static int hf_snmp_name = -1;                     /* ObjectName */
+static int hf_snmp_valueType = -1;                /* NULL */
+static int hf_snmp_VarBindList_item = -1;         /* VarBind */
+static int hf_snmp_open = -1;                     /* OpenPDU */
+static int hf_snmp_close = -1;                    /* ClosePDU */
+static int hf_snmp_registerRequest = -1;          /* RReqPDU */
+static int hf_snmp_registerResponse = -1;         /* RegisterResponse */
+static int hf_snmp_commitOrRollback = -1;         /* SOutPDU */
+static int hf_snmp_rRspPDU = -1;                  /* RRspPDU */
+static int hf_snmp_pDUs = -1;                     /* PDUs */
+static int hf_snmp_smux_simple = -1;              /* SimpleOpen */
+static int hf_snmp_smux_version = -1;             /* T_smux_version */
+static int hf_snmp_identity = -1;                 /* OBJECT_IDENTIFIER */
+static int hf_snmp_description = -1;              /* DisplayString */
+static int hf_snmp_password = -1;                 /* OCTET_STRING */
+static int hf_snmp_subtree = -1;                  /* ObjectName */
+static int hf_snmp_priority = -1;                 /* INTEGER_M1_2147483647 */
+static int hf_snmp_operation = -1;                /* T_operation */
+
+/*--- End of included file: packet-snmp-hf.c ---*/
+#line 221 "../../asn1/snmp/packet-snmp-template.c"
 
-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 }
+static int hf_smux_version = -1;
+static int hf_smux_pdutype = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_smux = -1;
+static gint ett_snmp = -1;
+static gint ett_engineid = -1;
+static gint ett_msgFlags = -1;
+static gint ett_encryptedPDU = -1;
+static gint ett_decrypted = -1;
+static gint ett_authParameters = -1;
+static gint ett_internet = -1;
+static gint ett_varbind = -1;
+static gint ett_name = -1;
+static gint ett_value = -1;
+static gint ett_decoding_error = -1;
+
+
+/*--- Included file: packet-snmp-ett.c ---*/
+#line 1 "../../asn1/snmp/packet-snmp-ett.c"
+static gint ett_snmp_Message = -1;
+static gint ett_snmp_Messagev2u = -1;
+static gint ett_snmp_T_datav2u = -1;
+static gint ett_snmp_UsmSecurityParameters = -1;
+static gint ett_snmp_SNMPv3Message = -1;
+static gint ett_snmp_HeaderData = -1;
+static gint ett_snmp_ScopedPduData = -1;
+static gint ett_snmp_ScopedPDU = -1;
+static gint ett_snmp_PDUs = -1;
+static gint ett_snmp_PDU = -1;
+static gint ett_snmp_BulkPDU = -1;
+static gint ett_snmp_Trap_PDU_U = -1;
+static gint ett_snmp_VarBind = -1;
+static gint ett_snmp_VarBindList = -1;
+static gint ett_snmp_SMUX_PDUs = -1;
+static gint ett_snmp_RegisterResponse = -1;
+static gint ett_snmp_OpenPDU = -1;
+static gint ett_snmp_SimpleOpen_U = -1;
+static gint ett_snmp_RReqPDU_U = -1;
+
+/*--- End of included file: packet-snmp-ett.c ---*/
+#line 240 "../../asn1/snmp/packet-snmp-template.c"
+
+static const true_false_string auth_flags = {
+       "OK",
+       "Failed"
 };
 
 /* Security Models */
 
 #define SNMP_SEC_ANY                   0
-#define SNMP_SEC_V1                    1
+#define SNMP_SEC_V1                            1
 #define SNMP_SEC_V2C                   2
 #define SNMP_SEC_USM                   3
 
@@ -419,7 +360,22 @@ static const value_string sec_models[] = {
        { 0,                            NULL }
 };
 
-/* SNMP Tags */
+/* 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 }
+};
+
 
 #define SNMP_IPA    0          /* IP Address */
 #define SNMP_CNT    1          /* Counter (Counter32) */
@@ -434,1132 +390,2370 @@ static const value_string sec_models[] = {
 #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
+dissector_table_t value_sub_dissectors_table;
 
-typedef struct _SNMP_CNV SNMP_CNV;
 
-struct _SNMP_CNV
+static const gchar *
+snmp_lookup_specific_trap (guint specific_trap)
 {
-  guint class;
-  guint tag;
-  gint  syntax;
-  gchar *name;
-};
+       guint i;
 
-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}
-};
+       for (i = 0; i < num_specific_traps; i++) {
+               snmp_st_assoc_t *u = &(specific_traps[i]);
 
-/*
- * 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
- */
+               if ((u->trap == specific_trap) &&
+                   (strcmp (u->enterprise, enterprise_oid) == 0))
+               {
+                       return u->desc;
+               }
+       }
 
-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;
+       return NULL;
 }
 
-static void
-dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                  proto_tree *tree, const char *field_name, int ret)
-{
-       char *errstr;
-
-       errstr = asn1_err_to_str(ret);
+/*
+ *  dissect_snmp_VarBind
+ *  this routine dissects variable bindings, looking for the oid information in our oid reporsitory
+ *  to format and add the value adequatelly.
+ *
+ * The choice to handwrite this code instead of using the asn compiler is to avoid having tons
+ * of uses of global variables distributed in very different parts of the code.
+ * Other than that there's a cosmetic thing: the tree from ASN generated code would be so
+ * convoluted due to the nesting of CHOICEs in the definition of VarBind/value.
+ *
+ * XXX: the length of this function (~400 lines) is an aberration!
+ *  oid_key_t:key_type could become a series of callbacks instead of an enum
+ *  the (! oid_info_is_ok) switch could be made into an array (would be slower)
+ *
 
-       if (check_col(pinfo->cinfo, COL_INFO)) {
-               col_add_fstr(pinfo->cinfo, COL_INFO,
-                   "ERROR: Couldn't parse %s: %s", field_name, errstr);
+       NetworkAddress ::=  CHOICE { internet IpAddress }
+       IpAddress ::= [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4))
+       TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
+       Integer32 ::= INTEGER (-2147483648..2147483647)
+       ObjectName ::= OBJECT IDENTIFIER
+       Counter32 ::= [APPLICATION 1] IMPLICIT INTEGER (0..4294967295)
+       Gauge32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
+       Unsigned32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
+       Integer-value ::=  INTEGER (-2147483648..2147483647)
+       Integer32 ::= INTEGER (-2147483648..2147483647)
+       ObjectID-value ::= OBJECT IDENTIFIER
+       Empty ::= NULL
+       TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
+       Opaque ::= [APPLICATION 4] IMPLICIT OCTET STRING
+       Counter64 ::= [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615)
+
+       ObjectSyntax ::= CHOICE {
+                simple SimpleSyntax,
+                application-wide ApplicationSyntax
        }
-       if (tree != NULL) {
-               proto_tree_add_text(tree, tvb, offset, 0,
-                   "ERROR: Couldn't parse %s: %s", field_name, errstr);
-               call_dissector(data_handle,
-                   tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
-       }
-}
-
-static void
-dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                  proto_tree *tree, const char *message)
-{
-       if (check_col(pinfo->cinfo, COL_INFO))
-               col_add_str(pinfo->cinfo, COL_INFO, message);
 
-       if (tree != NULL) {
-               proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
-               call_dissector(data_handle,
-                   tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+       SimpleSyntax ::= CHOICE {
+          integer-value Integer-value,
+          string-value String-value,
+          objectID-value ObjectID-value,
+          empty  Empty
        }
-}
-
-gchar *
-format_oid(subid_t *oid, guint oid_length)
-{
-       char *result;
-       int result_len;
-       int len;
-       unsigned int i;
-       char *buf;
-#ifdef HAVE_SOME_SNMP
-       guchar *oid_string;
-       size_t oid_string_len;
-       size_t oid_out_len;
-#endif
-
-       result_len = oid_length * 22;
 
-#ifdef HAVE_SOME_SNMP
-       /*
-        * Get the decoded form of the OID, and add its length to the
-        * length of the result string.
-        *
-        * XXX - check for "sprint_realloc_objid()" failure.
-        */
-       oid_string_len = 256;
-       oid_string = g_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
+       ApplicationSyntax ::= CHOICE {
+          ipAddress-value IpAddress,
+          counter-value Counter32,
+          timeticks-value TimeTicks,
+          arbitrary-value Opaque,
+          big-counter-value Counter64,
+          unsigned-integer-value Unsigned32
+       }
 
-       result = g_malloc(result_len + 1);
-       buf = result;
-       len = sprintf(buf, "%lu", (unsigned long)oid[0]);
-       buf += len;
-       for (i = 1; i < oid_length;i++) {
-               len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
-               buf += len;
+       ValueType ::=  CHOICE {
+          value ObjectSyntax,
+          unSpecified NULL,
+          noSuchObject[0] IMPLICIT NULL,
+          noSuchInstance[1] IMPLICIT NULL,
+          endOfMibView[2] IMPLICIT NULL
        }
 
-#ifdef HAVE_SOME_SNMP
-       /*
-        * Append the decoded form of the OID.
-        */
-       sprintf(buf, " (%s)", oid_string);
-       g_free(oid_string);
-#endif
+       VarBind ::= SEQUENCE {
+          name ObjectName,
+          valueType ValueType
+       }
 
-       return result;
-}
+ */
 
-/* returns the decoded (can be NULL) and non_decoded OID strings,
-   returned pointers shall be freed by the caller */
-void 
-new_format_oid(subid_t *oid, guint oid_length, 
-              gchar **non_decoded, gchar **decoded)
+extern int
+dissect_snmp_VarBind(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset,
+                    asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_)
 {
-       int len;
-       unsigned int i;
-       char *buf;
-
-#ifdef HAVE_SOME_SNMP
-       guchar *oid_string;
-       size_t oid_string_len;
-       size_t oid_out_len;
-
-       /*
-        * Get the decoded form of the OID, and add its length to the
-        * length of the result string.
-        */
-
-       oid_string_len = 256;
-       oid_string = g_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);
-       *decoded = oid_string;
-#else
-       *decoded = NULL;
-#endif
-
-       *non_decoded = g_malloc(oid_length * 22 + 1);
-       buf = *non_decoded;
-       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;
+       int seq_offset, name_offset, value_offset, value_start;
+       guint32 seq_len, name_len, value_len;
+       gint8 ber_class;
+       gboolean pc;
+       gint32 tag;
+       gboolean ind;
+       guint32* subids;
+       guint8* oid_bytes;
+       oid_info_t* oid_info = NULL;
+       guint oid_matched, oid_left;
+       proto_item *pi_name, *pi_varbind, *pi_value = NULL;
+       proto_tree *pt, *pt_varbind, *pt_name, *pt_value;
+       char label[ITEM_LABEL_LENGTH];
+       const char* repr = NULL;
+       const char* info_oid = NULL;
+       char* valstr;
+       int hfid = -1;
+       int min_len = 0, max_len = 0;
+       gboolean oid_info_is_ok;
+       const char* oid_string = NULL;
+       enum {BER_NO_ERROR, BER_WRONG_LENGTH, BER_WRONG_TAG} format_error = BER_NO_ERROR;
+
+       seq_offset = offset;
+
+       /* first have the VarBind's sequence header */
+       offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
+       offset = get_ber_length(tvb, offset, &seq_len, &ind);
+
+       seq_len += offset - seq_offset;
+
+       if (!pc && ber_class==BER_CLASS_UNI && tag==BER_UNI_TAG_SEQUENCE) {
+               proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"VarBind must be an universal class sequence");
+               pt = proto_item_add_subtree(pi,ett_decoding_error);
+               expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "VarBind is not an universal class sequence");
+               return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
        }
-}
-
-#ifdef HAVE_SOME_SNMP
-static guchar *
-check_var_length(guint vb_length, guint required_length)
-{
-       gchar *buf;
-       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. */
-               buf = g_malloc(sizeof badlen_fmt + 10 + 10);
-               sprintf(buf, badlen_fmt, vb_length, required_length);
-               return buf;
+       if (ind) {
+               proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"Indicator must be clear in VarBind");
+               pt = proto_item_add_subtree(pi,ett_decoding_error);
+               expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "VarBind has indicator set");
+               return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
        }
-       return NULL;    /* length is OK */
-}
 
-static gchar *
-format_var(struct variable_list *variable, subid_t *variable_oid,
-    guint variable_oid_length, gushort vb_type, guint val_len)
-{
-       guchar *buf;
-       size_t buf_len;
-       size_t out_len;
+       /* then we have the ObjectName's header */
 
-       switch (vb_type) {
+       offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
+       name_offset = offset = get_ber_length(tvb, offset, &name_len, &ind);
 
-       case SNMP_IPADDR:
-               /* Length has to be 4 bytes. */
-               buf = check_var_length(val_len, 4);
-               if (buf != NULL)
-                       return buf;     /* it's not 4 bytes */
-               break;
+       if (! ( !pc && ber_class==BER_CLASS_UNI && tag==BER_UNI_TAG_OID) ) {
+               proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"ObjectName must be an OID in primitive encoding");
+               pt = proto_item_add_subtree(pi,ett_decoding_error);
+               expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "ObjectName not an OID");
+               return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
+       }
 
-#ifdef REMOVED
-       /* not all counters are encoded as a full 64bit integer */
-       case SNMP_COUNTER64:
-               /* Length has to be 8 bytes. */
-               buf = check_var_length(val_len, 8);
-               if (buf != NULL)
-                       return buf;     /* it's not 8 bytes */
-               break;
-#endif
-       default:
-               break;
+       if (ind) {
+               proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"Indicator must be clear in ObjectName");
+               pt = proto_item_add_subtree(pi,ett_decoding_error);
+               expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "ObjectName has indicator set");
+               return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
        }
 
-       variable->next_variable = NULL;
-       variable->name = variable_oid;
-       variable->name_length = variable_oid_length;
-       switch (vb_type) {
+       offset += name_len;
+       value_start = offset;
 
-       case SNMP_INTEGER:
-               variable->type = VALTYPE_INTEGER;
-               break;
+       /* then we have the  value's header */
+       offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
+       value_offset = get_ber_length(tvb, offset, &value_len, &ind);
 
-       case SNMP_COUNTER:
-               variable->type = VALTYPE_COUNTER;
-               break;
+       if (! (!pc) ) {
+               proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"the value must be in primitive encoding");
+               pt = proto_item_add_subtree(pi,ett_decoding_error);
+               expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "value not in primitive encoding");
+               return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
+       }
 
-       case SNMP_GAUGE:
-               variable->type = VALTYPE_GAUGE;
-               break;
+       /* Now, we know where everithing is */
 
-       case SNMP_TIMETICKS:
-               variable->type = VALTYPE_TIMETICKS;
-               break;
 
-       case SNMP_OCTETSTR:
-               variable->type = VALTYPE_STRING;
-               break;
 
-       case SNMP_IPADDR:
-               variable->type = VALTYPE_IPADDR;
-               break;
+       /* we add the varbind tree root with a dummy label we'll fill later on */
+       pi_varbind = proto_tree_add_text(tree,tvb,seq_offset,seq_len,"VarBind");
+       pt_varbind = proto_item_add_subtree(pi_varbind,ett_varbind);
+       *label = '\0';
 
-       case SNMP_OPAQUE:
-               variable->type = VALTYPE_OPAQUE;
-               break;
+       pi_name = proto_tree_add_item(pt_varbind,hf_snmp_objectname,tvb,name_offset,name_len,ENC_NA);
+       pt_name = proto_item_add_subtree(pi_name,ett_name);
 
-       case SNMP_NSAP:
-               variable->type = VALTYPE_NSAP;
-               break;
+       /* fetch ObjectName and its relative oid_info */
+       oid_bytes = ep_tvb_memdup(tvb, name_offset, name_len);
+       oid_info = oid_get_from_encoded(oid_bytes, name_len, &subids, &oid_matched, &oid_left);
 
-       case SNMP_OBJECTID:
-               variable->type = VALTYPE_OBJECTID;
-               break;
+       add_oid_debug_subtree(oid_info,pt_name);
 
-       case SNMP_BITSTR:
-               variable->type = VALTYPE_BITSTR;
-               break;
+       if (!subids) {
+               proto_item* pi;
 
-       case SNMP_COUNTER64:
-               variable->type = VALTYPE_COUNTER64;
-               break;
+               repr = oid_encoded2string(oid_bytes, name_len);
+               pi = proto_tree_add_text(pt_name,tvb, 0, 0, "invalid oid: %s", repr);
+               pt = proto_item_add_subtree(pi, ett_decoding_error);
+               expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "invalid oid: %s", repr);
+               return dissect_unknown_ber(actx->pinfo, tvb, name_offset, pt);
        }
-       variable->val_len = val_len;
 
-       /*
-        * XXX - check for "sprint_realloc_objid()" failure.
-        */
-       buf_len = 256;
-       buf = g_malloc(buf_len);
-       *buf = '\0';
-       out_len = 0;
-       sprint_realloc_value(&buf, &buf_len, &out_len, 1,  variable_oid,
-           variable_oid_length, variable);
-       return buf;
-}
-#endif
+       if (oid_matched+oid_left) {
+               oid_string = oid_subid2string(subids,oid_matched+oid_left);
+       }
 
-static int
-snmp_variable_decode(proto_tree *snmp_tree,
-    subid_t *variable_oid
-#ifndef HAVE_SOME_SNMP
-       _U_
-#endif
-    ,
-    guint variable_oid_length
-#ifndef HAVE_SOME_SNMP
-       _U_
-#endif
-    ,
-    ASN1_SCK *asn1, int offset, guint *lengthp, tvbuff_t **out_tvb)
-{
-       int start, vb_value_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;
-
-       subid_t *vb_oid;
-       guint vb_oid_length;
-
-       gchar *vb_display_string;
-
-#ifdef HAVE_SOME_SNMP
-       struct variable_list variable;
-       long value;
-#else /* HAVE_SOME_SNMP */
-       unsigned int i;
-       gchar *buf;
-       int len;
-#endif /* HAVE_SOME_SNMP */
-
-       /* parse the type of the object */
-       start = asn1->offset;
-       ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
-       if (ret != ASN1_ERR_NOERROR)
-               return ret;
-       vb_value_start = asn1->offset;
-       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) {
-               /*
-                * Unsupported type.
-                * Dissect the value as an opaque string of octets.
-                */
-               vb_type_name = "unsupported type";
-               vb_type = SNMP_OPAQUE;
-       }
-
-       /* 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->offset - start;
-               if (snmp_tree) {
-#ifdef HAVE_SOME_SNMP
-                       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);
-                       g_free(vb_display_string);
-#else /* HAVE_SOME_SNMP */
-                       proto_tree_add_text(snmp_tree, asn1->tvb, offset,
-                           length,
-                           "Value: %s: %d (%#x)", vb_type_name,
-                           vb_integer_value, vb_integer_value);
-#endif /* HAVE_SOME_SNMP */
+       if (ber_class == BER_CLASS_CON) {
+               /* if we have an error value just add it and get out the way ASAP */
+               proto_item* pi;
+               const char* note;
+
+               if (value_len != 0) {
+                       min_len = max_len = 0;
+                       format_error = BER_WRONG_LENGTH;
+               }
+
+               switch (tag) {
+                       case SERR_NSO:
+                               hfid = hf_snmp_noSuchObject;
+                               note = "noSuchObject";
+                               break;
+                       case SERR_NSI:
+                               hfid = hf_snmp_noSuchInstance;
+                               note = "noSuchInstance";
+                               break;
+                       case SERR_EOM:
+                               hfid = hf_snmp_endOfMibView;
+                               note = "endOfMibView";
+                               break;
+                       default: {
+                               pi = proto_tree_add_text(pt_varbind,tvb,0,0,"Wrong tag for Error Value: expected 0, 1, or 2 but got: %d",tag);
+                               pt = proto_item_add_subtree(pi,ett_decoding_error);
+                               expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong tag for SNMP VarBind error value");
+                               return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
+                       }
                }
-               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->offset - start;
-               if (snmp_tree) {
-#ifdef HAVE_SOME_SNMP
-                       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);
-                       g_free(vb_display_string);
-#else /* HAVE_SOME_SNMP */
-                       proto_tree_add_text(snmp_tree, asn1->tvb, offset,
-                           length,
-                           "Value: %s: %u (%#x)", vb_type_name,
-                           vb_uinteger_value, vb_uinteger_value);
-#endif /* HAVE_SOME_SNMP */
-               }
-               break;
+               pi = proto_tree_add_item(pt_varbind,hfid,tvb,value_offset,value_len,ENC_BIG_ENDIAN);
+               expert_add_info_format(actx->pinfo, pi, PI_RESPONSE_CODE, PI_NOTE, "%s",note);
+               g_strlcpy (label, note, ITEM_LABEL_LENGTH);
+               goto set_label;
+       }
 
-       case SNMP_OCTETSTR:
-       case SNMP_IPADDR:
-       case SNMP_OPAQUE:
-       case SNMP_NSAP:
-       case SNMP_BITSTR:
-       case SNMP_COUNTER64:
-               ret = asn1_string_value_decode (asn1, vb_length,
-                   &vb_octet_string);
-               if (ret != ASN1_ERR_NOERROR)
-                       return ret;
-               length = asn1->offset - start;
-               if (out_tvb) {
-                       *out_tvb = tvb_new_subset(asn1->tvb, vb_value_start, asn1->offset - vb_value_start, vb_length);
-               }
-               if (snmp_tree) {
-#ifdef HAVE_SOME_SNMP
-                       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);
-                       g_free(vb_display_string);
-#else /* HAVE_SOME_SNMP */
-                       /*
-                        * 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.
-                                */
-                               vb_display_string = g_malloc(4*vb_length);
-                               buf = &vb_display_string[0];
-                               len = sprintf(buf, "%03u", vb_octet_string[0]);
-                               buf += len;
-                               for (i = 1; i < vb_length; i++) {
-                                       len = sprintf(buf, ".%03u",
-                                           vb_octet_string[i]);
-                                       buf += len;
+       /* now we'll try to figure out which are the indexing sub-oids and whether the oid we know about is the one oid we have to use */
+       switch (oid_info->kind) {
+               case OID_KIND_SCALAR:
+                       if (oid_left  == 1) {
+                               /* OK: we got the instance sub-id */
+                               proto_tree_add_uint64(pt_name,hf_snmp_scalar_instance_index,tvb,name_offset,name_len,subids[oid_matched]);
+                               oid_info_is_ok = TRUE;
+                               goto indexing_done;
+                       } else if (oid_left  == 0) {
+                               if (ber_class == BER_CLASS_UNI && tag == BER_UNI_TAG_NULL) {
+                                       /* unSpecified  does not require an instance sub-id add the new value and get off the way! */
+                                       pi_value = proto_tree_add_item(pt_varbind,hf_snmp_unSpecified,tvb,value_offset,value_len,ENC_NA);
+                                       goto set_label;
+                               } else {
+                                       proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"A scalar should have one instance sub-id this one has none");
+                                       expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "No instance sub-id in scalar value");
+                                       oid_info_is_ok = FALSE;
+                                       goto indexing_done;
                                }
-                               proto_tree_add_text(snmp_tree, asn1->tvb, offset,
-                                   length,
-                                   "Value: %s: %s", vb_type_name,
-                                   vb_display_string);
-                               g_free(vb_display_string);
                        } else {
-                               proto_tree_add_text(snmp_tree, asn1->tvb, offset,
-                                   length,
-                                   "Value: %s: %s", vb_type_name,
-                                   SAFE_STRING(vb_octet_string, vb_length));
+                               proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"A scalar should have only one instance sub-id this has: %d",oid_left);
+                               expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong number of instance sub-ids in scalar value");
+                               oid_info_is_ok = FALSE;
+                               goto indexing_done;
                        }
-#endif /* HAVE_SOME_SNMP */
-               }
-               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->offset - start;
-               if (snmp_tree) {
-                       proto_tree_add_text(snmp_tree, asn1->tvb, 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->offset - start;
-               if (snmp_tree) {
-#ifdef HAVE_SOME_SNMP
-                       variable.val.objid = vb_oid;
-                       vb_display_string = format_var(&variable,
-                           variable_oid, variable_oid_length, vb_type,
-                           vb_oid_length * sizeof (subid_t));
-                       proto_tree_add_text(snmp_tree, asn1->tvb, offset,
-                           length,
-                           "Value: %s", vb_display_string);
-                       g_free(vb_display_string);
-#else /* HAVE_SOME_SNMP */
-                       vb_display_string = format_oid(vb_oid, vb_oid_length);
-                       proto_tree_add_text(snmp_tree, asn1->tvb, offset,
-                           length,
-                           "Value: %s: %s", vb_type_name, vb_display_string);
-                       g_free(vb_display_string);
-#endif /* HAVE_SOME_SNMP */
-               }
-               g_free(vb_oid);
                break;
+               case OID_KIND_COLUMN:
+                       if ( oid_info->parent->kind == OID_KIND_ROW) {
+                               oid_key_t* k = oid_info->parent->key;
+                               guint key_start = oid_matched;
+                               guint key_len = oid_left;
+                               oid_info_is_ok = TRUE;
+
+                               if ( key_len == 0 && ber_class == BER_CLASS_UNI && tag == BER_UNI_TAG_NULL) {
+                                       /* unSpecified  does not require an instance sub-id add the new value and get off the way! */
+                                       pi_value = proto_tree_add_item(pt_varbind,hf_snmp_unSpecified,tvb,value_offset,value_len,ENC_NA);
+                                       goto set_label;
+                               }
 
-       case SNMP_NOSUCHOBJECT:
-               length = asn1->offset - start;
-               if (snmp_tree) {
-                       proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
-                           "Value: %s: no such object", vb_type_name);
+                               if (k) {
+                                       for (;k;k = k->next) {
+                                               guint suboid_len;
+
+                                               if (key_start >= oid_matched+oid_left) {
+                                                       proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"index sub-oid shorter than expected");
+                                                       expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "index sub-oid shorter than expected");
+                                                       oid_info_is_ok = FALSE;
+                                                       goto indexing_done;
+                                               }
+
+                                               switch(k->key_type) {
+                                                       case OID_KEY_TYPE_WRONG: {
+                                                               proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"OID instaces not handled, if you want this implemented please contact the wireshark developers");
+                                                               expert_add_info_format(actx->pinfo, pi, PI_UNDECODED, PI_WARN, "Unimplemented instance index");
+                                                               oid_info_is_ok = FALSE;
+                                                               goto indexing_done;
+                                                       }
+                                                       case OID_KEY_TYPE_INTEGER: {
+                                                               if (IS_FT_INT(k->ft_type)) {
+                                                                       proto_tree_add_int(pt_name,k->hfid,tvb,name_offset,name_len,(guint)subids[key_start]);
+                                                               } else { /* if it's not an unsigned int let proto_tree_add_uint throw a warning */
+                                                                       proto_tree_add_uint64(pt_name,k->hfid,tvb,name_offset,name_len,(guint)subids[key_start]);
+                                                               }
+                                                               key_start++;
+                                                               key_len--;
+                                                               continue; /* k->next */
+                                                       }
+                                                       case OID_KEY_TYPE_IMPLIED_OID:
+                                                               suboid_len = key_len;
+
+                                                               goto show_oid_index;
+
+                                                       case OID_KEY_TYPE_OID: {
+                                                               guint8* suboid_buf;
+                                                               guint suboid_buf_len;
+                                                               guint32* suboid;
+
+                                                               suboid_len = subids[key_start++];
+                                                               key_len--;
+
+show_oid_index:
+                                                               suboid = &(subids[key_start]);
+
+                                                               if( suboid_len == 0 ) {
+                                                                       proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"an index sub-oid OID cannot be 0 bytes long!");
+                                                                       expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "index sub-oid OID with len=0");
+                                                                       oid_info_is_ok = FALSE;
+                                                                       goto indexing_done;
+                                                               }
+
+                                                               if( key_len < suboid_len ) {
+                                                                       proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"index sub-oid should not be longer than remaining oid size");
+                                                                       expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "index sub-oid longer than remaining oid size");
+                                                                       oid_info_is_ok = FALSE;
+                                                                       goto indexing_done;
+                                                               }
+
+                                                               suboid_buf_len = oid_subid2encoded(suboid_len, suboid, &suboid_buf);
+
+                                                               DISSECTOR_ASSERT(suboid_buf_len);
+
+                                                               proto_tree_add_oid(pt_name,k->hfid,tvb,name_offset, suboid_buf_len, suboid_buf);
+
+                                                               key_start += suboid_len;
+                                                               key_len -= suboid_len + 1;
+                                                               continue; /* k->next */
+                                                       }
+                                                       default: {
+                                                               guint8* buf;
+                                                               guint buf_len;
+                                                               guint32* suboid;
+                                                               guint i;
+
+
+                                                               switch (k->key_type) {
+                                                                       case OID_KEY_TYPE_IPADDR:
+                                                                               suboid = &(subids[key_start]);
+                                                                               buf_len = 4;
+                                                                               break;
+                                                                       case OID_KEY_TYPE_IMPLIED_STRING:
+                                                                       case OID_KEY_TYPE_IMPLIED_BYTES:
+                                                                       case OID_KEY_TYPE_ETHER:
+                                                                               suboid = &(subids[key_start]);
+                                                                               buf_len = key_len;
+                                                                               break;
+                                                                       default:
+                                                                               buf_len = k->num_subids;
+                                                                               suboid = &(subids[key_start]);
+
+                                                                               if(!buf_len) {
+                                                                                       buf_len = *suboid++;
+                                                                                       key_len--;
+                                                                                       key_start++;
+                                                                               }
+                                                                               break;
+                                                               }
+
+                                                               if( key_len < buf_len ) {
+                                                                       proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"index string should not be longer than remaining oid size");
+                                                                       expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "index string longer than remaining oid size");
+                                                                       oid_info_is_ok = FALSE;
+                                                                       goto indexing_done;
+                                                               }
+
+                                                               buf = ep_alloc(buf_len+1);
+                                                               for (i = 0; i < buf_len; i++)
+                                                                       buf[i] = (guint8)suboid[i];
+                                                               buf[i] = '\0';
+
+                                                               switch(k->key_type) {
+                                                                       case OID_KEY_TYPE_STRING:
+                                                                       case OID_KEY_TYPE_IMPLIED_STRING:
+                                                                               proto_tree_add_string(pt_name,k->hfid,tvb,name_offset,buf_len, buf);
+                                                                               break;
+                                                                       case OID_KEY_TYPE_BYTES:
+                                                                       case OID_KEY_TYPE_NSAP:
+                                                                       case OID_KEY_TYPE_IMPLIED_BYTES:
+                                                                               proto_tree_add_bytes(pt_name,k->hfid,tvb,name_offset,buf_len, buf);
+                                                                               break;
+                                                                       case OID_KEY_TYPE_ETHER:
+                                                                               proto_tree_add_ether(pt_name,k->hfid,tvb,name_offset,buf_len, buf);
+                                                                               break;
+                                                                       case OID_KEY_TYPE_IPADDR: {
+                                                                               guint32* ipv4_p = (void*)buf;
+                                                                               proto_tree_add_ipv4(pt_name,k->hfid,tvb,name_offset,buf_len, *ipv4_p);
+                                                                               }
+                                                                               break;
+                                                                       default:
+                                                                               DISSECTOR_ASSERT_NOT_REACHED();
+                                                                               break;
+                                                               }
+
+                                                               key_start += buf_len;
+                                                               key_len -= buf_len;
+                                                               continue; /* k->next*/
+                                                       }
+                                               }
+                                       }
+                                       goto indexing_done;
+                               } else {
+                                       proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"We do not know how to handle this OID, if you want this implemented please contact the wireshark developers");
+                                       expert_add_info_format(actx->pinfo, pi, PI_UNDECODED, PI_WARN, "Unimplemented instance index");
+                                       oid_info_is_ok = FALSE;
+                                       goto indexing_done;
+                               }
+                       } else {
+                               proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"The COLUMS's parent is not a ROW. This is a BUG! please contact the wireshark developers.");
+                               expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_ERROR, "COLUMS's parent is not a ROW");
+                               oid_info_is_ok = FALSE;
+                               goto indexing_done;
+                       }
+               default: {
+/*                     proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"This kind OID should have no value");
+                       expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "This kind OID should have no value"); */
+                       oid_info_is_ok = FALSE;
+                       goto indexing_done;
                }
-               break;
+       }
+indexing_done:
+
+       if (oid_info_is_ok && oid_info->value_type) {
+               if (ber_class == BER_CLASS_UNI && tag == BER_UNI_TAG_NULL) {
+                       pi_value = proto_tree_add_item(pt_varbind,hf_snmp_unSpecified,tvb,value_offset,value_len,ENC_NA);
+               } else {
+                       /* Provide a tree_item to attach errors to, if needed. */
+                       pi_value = pi_name;
+
+                       if ((oid_info->value_type->ber_class != BER_CLASS_ANY) &&
+                               (ber_class != oid_info->value_type->ber_class))
+                               format_error = BER_WRONG_TAG;
+                       else if ((oid_info->value_type->ber_tag != BER_TAG_ANY) &&
+                               (tag != oid_info->value_type->ber_tag))
+                               format_error = BER_WRONG_TAG;
+                       else {
+                               max_len = oid_info->value_type->max_len == -1 ? 0xffffff : oid_info->value_type->max_len;
+                               min_len  = oid_info->value_type->min_len;
+
+                               if ((int)value_len < min_len || (int)value_len > max_len)
+                                       format_error = BER_WRONG_LENGTH;
+                       }
 
-       case SNMP_NOSUCHINSTANCE:
-               length = asn1->offset - start;
-               if (snmp_tree) {
-                       proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
-                           "Value: %s: no such instance", vb_type_name);
+                       if (format_error == BER_NO_ERROR)
+                               pi_value = proto_tree_add_item(pt_varbind,oid_info->value_hfid,tvb,value_offset,value_len,ENC_BIG_ENDIAN);
                }
-               break;
+       } else {
+               switch(ber_class|(tag<<4)) {
+                       case BER_CLASS_UNI|(BER_UNI_TAG_INTEGER<<4):
+                       {
+                               gint64 val=0;
+                               unsigned int_val_offset = value_offset;
+                               unsigned i;
+
+                               max_len = 5; min_len = 1;
+                               if (value_len > (guint)max_len && value_len < (guint)min_len) {
+                                       format_error = BER_WRONG_LENGTH;
+                                       break;
+                               }
 
-       case SNMP_ENDOFMIBVIEW:
-               length = asn1->offset - start;
-               if (snmp_tree) {
-                       proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
-                           "Value: %s: end of mib view", vb_type_name);
-               }
-               break;
+                               if(value_len > 0) {
+                                       /* extend sign bit */
+                                       if(tvb_get_guint8(tvb, int_val_offset)&0x80) {
+                                               val=-1;
+                                       }
+                                       for(i=0;i<value_len;i++) {
+                                               val=(val<<8)|tvb_get_guint8(tvb, int_val_offset);
+                                               int_val_offset++;
+                                       }
+                               }
+                               proto_tree_add_int64(pt_varbind, hf_snmp_integer32_value, tvb,value_offset,value_len, val);
 
-       default:
-               g_assert_not_reached();
-               return ASN1_ERR_WRONG_TYPE;
+                               goto already_added;
+                       }
+                       case BER_CLASS_UNI|(BER_UNI_TAG_OCTETSTRING<<4):
+                               hfid = hf_snmp_octetstring_value;
+                               break;
+                       case BER_CLASS_UNI|(BER_UNI_TAG_OID<<4):
+                               max_len = -1; min_len = 1;
+                               if (value_len < (guint)min_len) format_error = BER_WRONG_LENGTH;
+                               hfid = hf_snmp_oid_value;
+                               break;
+                       case BER_CLASS_UNI|(BER_UNI_TAG_NULL<<4):
+                               max_len = 0; min_len = 0;
+                               if (value_len != 0) format_error = BER_WRONG_LENGTH;
+                               hfid = hf_snmp_null_value;
+                               break;
+                       case BER_CLASS_APP: /* | (SNMP_IPA<<4)*/
+                               switch(value_len) {
+                                       case 4: hfid = hf_snmp_ipv4_value; break;
+                                       case 16: hfid = hf_snmp_ipv6_value; break;
+                                       default: hfid = hf_snmp_anyaddress_value; break;
+                               }
+                               break;
+                       case BER_CLASS_APP|(SNMP_U32<<4):
+                               hfid = hf_snmp_unsigned32_value;
+                               break;
+                       case BER_CLASS_APP|(SNMP_GGE<<4):
+                               hfid = hf_snmp_gauge32_value;
+                               break;
+                       case BER_CLASS_APP|(SNMP_CNT<<4):
+                               hfid = hf_snmp_counter_value;
+                               break;
+                       case BER_CLASS_APP|(SNMP_TIT<<4):
+                               hfid = hf_snmp_timeticks_value;
+                               break;
+                       case BER_CLASS_APP|(SNMP_OPQ<<4):
+                               hfid = hf_snmp_opaque_value;
+                               break;
+                       case BER_CLASS_APP|(SNMP_NSP<<4):
+                               hfid = hf_snmp_nsap_value;
+                               break;
+                       case BER_CLASS_APP|(SNMP_C64<<4):
+                               hfid = hf_snmp_big_counter_value;
+                               break;
+                       default:
+                               hfid = hf_snmp_unknown_value;
+                               break;
+               }
+
+               pi_value = proto_tree_add_item(pt_varbind,hfid,tvb,value_offset,value_len,ENC_BIG_ENDIAN);
+               if (format_error != BER_NO_ERROR) {
+                       expert_add_info_format(actx->pinfo, pi_value, PI_UNDECODED, PI_NOTE, "Unresolved value, Missing MIB");
+               }
+
+already_added:
+               oid_info_is_ok = FALSE;
        }
-       *lengthp = length;
-       return ASN1_ERR_NOERROR;
-}
 
-static void
-dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, proto_tree *root_tree, ASN1_SCK asn1, guint pdu_type, int start)
-{
-       gboolean def;
-       guint length;
-       guint sequence_length;
+       pt_value = proto_item_add_subtree(pi_value,ett_value);
 
-       guint32 request_id;
+       if (value_len > 0 && oid_string) {
+               tvbuff_t* sub_tvb = tvb_new_subset(tvb, value_offset, value_len, value_len);
 
-       guint32 error_status;
+               next_tvb_add_string(&var_list, sub_tvb, (snmp_var_in_tree) ? pt_value : NULL, value_sub_dissectors_table, oid_string);
+       }
 
-       guint32 error_index;
 
-       char *pdu_type_string;
+set_label:
+       if (pi_value) proto_item_fill_label(PITEM_FINFO(pi_value), label);
+
+       if (oid_info && oid_info->name) {
+               if (oid_left >= 1) {
+                       repr  = ep_strdup_printf("%s.%s (%s)", oid_info->name,
+                                                oid_subid2string(&(subids[oid_matched]),oid_left),
+                                                oid_subid2string(subids,oid_matched+oid_left));
+                       info_oid = ep_strdup_printf("%s.%s", oid_info->name,
+                                                   oid_subid2string(&(subids[oid_matched]),oid_left));
+               } else {
+                       repr  = ep_strdup_printf("%s (%s)", oid_info->name,
+                                                oid_subid2string(subids,oid_matched));
+                       info_oid = oid_info->name;
+               }
+       } else if (oid_string) {
+               repr  = ep_strdup(oid_string);
+               info_oid = oid_string;
+       } else {
+               repr  = ep_strdup("[Bad OID]");
+       }
 
-       subid_t *enterprise;
-       guint enterprise_length;
+       valstr = strstr(label,": ");
+       valstr = valstr ? valstr+2 : label;
 
-       guint32 agent_ipaddr;
+       proto_item_set_text(pi_varbind,"%s: %s",repr,valstr);
 
-       guint8 *agent_address;
-       guint agent_address_length;
+       if (display_oid && info_oid) {
+         col_append_fstr (actx->pinfo->cinfo, COL_INFO, " %s", info_oid);
+       }
 
-       guint32 trap_type;
+       switch (format_error) {
+               case BER_WRONG_LENGTH: {
+                       proto_tree* pt = proto_item_add_subtree(pi_value,ett_decoding_error);
+                       proto_item* pi = proto_tree_add_text(pt,tvb,0,0,"Wrong value length: %u  expecting: %u <= len <= %u",
+                                                            value_len, min_len, max_len == -1 ? 0xFFFFFF : max_len);
+                       pt = proto_item_add_subtree(pi,ett_decoding_error);
+                       expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong length for SNMP VarBind/value");
+                       return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
+               }
+               case BER_WRONG_TAG: {
+                       proto_tree* pt = proto_item_add_subtree(pi_value,ett_decoding_error);
+                       proto_item* pi = proto_tree_add_text(pt,tvb,0,0,"Wrong class/tag for Value expected: %d,%d got: %d,%d",
+                                                            oid_info->value_type->ber_class, oid_info->value_type->ber_tag,
+                                                            ber_class, tag);
+                       pt = proto_item_add_subtree(pi,ett_decoding_error);
+                       expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong class/tag for SNMP VarBind/value");
+                       return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
+               }
+               default:
+                       break;
+       }
 
-       guint32 specific_type;
+       return seq_offset + seq_len;
+}
 
-       guint timestamp;
-       guint timestamp_length;
 
-       gchar *oid_string;
-       gchar *decoded_oid;
-       gchar *non_decoded_oid;
+#define F_SNMP_ENGINEID_CONFORM 0x80
+#define SNMP_ENGINEID_RFC1910 0x00
+#define SNMP_ENGINEID_RFC3411 0x01
 
+static const true_false_string tfs_snmp_engineid_conform = {
+  "RFC3411 (SNMPv3)",
+  "RFC1910 (Non-SNMPv3)"
+};
 
-       guint variable_bindings_length;
+#define SNMP_ENGINEID_FORMAT_IPV4 0x01
+#define SNMP_ENGINEID_FORMAT_IPV6 0x02
+#define SNMP_ENGINEID_FORMAT_MACADDRESS 0x03
+#define SNMP_ENGINEID_FORMAT_TEXT 0x04
+#define SNMP_ENGINEID_FORMAT_OCTETS 0x05
+
+static const value_string snmp_engineid_format_vals[] = {
+       { SNMP_ENGINEID_FORMAT_IPV4,    "IPv4 address" },
+       { SNMP_ENGINEID_FORMAT_IPV6,    "IPv6 address" },
+       { SNMP_ENGINEID_FORMAT_MACADDRESS,      "MAC address" },
+       { SNMP_ENGINEID_FORMAT_TEXT,    "Text, administratively assigned" },
+       { SNMP_ENGINEID_FORMAT_OCTETS,  "Octets, administratively assigned" },
+       { 0,    NULL }
+};
 
-       int vb_index;
-       guint variable_length;
-       subid_t *variable_oid;
-       guint variable_oid_length;
-       tvbuff_t *next_tvb;
+#define SNMP_ENGINEID_CISCO_AGENT 0x00
+#define SNMP_ENGINEID_CISCO_MANAGER 0x01
 
-       int ret;
-       guint cls, con, tag;
+static const value_string snmp_engineid_cisco_type_vals[] = {
+       { SNMP_ENGINEID_CISCO_AGENT,    "Agent" },
+       { SNMP_ENGINEID_CISCO_MANAGER,  "Manager" },
+       { 0,    NULL }
+};
 
-       pdu_type_string = val_to_str(pdu_type, pdu_types,
-           "Unknown PDU type %#x");
-       if (check_col(pinfo->cinfo, COL_INFO))
-               col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
-       length = asn1.offset - start;
-       if (tree) {
-               proto_tree_add_uint(tree, hf_snmp_pdutype, tvb, offset, length,
-                   pdu_type);
-       }
-       offset += length;
-
-       /* get the fields in the PDU preceeding the variable-bindings sequence */
-       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:
-       case SNMP_MSG_TRAP2:
-       case SNMP_MSG_REPORT:
-               /* request id */
-               ret = asn1_uint32_decode (&asn1, &request_id, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "request ID", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_uint(tree, hf_snmp_request_id,
-                               tvb, offset, length, request_id);
-               }
-               offset += length;
-
-               /* error status, or getbulk non-repeaters */
-               ret = asn1_uint32_decode (&asn1, &error_status, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
-                                                          : "error status",
-                           ret);
-                       return;
-               }
-               if (tree) {
-                       if (pdu_type == SNMP_MSG_GETBULK) {
-                               proto_tree_add_text(tree, tvb, offset,
-                                   length, "Non-repeaters: %u", error_status);
-                       } else {
-                               proto_tree_add_uint(tree, 
-                                                   hf_snmp_error_status,
-                                                   tvb, offset,
-                                                   length, error_status);
-                       }
-               }
-               offset += length;
-
-               /* error index, or getbulk max-repetitions */
-               ret = asn1_uint32_decode (&asn1, &error_index, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
-                                                          : "error index",
-                           ret);
-                       return;
-               }
-               if (tree) {
-                       if (pdu_type == SNMP_MSG_GETBULK) {
-                               proto_tree_add_text(tree, tvb, offset,
-                                   length, "Max repetitions: %u", error_index);
-                       } else {
-                               proto_tree_add_text(tree, tvb, offset,
-                                   length, "Error Index: %u", error_index);
-                       }
-               }
-               offset += length;
-               break;
+/*
+ * SNMP Engine ID dissection according to RFC 3411 (SnmpEngineID TC)
+ * or historic RFC 1910 (AgentID)
+ */
+int
+dissect_snmp_engineid(proto_tree *tree, tvbuff_t *tvb, int offset, int len)
+{
+    proto_item *item = NULL;
+    guint8 conformance, format;
+    guint32 enterpriseid, seconds;
+    nstime_t ts;
+    int len_remain = len;
+
+    /* first bit: engine id conformance */
+    if (len_remain<4) return offset;
+    conformance = ((tvb_get_guint8(tvb, offset)>>7) & 0x01);
+    proto_tree_add_item(tree, hf_snmp_engineid_conform, tvb, offset, 1, ENC_BIG_ENDIAN);
+
+    /* 4-byte enterprise number/name */
+    if (len_remain<4) return offset;
+    enterpriseid = tvb_get_ntohl(tvb, offset);
+    if (conformance)
+      enterpriseid -= 0x80000000; /* ignore first bit */
+    proto_tree_add_uint(tree, hf_snmp_engineid_enterprise, tvb, offset, 4, enterpriseid);
+    offset+=4;
+    len_remain-=4;
+
+    switch(conformance) {
+
+    case SNMP_ENGINEID_RFC1910:
+      /* 12-byte AgentID w/ 8-byte trailer */
+      if (len_remain==8) {
+       proto_tree_add_text(tree, tvb, offset, 8, "AgentID Trailer: 0x%s",
+                           tvb_bytes_to_str(tvb, offset, 8));
+       offset+=8;
+       len_remain-=8;
+      } else {
+       proto_tree_add_text(tree, tvb, offset, len_remain, "<Data not conforming to RFC1910>");
+       return offset;
+      }
+      break;
+
+    case SNMP_ENGINEID_RFC3411: /* variable length: 5..32 */
+
+      /* 1-byte format specifier */
+      if (len_remain<1) return offset;
+      format = tvb_get_guint8(tvb, offset);
+      item = proto_tree_add_uint_format(tree, hf_snmp_engineid_format, tvb, offset, 1, format, "Engine ID Format: %s (%d)",
+                                       val_to_str(format, snmp_engineid_format_vals, "Reserved/Enterprise-specific"), format);
+      offset+=1;
+      len_remain-=1;
+
+      switch(format) {
+      case SNMP_ENGINEID_FORMAT_IPV4:
+       /* 4-byte IPv4 address */
+       if (len_remain==4) {
+         proto_tree_add_item(tree, hf_snmp_engineid_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
+         offset+=4;
+         len_remain=0;
+       }
+       break;
+      case SNMP_ENGINEID_FORMAT_IPV6:
+       /* 16-byte IPv6 address */
+       if (len_remain==16) {
+         proto_tree_add_item(tree, hf_snmp_engineid_ipv6, tvb, offset, 16, ENC_NA);
+         offset+=16;
+         len_remain=0;
+       }
+       break;
+      case SNMP_ENGINEID_FORMAT_MACADDRESS:
+       /* See: https://supportforums.cisco.com/message/3010617#3010617 for details. */
+       if ((enterpriseid==9)&&(len_remain==7)) {
+         proto_tree_add_item(tree, hf_snmp_engineid_cisco_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+         offset++;
+         len_remain--;
+       }
+       /* 6-byte MAC address */
+       if (len_remain==6) {
+         proto_tree_add_item(tree, hf_snmp_engineid_mac, tvb, offset, 6, ENC_BIG_ENDIAN);
+         offset+=6;
+         len_remain=0;
+       }
+       break;
+      case SNMP_ENGINEID_FORMAT_TEXT:
+       /* max. 27-byte string, administratively assigned */
+       if (len_remain<=27) {
+         proto_tree_add_item(tree, hf_snmp_engineid_text, tvb, offset, len_remain, ENC_ASCII|ENC_NA);
+         offset+=len_remain;
+         len_remain=0;
+       }
+       break;
+      case 128:
+       /* most common enterprise-specific format: (ucd|net)-snmp random */
+       if ((enterpriseid==2021)||(enterpriseid==8072)) {
+         proto_item_append_text(item, (enterpriseid==2021) ? ": UCD-SNMP Random" : ": Net-SNMP Random");
+         /* demystify: 4B random, 4B epoch seconds */
+         if (len_remain==8) {
+           proto_tree_add_item(tree, hf_snmp_engineid_data, tvb, offset, 4, ENC_NA);
+           seconds = tvb_get_letohl(tvb, offset+4);
+           ts.secs = seconds;
+           ts.nsecs = 0;
+           proto_tree_add_time_format_value(tree, hf_snmp_engineid_time, tvb, offset+4, 4,
+                                            &ts, "%s",
+                                            abs_time_secs_to_str(seconds, ABSOLUTE_TIME_LOCAL, TRUE));
+           offset+=8;
+           len_remain=0;
+         }
+       }
+       break;
+      case SNMP_ENGINEID_FORMAT_OCTETS:
+      default:
+       /* max. 27 bytes, administratively assigned or unknown format */
+       if (len_remain<=27) {
+         proto_tree_add_item(tree, hf_snmp_engineid_data, tvb, offset, len_remain, ENC_NA);
+         offset+=len_remain;
+         len_remain=0;
+       }
+       break;
+      }
+    }
+
+    if (len_remain>0) {
+      proto_tree_add_text(tree, tvb, offset, len_remain, "<Data not conforming to RFC3411>");
+      offset+=len_remain;
+    }
+    return offset;
+}
+
+
+static void set_ue_keys(snmp_ue_assoc_t* n ) {
+       guint key_size = n->user.authModel->key_size;
+
+       n->user.authKey.data = se_alloc(key_size);
+       n->user.authKey.len = key_size;
+       n->user.authModel->pass2key(n->user.authPassword.data,
+                                   n->user.authPassword.len,
+                                   n->engine.data,
+                                   n->engine.len,
+                                   n->user.authKey.data);
+
+       n->user.privKey.data = se_alloc(key_size);
+       n->user.privKey.len = key_size;
+       n->user.authModel->pass2key(n->user.privPassword.data,
+                                   n->user.privPassword.len,
+                                   n->engine.data,
+                                   n->engine.len,
+                                   n->user.privKey.data);
+}
+
+static snmp_ue_assoc_t*
+ue_se_dup(snmp_ue_assoc_t* o)
+{
+       snmp_ue_assoc_t* d = se_memdup(o,sizeof(snmp_ue_assoc_t));
+
+       d->user.authModel = o->user.authModel;
+
+       d->user.privProtocol = o->user.privProtocol;
+
+       d->user.userName.data = se_memdup(o->user.userName.data,o->user.userName.len);
+       d->user.userName.len = o->user.userName.len;
+
+       d->user.authPassword.data = o->user.authPassword.data ? se_memdup(o->user.authPassword.data,o->user.authPassword.len) : NULL;
+       d->user.authPassword.len = o->user.authPassword.len;
+
+       d->user.privPassword.data = o->user.privPassword.data ? se_memdup(o->user.privPassword.data,o->user.privPassword.len) : NULL;
+       d->user.privPassword.len = o->user.privPassword.len;
+
+       d->engine.len = o->engine.len;
+
+       if (d->engine.len) {
+               d->engine.data = se_memdup(o->engine.data,o->engine.len);
+               set_ue_keys(d);
+       }
+
+       return d;
+
+}
+
+
+#define CACHE_INSERT(c,a) if (c) { snmp_ue_assoc_t* t = c; c = a; c->next = t; } else { c = a; a->next = NULL; }
+
+static void
+renew_ue_cache(void)
+{
+       localized_ues = NULL;
+       unlocalized_ues = NULL;
+
+       if (num_ueas) {
+               guint i;
+
+               for(i = 0; i < num_ueas; i++) {
+                       snmp_ue_assoc_t* a = ue_se_dup(&(ueas[i]));
+
+                       if (a->engine.len) {
+                               CACHE_INSERT(localized_ues,a);
 
-       case SNMP_MSG_TRAP:
-               /* enterprise */
-               ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
-                   &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "enterprise OID", ret);
-                       return;
-               }
-               if (tree) {
-                       oid_string = format_oid(enterprise, enterprise_length);
-                       proto_tree_add_string(tree, hf_snmp_enterprise, tvb,
-                           offset, length, oid_string);
-                       g_free(oid_string);
-               }
-               g_free(enterprise);
-               offset += length;
-
-               /* agent address */
-               start = asn1.offset;
-               ret = asn1_header_decode (&asn1, &cls, &con, &tag,
-                   &def, &agent_address_length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "agent address", ret);
-                       return;
-               }
-               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(tvb, offset, pinfo, tree,
-                           "agent_address", ASN1_ERR_WRONG_TYPE);
-                       return;
-               }
-               if (agent_address_length != 4) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
-                       return;
-               }
-               ret = asn1_string_value_decode (&asn1,
-                   agent_address_length, &agent_address);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "agent address", ret);
-                       return;
-               }
-               length = asn1.offset - start;
-               if (tree) {
-                       if (agent_address_length != 4) {
-                               proto_tree_add_text(tree, tvb, offset,
-                                   length,
-                                   "Agent address: <length is %u, not 4>",
-                                   agent_address_length);
                        } else {
-                               memcpy((guint8 *)&agent_ipaddr, agent_address,
-                                   agent_address_length);
-                               proto_tree_add_ipv4(tree, hf_snmp_agent, tvb,
-                                   offset, length, agent_ipaddr);
+                               CACHE_INSERT(unlocalized_ues,a);
                        }
+
                }
-               g_free(agent_address);
-               offset += length;
-
-               /* generic trap type */
-               ret = asn1_uint32_decode (&asn1, &trap_type, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "generic trap type", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_uint(tree, hf_snmp_traptype, tvb,
-                           offset, length, trap_type);
-               }
-               offset += length;
-
-               /* specific trap type */
-               ret = asn1_uint32_decode (&asn1, &specific_type, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "specific trap type", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_uint(tree, hf_snmp_spectraptype, tvb,
-                           offset, length, specific_type);
-               }
-               offset += length;
-
-               /* timestamp */
-               start = asn1.offset;
-               ret = asn1_header_decode (&asn1, &cls, &con, &tag,
-                   &def, &timestamp_length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "timestamp", ret);
-                       return;
-               }
-               if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
-                   (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "timestamp", ASN1_ERR_WRONG_TYPE);
-                       return;
-               }
-               ret = asn1_uint32_value_decode(&asn1, timestamp_length,
-                   &timestamp);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "timestamp", ret);
-                       return;
+       }
+}
+
+
+static snmp_ue_assoc_t*
+localize_ue( snmp_ue_assoc_t* o, const guint8* engine, guint engine_len )
+{
+       snmp_ue_assoc_t* n = se_memdup(o,sizeof(snmp_ue_assoc_t));
+
+       n->engine.data = se_memdup(engine,engine_len);
+       n->engine.len = engine_len;
+
+       set_ue_keys(n);
+
+       return n;
+}
+
+
+#define localized_match(a,u,ul,e,el) \
+       ( a->user.userName.len == ul \
+       && a->engine.len == el \
+       && memcmp( a->user.userName.data, u, ul ) == 0 \
+       && memcmp( a->engine.data,   e,  el ) == 0 )
+
+#define unlocalized_match(a,u,l) \
+       ( a->user.userName.len == l && memcmp( a->user.userName.data, u, l) == 0 )
+
+static snmp_ue_assoc_t*
+get_user_assoc(tvbuff_t* engine_tvb, tvbuff_t* user_tvb)
+{
+       static snmp_ue_assoc_t* a;
+       guint given_username_len;
+       guint8* given_username;
+       guint given_engine_len;
+       guint8* given_engine;
+
+       if ( ! (localized_ues || unlocalized_ues ) ) return NULL;
+
+       if (! ( user_tvb && engine_tvb ) ) return NULL;
+
+       given_username_len = tvb_ensure_length_remaining(user_tvb,0);
+       given_username = ep_tvb_memdup(user_tvb,0,-1);
+       given_engine_len = tvb_ensure_length_remaining(engine_tvb,0);
+       given_engine = ep_tvb_memdup(engine_tvb,0,-1);
+
+       for (a = localized_ues; a; a = a->next) {
+               if ( localized_match(a, given_username, given_username_len, given_engine, given_engine_len) ) {
+                       return a;
                }
-               length = asn1.offset - start;
-               if (tree) {
-                       proto_tree_add_uint(tree, hf_snmp_timestamp, tvb,
-                           offset, length, timestamp);
+       }
+
+       for (a = unlocalized_ues; a; a = a->next) {
+               if ( unlocalized_match(a, given_username, given_username_len) ) {
+                       snmp_ue_assoc_t* n = localize_ue( a, given_engine, given_engine_len );
+                       CACHE_INSERT(localized_ues,n);
+                       return n;
                }
-               offset += length;
-               break;
        }
 
-       /* variable bindings */
-       /* get header for variable-bindings sequence */
-       ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
-       if (ret != ASN1_ERR_NOERROR) {
-               dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                       "variable bindings header", ret);
-               return;
+       return NULL;
+}
+
+static gboolean
+snmp_usm_auth_md5(snmp_usm_params_t* p, guint8** calc_auth_p, guint* calc_auth_len_p, gchar const** error)
+{
+       guint msg_len;
+       guint8* msg;
+       guint auth_len;
+       guint8* auth;
+       guint8* key;
+       guint key_len;
+       guint8 *calc_auth;
+       guint start;
+       guint end;
+       guint i;
+
+       if (!p->auth_tvb) {
+               *error = "No Authenticator";
+               return FALSE;
        }
-       offset += length;
 
-       /* loop on variable bindings */
-       vb_index = 0;
-       while (variable_bindings_length > 0) {
-               vb_index++;
-               sequence_length = 0;
+       key = p->user_assoc->user.authKey.data;
+       key_len = p->user_assoc->user.authKey.len;
 
-               /* parse type */
-               ret = asn1_sequence_decode(&asn1, &variable_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                               "variable binding header", ret);
-                       return;
-               }
-               sequence_length += length;
-
-               /* parse object identifier */
-               ret = asn1_oid_decode (&asn1, &variable_oid,
-                   &variable_oid_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "variable binding OID", ret);
-                       return;
-               }
-               sequence_length += length;
-
-               if (display_oid || tree) {
-
-                 gchar *decoded_oid;
-                 gchar *non_decoded_oid;
-
-                 new_format_oid(variable_oid, variable_oid_length,
-                                &non_decoded_oid, &decoded_oid);
-                 
-                 if (display_oid && check_col(pinfo->cinfo, COL_INFO)) {
-                   col_append_fstr(pinfo->cinfo, COL_INFO, 
-                                   " %s", 
-                                   (decoded_oid == NULL) ? non_decoded_oid :
-                                   decoded_oid);
-                 }
-                 
-                 if (tree) {
-                   if (decoded_oid) {
-                     proto_tree_add_string_format(tree, hf_snmp_oid,
-                                                  tvb, offset, 
-                                                  sequence_length, 
-                                                  decoded_oid,
-                                                  "Object identifier %d: %s (%s)", 
-                                                  vb_index, 
-                                                  non_decoded_oid,
-                                                  decoded_oid);
-                     /* add also the non decoded oid string */
-                     proto_tree_add_string_hidden(tree, hf_snmp_oid,
-                                                  tvb, offset, 
-                                                  sequence_length,
-                                                  non_decoded_oid);
-                   } else {
-                     proto_tree_add_string_format(tree, hf_snmp_oid,
-                                                  tvb, offset, 
-                                                  sequence_length, 
-                                                  non_decoded_oid,
-                                                  "Object identifier %d: %s", 
-                                                  vb_index, 
-                                                  non_decoded_oid);
-                   }
-                 }
-                 
-                 if (decoded_oid) g_free(decoded_oid);
-                 g_free(non_decoded_oid);
+       if (! key ) {
+               *error = "User has no authKey";
+               return FALSE;
+       }
 
-               }
 
-               offset += sequence_length;
-               variable_bindings_length -= sequence_length;
+       auth_len = tvb_length_remaining(p->auth_tvb,0);
 
-               /*
-                * Register a cleanup function in case one of our
-                * tvbuff accesses throws an exception.  We need
-                * to clean up variable_oid.
-                */
-               CLEANUP_PUSH(g_free, variable_oid);
-
-               /* Parse the variable's value */
-               next_tvb = NULL;
-               ret = snmp_variable_decode(tree, variable_oid,
-                   variable_oid_length, &asn1, offset, &length, &next_tvb);
-               if (next_tvb) {
-                       new_format_oid(variable_oid, variable_oid_length,
-                           &non_decoded_oid, &decoded_oid);
-                       dissector_try_string(variable_oid_dissector_table,
-                           non_decoded_oid, next_tvb, pinfo, root_tree);
-                       if (decoded_oid)
-                               g_free(decoded_oid);
-                       g_free(non_decoded_oid);
-               }
+       if (auth_len != 12) {
+               *error = "Authenticator length wrong";
+               return FALSE;
+       }
 
-               /*
-                * We're done with variable_oid, so we can call the cleanup
-                * handler to free* it, and then pop the cleanup handler.
-                */
-               CLEANUP_CALL_AND_POP;
+       msg_len = tvb_length_remaining(p->msg_tvb,0);
+       msg = ep_tvb_memdup(p->msg_tvb,0,msg_len);
 
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, tree,
-                           "variable", ret);
-                       return;
-               }
-               offset += length;
-               variable_bindings_length -= length;
+
+       auth = ep_tvb_memdup(p->auth_tvb,0,auth_len);
+
+       start = p->auth_offset - p->start_offset;
+       end =   start + auth_len;
+
+       /* fill the authenticator with zeros */
+       for ( i = start ; i < end ; i++ ) {
+               msg[i] = '\0';
        }
+
+       calc_auth = ep_alloc(16);
+
+       md5_hmac(msg, msg_len, key, key_len, calc_auth);
+
+       if (calc_auth_p) *calc_auth_p = calc_auth;
+       if (calc_auth_len_p) *calc_auth_len_p = 12;
+
+       return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
 }
 
-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
-dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
-    guchar *parameters, int parameters_length)
+static gboolean
+snmp_usm_auth_sha1(snmp_usm_params_t* p _U_, guint8** calc_auth_p, guint* calc_auth_len_p,  gchar const** error _U_)
 {
-       proto_item *item;
-       proto_tree *parameters_tree;
-       proto_tree *qos_tree;
-       guint8 model;
-       guint8 qos;
-       guint8 len;
-
-       item = proto_tree_add_text(tree, tvb, offset, length,
-           "Parameters");
-       parameters_tree = proto_item_add_subtree(item, ett_parameters);
-       offset += length - parameters_length;
-
-       if (parameters_length < 1)
-               return;
-       model = *parameters;
-       proto_tree_add_text(parameters_tree, tvb, offset, 1,
-           "model: %u", model);
-       offset += 1;
-       parameters += 1;
-       parameters_length -= 1;
-       if (model != 1) {
-               /* Unknown model. */
-               proto_tree_add_text(parameters_tree, tvb, offset,                   parameters_length, "parameters: %s",
-                   bytes_to_str(parameters, parameters_length));
-               return;
+       guint msg_len;
+       guint8* msg;
+       guint auth_len;
+       guint8* auth;
+       guint8* key;
+       guint key_len;
+       guint8 *calc_auth;
+       guint start;
+       guint end;
+       guint i;
+
+       if (!p->auth_tvb) {
+               *error = "No Authenticator";
+               return FALSE;
        }
 
-       if (parameters_length < 1)
-               return;
-       qos = *parameters;
-       item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
-           "qoS: 0x%x", qos);
-       qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
-       proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
-           decode_boolean_bitfield(qos, 0x04,
-               8, "Generation of report PDU allowed",
-                  "Generation of report PDU not allowed"));
-       proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
-           decode_enumerated_bitfield(qos, 0x03,
-               8, qos_vals, "%s"));
-       offset += 1;
-       parameters += 1;
-       parameters_length -= 1;
-
-       if (parameters_length < 12)
-               return;
-       proto_tree_add_text(parameters_tree, tvb, offset, 12,
-           "agentID: %s", bytes_to_str(parameters, 12));
-       offset += 12;
-       parameters += 12;
-       parameters_length -= 12;
+       key = p->user_assoc->user.authKey.data;
+       key_len = p->user_assoc->user.authKey.len;
 
-       if (parameters_length < 4)
-               return;
-       proto_tree_add_text(parameters_tree, tvb, offset, 4,
-           "agentBoots: %u", pntohl(parameters));
-       offset += 4;
-       parameters += 4;
-       parameters_length -= 4;
+       if (! key ) {
+               *error = "User has no authKey";
+               return FALSE;
+       }
 
-       if (parameters_length < 4)
-               return;
-       proto_tree_add_text(parameters_tree, tvb, offset, 4,
-           "agentTime: %u", pntohl(parameters));
-       offset += 4;
-       parameters += 4;
-       parameters_length -= 4;
 
-       if (parameters_length < 2)
-               return;
-       proto_tree_add_text(parameters_tree, tvb, offset, 2,
-           "maxSize: %u", pntohs(parameters));
-       offset += 2;
-       parameters += 2;
-       parameters_length -= 2;
+       auth_len = tvb_length_remaining(p->auth_tvb,0);
 
-       if (parameters_length < 1)
-               return;
-       len = *parameters;
-       proto_tree_add_text(parameters_tree, tvb, offset, 1,
-           "userLen: %u", len);
-       offset += 1;
-       parameters += 1;
-       parameters_length -= 1;
-
-       if (parameters_length < len)
-               return;
-       proto_tree_add_text(parameters_tree, tvb, offset, len,
-           "userName: %.*s", len, parameters);
-       offset += len;
-       parameters += len;
-       parameters_length -= len;
 
-       if (parameters_length < 1)
-               return;
-       len = *parameters;
-       proto_tree_add_text(parameters_tree, tvb, offset, 1,
-           "authLen: %u", len);
-       offset += 1;
-       parameters += 1;
-       parameters_length -= 1;
-
-       if (parameters_length < len)
-               return;
-       proto_tree_add_text(parameters_tree, tvb, offset, len,
-           "authDigest: %s", bytes_to_str(parameters, len));
-       offset += len;
-       parameters += len;
-       parameters_length -= len;
+       if (auth_len != 12) {
+               *error = "Authenticator length wrong";
+               return FALSE;
+       }
+
+       msg_len = tvb_length_remaining(p->msg_tvb,0);
+       msg = ep_tvb_memdup(p->msg_tvb,0,msg_len);
+
+       auth = ep_tvb_memdup(p->auth_tvb,0,auth_len);
+
+       start = p->auth_offset - p->start_offset;
+       end =   start + auth_len;
+
+       /* fill the authenticator with zeros */
+       for ( i = start ; i < end ; i++ ) {
+               msg[i] = '\0';
+       }
+
+       calc_auth = ep_alloc(20);
+
+       sha1_hmac(key, key_len, msg, msg_len, calc_auth);
+
+       if (calc_auth_p) *calc_auth_p = calc_auth;
+       if (calc_auth_len_p) *calc_auth_len_p = 12;
+
+       return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
+}
+
+static tvbuff_t*
+snmp_usm_priv_des(snmp_usm_params_t* p _U_, tvbuff_t* encryptedData _U_, gchar const** error _U_)
+{
+#ifdef HAVE_LIBGCRYPT
+    gcry_error_t err;
+    gcry_cipher_hd_t hd = NULL;
+
+       guint8* cleartext;
+       guint8* des_key = p->user_assoc->user.privKey.data; /* first 8 bytes */
+       guint8* pre_iv = &(p->user_assoc->user.privKey.data[8]); /* last 8 bytes */
+       guint8* salt;
+       gint salt_len;
+       gint cryptgrm_len;
+       guint8* cryptgrm;
+       tvbuff_t* clear_tvb;
+       guint8 iv[8];
+       guint i;
+
+
+       salt_len = tvb_length_remaining(p->priv_tvb,0);
+
+       if (salt_len != 8)  {
+               *error = "decryptionError: msgPrivacyParameters length != 8";
+               return NULL;
+       }
+
+       salt = ep_tvb_memdup(p->priv_tvb,0,salt_len);
+
+       /*
+        The resulting "salt" is XOR-ed with the pre-IV to obtain the IV.
+        */
+       for (i=0; i<8; i++) {
+               iv[i] = pre_iv[i] ^ salt[i];
+       }
+
+       cryptgrm_len = tvb_length_remaining(encryptedData,0);
+
+       if (cryptgrm_len % 8) {
+               *error = "decryptionError: the length of the encrypted data is not a mutiple of 8 octets";
+               return NULL;
+       }
+
+       cryptgrm = ep_tvb_memdup(encryptedData,0,-1);
+
+       cleartext = ep_alloc(cryptgrm_len);
+
+       err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC, 0);
+       if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
+
+       err = gcry_cipher_setiv(hd, iv, 8);
+       if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
+
+       err = gcry_cipher_setkey(hd,des_key,8);
+       if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
+
+       err = gcry_cipher_decrypt(hd, cleartext, cryptgrm_len, cryptgrm, cryptgrm_len);
+       if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
+
+       gcry_cipher_close(hd);
+
+       clear_tvb = tvb_new_child_real_data(encryptedData, cleartext, cryptgrm_len, cryptgrm_len);
+
+       return clear_tvb;
+
+on_gcry_error:
+       *error = (void*)gpg_strerror(err);
+       if (hd) gcry_cipher_close(hd);
+       return NULL;
+#else
+       *error = "libgcrypt not present, cannot decrypt";
+       return NULL;
+#endif
+}
+
+static tvbuff_t*
+snmp_usm_priv_aes(snmp_usm_params_t* p _U_, tvbuff_t* encryptedData _U_, gchar const** error _U_)
+{
+#ifdef HAVE_LIBGCRYPT
+       gcry_error_t err;
+       gcry_cipher_hd_t hd = NULL;
+
+       guint8* cleartext;
+       guint8* aes_key = p->user_assoc->user.privKey.data; /* first 16 bytes */
+       guint8 iv[16];
+       gint priv_len;
+       gint cryptgrm_len;
+       guint8* cryptgrm;
+       tvbuff_t* clear_tvb;
+
+       priv_len = tvb_length_remaining(p->priv_tvb,0);
+
+       if (priv_len != 8)  {
+               *error = "decryptionError: msgPrivacyParameters length != 8";
+               return NULL;
+       }
+
+       iv[0] = (p->boots & 0xff000000) >> 24;
+       iv[1] = (p->boots & 0x00ff0000) >> 16;
+       iv[2] = (p->boots & 0x0000ff00) >> 8;
+       iv[3] = (p->boots & 0x000000ff);
+       iv[4] = (p->time & 0xff000000) >> 24;
+       iv[5] = (p->time & 0x00ff0000) >> 16;
+       iv[6] = (p->time & 0x0000ff00) >> 8;
+       iv[7] = (p->time & 0x000000ff);
+       tvb_memcpy(p->priv_tvb,&(iv[8]),0,8);
+
+       cryptgrm_len = tvb_length_remaining(encryptedData,0);
+       cryptgrm = ep_tvb_memdup(encryptedData,0,-1);
+
+       cleartext = ep_alloc(cryptgrm_len);
+
+       err = gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CFB, 0);
+       if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
+
+       err = gcry_cipher_setiv(hd, iv, 16);
+       if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
+
+       err = gcry_cipher_setkey(hd,aes_key,16);
+       if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
+
+       err = gcry_cipher_decrypt(hd, cleartext, cryptgrm_len, cryptgrm, cryptgrm_len);
+       if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
+
+       gcry_cipher_close(hd);
+
+       clear_tvb = tvb_new_child_real_data(encryptedData, cleartext, cryptgrm_len, cryptgrm_len);
+
+       return clear_tvb;
+
+on_gcry_error:
+       *error = (void*)gpg_strerror(err);
+       if (hd) gcry_cipher_close(hd);
+       return NULL;
+#else
+       *error = "libgcrypt not present, cannot decrypt";
+       return NULL;
+#endif
+}
+
+
+gboolean
+check_ScopedPdu(tvbuff_t* tvb)
+{
+       int offset;
+       gint8 class;
+       gboolean pc;
+       gint32 tag;
+       int hoffset, eoffset;
+       guint32 len;
+
+       offset = get_ber_identifier(tvb, 0, &class, &pc, &tag);
+       offset = get_ber_length(tvb, offset, NULL, NULL);
+
+       if ( ! (((class!=BER_CLASS_APP) && (class!=BER_CLASS_PRI) )
+                       && ( (!pc) || (class!=BER_CLASS_UNI) || (tag!=BER_UNI_TAG_ENUMERATED) )
+                       )) return FALSE;
+
+       if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0))
+               return TRUE;
+
+       hoffset = offset;
+
+       offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
+       offset = get_ber_length(tvb, offset, &len, NULL);
+       eoffset = offset + len;
+
+       if (eoffset <= hoffset) return FALSE;
+
+       if ((class!=BER_CLASS_APP)&&(class!=BER_CLASS_PRI))
+               if( (class!=BER_CLASS_UNI)
+                       ||((tag<BER_UNI_TAG_NumericString)&&(tag!=BER_UNI_TAG_OCTETSTRING)&&(tag!=BER_UNI_TAG_UTF8String)) )
+                       return FALSE;
+
+       return TRUE;
+
+}
+
+
+/*--- Included file: packet-snmp-fn.c ---*/
+#line 1 "../../asn1/snmp/packet-snmp-fn.c"
+
+
+
+static int
+dissect_snmp_EnterpriseOID(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 64 "../../asn1/snmp/snmp.cnf"
+  const gchar* name;
+
+  offset = dissect_ber_object_identifier_str(implicit_tag, actx, tree, tvb, offset, hf_index, &enterprise_oid);
+
+
+  if (display_oid && enterprise_oid) {
+    name = oid_resolved_from_string(enterprise_oid);
+    if (name) {
+      col_append_fstr (actx->pinfo->cinfo, COL_INFO, " %s", name);
+    }
+  }
+
+
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_OCTET_STRING_SIZE_4(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_NetworkAddress(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_APP, 0, TRUE, dissect_snmp_OCTET_STRING_SIZE_4);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_INTEGER_0_4294967295(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_TimeTicks(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_APP, 3, TRUE, dissect_snmp_INTEGER_0_4294967295);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_Integer32(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_ObjectName(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
+
+  return offset;
+}
+
+
+static const value_string snmp_Version_vals[] = {
+  {   0, "version-1" },
+  {   1, "v2c" },
+  {   2, "v2u" },
+  {   3, "snmpv3" },
+  { 0, NULL }
+};
+
+
+static int
+dissect_snmp_Version(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_Community(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_INTEGER(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+static const value_string snmp_T_error_status_vals[] = {
+  {   0, "noError" },
+  {   1, "tooBig" },
+  {   2, "noSuchName" },
+  {   3, "badValue" },
+  {   4, "readOnly" },
+  {   5, "genErr" },
+  {   6, "noAccess" },
+  {   7, "wrongType" },
+  {   8, "wrongLength" },
+  {   9, "wrongEncoding" },
+  {  10, "wrongValue" },
+  {  11, "noCreation" },
+  {  12, "inconsistentValue" },
+  {  13, "resourceUnavailable" },
+  {  14, "commitFailed" },
+  {  15, "undoFailed" },
+  {  16, "authorizationError" },
+  {  17, "notWritable" },
+  {  18, "inconsistentName" },
+  { 0, NULL }
+};
+
+
+static int
+dissect_snmp_T_error_status(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_NULL(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_null(implicit_tag, actx, tree, tvb, offset, hf_index);
+
+  return offset;
+}
+
+
+
+static const ber_sequence_t VarBindList_sequence_of[1] = {
+  { &hf_snmp_VarBindList_item, BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_VarBind },
+};
+
+static int
+dissect_snmp_VarBindList(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset,
+                                      VarBindList_sequence_of, hf_index, ett_snmp_VarBindList);
+
+  return offset;
+}
+
+
+static const ber_sequence_t PDU_sequence[] = {
+  { &hf_snmp_request_id     , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER },
+  { &hf_snmp_error_status   , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_error_status },
+  { &hf_snmp_error_index    , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER },
+  { &hf_snmp_variable_bindings, BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_VarBindList },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   PDU_sequence, hf_index, ett_snmp_PDU);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_GetRequest_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_CON, 0, TRUE, dissect_snmp_PDU);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_GetNextRequest_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_CON, 1, TRUE, dissect_snmp_PDU);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_GetResponse_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_CON, 2, TRUE, dissect_snmp_PDU);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_SetRequest_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_CON, 3, TRUE, dissect_snmp_PDU);
+
+  return offset;
+}
+
+
+static const value_string snmp_GenericTrap_vals[] = {
+  {   0, "coldStart" },
+  {   1, "warmStart" },
+  {   2, "linkDown" },
+  {   3, "linkUp" },
+  {   4, "authenticationFailure" },
+  {   5, "egpNeighborLoss" },
+  {   6, "enterpriseSpecific" },
+  { 0, NULL }
+};
+
+
+static int
+dissect_snmp_GenericTrap(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                &generic_trap);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_SpecificTrap(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 48 "../../asn1/snmp/snmp.cnf"
+  guint specific_trap;
+  
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                &specific_trap);
+
+
+  if (generic_trap == 6) { /* enterprise specific */
+    const gchar *specific_str = snmp_lookup_specific_trap (specific_trap);
+    if (specific_str) {
+      proto_item_append_text(actx->created_item, " (%s)", specific_str);
+    }
+  }
+
+
+  return offset;
+}
+
+
+static const ber_sequence_t Trap_PDU_U_sequence[] = {
+  { &hf_snmp_enterprise     , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_snmp_EnterpriseOID },
+  { &hf_snmp_agent_addr     , BER_CLASS_APP, 0, BER_FLAGS_NOOWNTAG, dissect_snmp_NetworkAddress },
+  { &hf_snmp_generic_trap   , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_GenericTrap },
+  { &hf_snmp_specific_trap  , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_SpecificTrap },
+  { &hf_snmp_time_stamp     , BER_CLASS_APP, 3, BER_FLAGS_NOOWNTAG, dissect_snmp_TimeTicks },
+  { &hf_snmp_variable_bindings, BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_VarBindList },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_Trap_PDU_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 40 "../../asn1/snmp/snmp.cnf"
+  generic_trap = 0;
+  enterprise_oid = NULL;
+
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   Trap_PDU_U_sequence, hf_index, ett_snmp_Trap_PDU_U);
+
+
+
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_Trap_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_CON, 4, TRUE, dissect_snmp_Trap_PDU_U);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_INTEGER_0_2147483647(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+static const ber_sequence_t BulkPDU_sequence[] = {
+  { &hf_snmp_bulkPDU_request_id, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_Integer32 },
+  { &hf_snmp_non_repeaters  , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_0_2147483647 },
+  { &hf_snmp_max_repetitions, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_0_2147483647 },
+  { &hf_snmp_variable_bindings, BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_VarBindList },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_BulkPDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   BulkPDU_sequence, hf_index, ett_snmp_BulkPDU);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_GetBulkRequest_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_CON, 5, TRUE, dissect_snmp_BulkPDU);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_InformRequest_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_CON, 6, TRUE, dissect_snmp_PDU);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_SNMPv2_Trap_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_CON, 7, TRUE, dissect_snmp_PDU);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_Report_PDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_CON, 8, TRUE, dissect_snmp_PDU);
+
+  return offset;
+}
+
+
+static const value_string snmp_PDUs_vals[] = {
+  {   0, "get-request" },
+  {   1, "get-next-request" },
+  {   2, "get-response" },
+  {   3, "set-request" },
+  {   4, "trap" },
+  {   5, "getBulkRequest" },
+  {   6, "informRequest" },
+  {   7, "snmpV2-trap" },
+  {   8, "report" },
+  { 0, NULL }
+};
+
+static const ber_choice_t PDUs_choice[] = {
+  {   0, &hf_snmp_get_request    , BER_CLASS_CON, 0, BER_FLAGS_NOOWNTAG, dissect_snmp_GetRequest_PDU },
+  {   1, &hf_snmp_get_next_request, BER_CLASS_CON, 1, BER_FLAGS_NOOWNTAG, dissect_snmp_GetNextRequest_PDU },
+  {   2, &hf_snmp_get_response   , BER_CLASS_CON, 2, BER_FLAGS_NOOWNTAG, dissect_snmp_GetResponse_PDU },
+  {   3, &hf_snmp_set_request    , BER_CLASS_CON, 3, BER_FLAGS_NOOWNTAG, dissect_snmp_SetRequest_PDU },
+  {   4, &hf_snmp_trap           , BER_CLASS_CON, 4, BER_FLAGS_NOOWNTAG, dissect_snmp_Trap_PDU },
+  {   5, &hf_snmp_getBulkRequest , BER_CLASS_CON, 5, BER_FLAGS_NOOWNTAG, dissect_snmp_GetBulkRequest_PDU },
+  {   6, &hf_snmp_informRequest  , BER_CLASS_CON, 6, BER_FLAGS_NOOWNTAG, dissect_snmp_InformRequest_PDU },
+  {   7, &hf_snmp_snmpV2_trap    , BER_CLASS_CON, 7, BER_FLAGS_NOOWNTAG, dissect_snmp_SNMPv2_Trap_PDU },
+  {   8, &hf_snmp_report         , BER_CLASS_CON, 8, BER_FLAGS_NOOWNTAG, dissect_snmp_Report_PDU },
+  { 0, NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_PDUs(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 28 "../../asn1/snmp/snmp.cnf"
+gint pdu_type=-1;
+
+  col_clear(actx->pinfo->cinfo, COL_INFO);
+
+  offset = dissect_ber_choice(actx, tree, tvb, offset,
+                                 PDUs_choice, hf_index, ett_snmp_PDUs,
+                                 &pdu_type);
+
+  if( (pdu_type!=-1) && snmp_PDUs_vals[pdu_type].strptr ){
+       col_prepend_fstr(actx->pinfo->cinfo, COL_INFO, "%s", snmp_PDUs_vals[pdu_type].strptr);
+  }
+
+
+
+  return offset;
+}
+
+
+static const ber_sequence_t Message_sequence[] = {
+  { &hf_snmp_version        , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_Version },
+  { &hf_snmp_community      , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_Community },
+  { &hf_snmp_data           , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_snmp_PDUs },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_Message(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   Message_sequence, hf_index, ett_snmp_Message);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_OCTET_STRING(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       NULL);
+
+  return offset;
+}
+
+
+static const value_string snmp_T_datav2u_vals[] = {
+  {   0, "plaintext" },
+  {   1, "encrypted" },
+  { 0, NULL }
+};
+
+static const ber_choice_t T_datav2u_choice[] = {
+  {   0, &hf_snmp_v2u_plaintext  , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG, dissect_snmp_PDUs },
+  {   1, &hf_snmp_encrypted      , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_OCTET_STRING },
+  { 0, NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_T_datav2u(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_choice(actx, tree, tvb, offset,
+                                 T_datav2u_choice, hf_index, ett_snmp_T_datav2u,
+                                 NULL);
+
+  return offset;
+}
+
+
+static const ber_sequence_t Messagev2u_sequence[] = {
+  { &hf_snmp_version        , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_Version },
+  { &hf_snmp_parameters     , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_OCTET_STRING },
+  { &hf_snmp_datav2u        , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_snmp_T_datav2u },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_Messagev2u(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   Messagev2u_sequence, hf_index, ett_snmp_Messagev2u);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_SnmpEngineID(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 99 "../../asn1/snmp/snmp.cnf"
+       tvbuff_t* param_tvb = NULL;
+
+       offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       &param_tvb);
+        if (param_tvb) {
+               proto_tree* engine_tree = proto_item_add_subtree(actx->created_item,ett_engineid);
+               dissect_snmp_engineid(engine_tree, param_tvb, 0, tvb_length_remaining(param_tvb,0));
+       }
+
+
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_msgAuthoritativeEngineID(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 90 "../../asn1/snmp/snmp.cnf"
+
+  offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       &usm_p.engine_tvb);
+        if (usm_p.engine_tvb) {
+               proto_tree* engine_tree = proto_item_add_subtree(actx->created_item,ett_engineid);
+               dissect_snmp_engineid(engine_tree, usm_p.engine_tvb, 0, tvb_length_remaining(usm_p.engine_tvb,0));
+       }
+
+
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_msgAuthoritativeEngineBoots(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                &usm_p.boots);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_msgAuthoritativeEngineTime(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                &usm_p.time);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_msgUserName(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       &usm_p.user_tvb);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_msgAuthenticationParameters(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 112 "../../asn1/snmp/snmp.cnf"
+       offset = dissect_ber_octet_string(FALSE, actx, tree, tvb, offset, hf_index, &usm_p.auth_tvb);
+       if (usm_p.auth_tvb) {
+               usm_p.auth_item = actx->created_item;
+               usm_p.auth_offset = tvb_offset_from_real_beginning(usm_p.auth_tvb);
+       }
+
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_msgPrivacyParameters(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       &usm_p.priv_tvb);
+
+  return offset;
+}
+
+
+static const ber_sequence_t UsmSecurityParameters_sequence[] = {
+  { &hf_snmp_msgAuthoritativeEngineID, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgAuthoritativeEngineID },
+  { &hf_snmp_msgAuthoritativeEngineBoots, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgAuthoritativeEngineBoots },
+  { &hf_snmp_msgAuthoritativeEngineTime, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgAuthoritativeEngineTime },
+  { &hf_snmp_msgUserName    , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgUserName },
+  { &hf_snmp_msgAuthenticationParameters, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgAuthenticationParameters },
+  { &hf_snmp_msgPrivacyParameters, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgPrivacyParameters },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_UsmSecurityParameters(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   UsmSecurityParameters_sequence, hf_index, ett_snmp_UsmSecurityParameters);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_INTEGER_484_2147483647(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_msgFlags(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 227 "../../asn1/snmp/snmp.cnf"
+       tvbuff_t *parameter_tvb = NULL;
+
+   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       &parameter_tvb);
+
+ if (parameter_tvb){
+       guint8 v3_flags = tvb_get_guint8(parameter_tvb, 0);
+       proto_tree* flags_tree = proto_item_add_subtree(actx->created_item,ett_msgFlags);
+       
+       proto_tree_add_item(flags_tree, hf_snmp_v3_flags_report, parameter_tvb, 0, 1, FALSE);
+       proto_tree_add_item(flags_tree, hf_snmp_v3_flags_crypt, parameter_tvb, 0, 1, FALSE);
+       proto_tree_add_item(flags_tree, hf_snmp_v3_flags_auth, parameter_tvb, 0, 1, FALSE);
+       
+       usm_p.encrypted = v3_flags & TH_CRYPT ? TRUE : FALSE;
+       usm_p.authenticated = v3_flags & TH_AUTH ? TRUE : FALSE;
+  }
+
+
+
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_msgSecurityModel(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                &MsgSecurityModel);
+
+  return offset;
+}
+
+
+static const ber_sequence_t HeaderData_sequence[] = {
+  { &hf_snmp_msgID          , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_0_2147483647 },
+  { &hf_snmp_msgMaxSize     , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_484_2147483647 },
+  { &hf_snmp_msgFlags       , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgFlags },
+  { &hf_snmp_msgSecurityModel, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgSecurityModel },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_HeaderData(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   HeaderData_sequence, hf_index, ett_snmp_HeaderData);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_msgSecurityParameters(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 170 "../../asn1/snmp/snmp.cnf"
+
+       switch(MsgSecurityModel){
+               case SNMP_SEC_USM:      /* 3 */         
+                       offset = dissect_snmp_UsmSecurityParameters(FALSE, tvb, offset+2, actx, tree, -1);
+                       usm_p.user_assoc = get_user_assoc(usm_p.engine_tvb, usm_p.user_tvb);
+                       break;
+               case SNMP_SEC_ANY:      /* 0 */
+               case SNMP_SEC_V1:       /* 1 */
+               case SNMP_SEC_V2C:      /* 2 */
+               default:
+                         offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       NULL);
+
+                       break;
+       }
+
+
+
+  return offset;
+}
+
+
+static const ber_sequence_t ScopedPDU_sequence[] = {
+  { &hf_snmp_contextEngineID, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_SnmpEngineID },
+  { &hf_snmp_contextName    , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_OCTET_STRING },
+  { &hf_snmp_data           , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_snmp_PDUs },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_ScopedPDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   ScopedPDU_sequence, hf_index, ett_snmp_ScopedPDU);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_T_encryptedPDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 121 "../../asn1/snmp/snmp.cnf"
+       tvbuff_t* crypt_tvb;
+       offset = dissect_ber_octet_string(FALSE, actx, tree, tvb, offset, hf_snmp_encryptedPDU, &crypt_tvb);
+
+       if( usm_p.encrypted && crypt_tvb
+               && usm_p.user_assoc
+               && usm_p.user_assoc->user.privProtocol ) {
+               
+               const gchar* error = NULL;
+               proto_tree* encryptedpdu_tree = proto_item_add_subtree(actx->created_item,ett_encryptedPDU);
+               tvbuff_t* cleartext_tvb = usm_p.user_assoc->user.privProtocol(&usm_p, crypt_tvb, &error );
+
+               if (! cleartext_tvb) {
+                       proto_item* cause = proto_tree_add_text(encryptedpdu_tree, crypt_tvb, 0, -1,
+                               "Failed to decrypt encryptedPDU: %s", error);
+                       
+                       expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN,
+                               "Failed to decrypt encryptedPDU: %s", error);
+
+                       col_set_str(actx->pinfo->cinfo, COL_INFO, "encryptedPDU: Failed to decrypt");
+                               
+                       return offset;
+               } else {
+                       proto_item* decrypted_item;
+                       proto_tree* decrypted_tree;
+
+                       if (! check_ScopedPdu(cleartext_tvb)) {
+                               proto_item* cause = proto_tree_add_text(encryptedpdu_tree, cleartext_tvb, 0, -1,
+                                                                                       "Decrypted data not formatted as expected, wrong key?");
+                               
+                               expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN,
+                                                                          "Decrypted data not formatted as expected");
+
+                               col_set_str(actx->pinfo->cinfo, COL_INFO, "encryptedPDU: Decrypted data not formatted as expected");
+                               
+                               return offset;
+                       }
+
+                       
+            add_new_data_source(actx->pinfo, cleartext_tvb, "Decrypted ScopedPDU");
+                       
+                       decrypted_item = proto_tree_add_item(encryptedpdu_tree, hf_snmp_decryptedPDU,cleartext_tvb,0,-1,FALSE);
+                       decrypted_tree = proto_item_add_subtree(decrypted_item,ett_decrypted);
+                       dissect_snmp_ScopedPDU(FALSE, cleartext_tvb, 0, actx, decrypted_tree, -1);
+                }
+       } else {
+                       col_set_str(actx->pinfo->cinfo, COL_INFO, "encryptedPDU: privKey Unknown");
+       }
+
+
+
+  return offset;
+}
+
+
+static const value_string snmp_ScopedPduData_vals[] = {
+  {   0, "plaintext" },
+  {   1, "encryptedPDU" },
+  { 0, NULL }
+};
+
+static const ber_choice_t ScopedPduData_choice[] = {
+  {   0, &hf_snmp_plaintext      , BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_ScopedPDU },
+  {   1, &hf_snmp_encryptedPDU   , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_encryptedPDU },
+  { 0, NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_ScopedPduData(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_choice(actx, tree, tvb, offset,
+                                 ScopedPduData_choice, hf_index, ett_snmp_ScopedPduData,
+                                 NULL);
+
+  return offset;
+}
+
+
+static const ber_sequence_t SNMPv3Message_sequence[] = {
+  { &hf_snmp_msgVersion     , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_Version },
+  { &hf_snmp_msgGlobalData  , BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_HeaderData },
+  { &hf_snmp_msgSecurityParameters, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgSecurityParameters },
+  { &hf_snmp_msgData        , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_snmp_ScopedPduData },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_SNMPv3Message(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   SNMPv3Message_sequence, hf_index, ett_snmp_SNMPv3Message);
+
+#line 185 "../../asn1/snmp/snmp.cnf"
+
+       if( usm_p.authenticated
+               && usm_p.user_assoc
+               && usm_p.user_assoc->user.authModel ) {
+               const gchar* error = NULL;
+               proto_item* authen_item;
+               proto_tree* authen_tree = proto_item_add_subtree(usm_p.auth_item,ett_authParameters);
+               guint8* calc_auth;
+               guint calc_auth_len;
+               
+               usm_p.authOK = usm_p.user_assoc->user.authModel->authenticate( &usm_p, &calc_auth, &calc_auth_len, &error );
+
+               if (error) {
+                       authen_item = proto_tree_add_text(authen_tree,tvb,0,0,"Error while verifying Message authenticity: %s", error);
+                       PROTO_ITEM_SET_GENERATED(authen_item);
+                       expert_add_info_format( actx->pinfo, authen_item, PI_MALFORMED, PI_ERROR, "Error while verifying Message authenticity: %s", error );
+               } else {
+                       int severity;
+                       gchar* msg;                     
+
+                       authen_item = proto_tree_add_boolean(authen_tree, hf_snmp_msgAuthentication, tvb, 0, 0, usm_p.authOK);
+                       PROTO_ITEM_SET_GENERATED(authen_item);
+                       
+                       if (usm_p.authOK) {
+                               msg = "SNMP Authentication OK";
+                               severity = PI_CHAT;
+                       } else {
+                               gchar* calc_auth_str = bytestring_to_str(calc_auth,calc_auth_len,' ');
+                               proto_item_append_text(authen_item, " calculated = %s", calc_auth_str);
+                               msg = "SNMP Authentication Error";
+                               severity = PI_WARN;
+                       }
+
+                       expert_add_info_format( actx->pinfo, authen_item, PI_CHECKSUM, severity, "%s", msg );
+               }
+       }
+
+
+  return offset;
+}
+
+
+static const value_string snmp_T_smux_version_vals[] = {
+  {   0, "version-1" },
+  { 0, NULL }
+};
+
+
+static int
+dissect_snmp_T_smux_version(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_OBJECT_IDENTIFIER(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_DisplayString(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                       NULL);
+
+  return offset;
+}
+
+
+static const ber_sequence_t SimpleOpen_U_sequence[] = {
+  { &hf_snmp_smux_version   , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_smux_version },
+  { &hf_snmp_identity       , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_snmp_OBJECT_IDENTIFIER },
+  { &hf_snmp_description    , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_DisplayString },
+  { &hf_snmp_password       , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_OCTET_STRING },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_SimpleOpen_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   SimpleOpen_U_sequence, hf_index, ett_snmp_SimpleOpen_U);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_SimpleOpen(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_APP, 0, TRUE, dissect_snmp_SimpleOpen_U);
+
+  return offset;
+}
+
+
+static const value_string snmp_OpenPDU_vals[] = {
+  {   0, "smux-simple" },
+  { 0, NULL }
+};
+
+static const ber_choice_t OpenPDU_choice[] = {
+  {   0, &hf_snmp_smux_simple    , BER_CLASS_APP, 0, BER_FLAGS_NOOWNTAG, dissect_snmp_SimpleOpen },
+  { 0, NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_OpenPDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_choice(actx, tree, tvb, offset,
+                                 OpenPDU_choice, hf_index, ett_snmp_OpenPDU,
+                                 NULL);
+
+  return offset;
+}
+
+
+static const value_string snmp_ClosePDU_U_vals[] = {
+  {   0, "goingDown" },
+  {   1, "unsupportedVersion" },
+  {   2, "packetFormat" },
+  {   3, "protocolError" },
+  {   4, "internalError" },
+  {   5, "authenticationFailure" },
+  { 0, NULL }
+};
+
+
+static int
+dissect_snmp_ClosePDU_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_ClosePDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_APP, 1, TRUE, dissect_snmp_ClosePDU_U);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_INTEGER_M1_2147483647(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+static const value_string snmp_T_operation_vals[] = {
+  {   0, "delete" },
+  {   1, "readOnly" },
+  {   2, "readWrite" },
+  { 0, NULL }
+};
+
+
+static int
+dissect_snmp_T_operation(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+static const ber_sequence_t RReqPDU_U_sequence[] = {
+  { &hf_snmp_subtree        , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_snmp_ObjectName },
+  { &hf_snmp_priority       , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_M1_2147483647 },
+  { &hf_snmp_operation      , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_operation },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_RReqPDU_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   RReqPDU_U_sequence, hf_index, ett_snmp_RReqPDU_U);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_RReqPDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_APP, 2, TRUE, dissect_snmp_RReqPDU_U);
+
+  return offset;
+}
+
+
+static const value_string snmp_RRspPDU_U_vals[] = {
+  {  -1, "failure" },
+  { 0, NULL }
+};
+
+
+static int
+dissect_snmp_RRspPDU_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_RRspPDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_APP, 3, TRUE, dissect_snmp_RRspPDU_U);
+
+  return offset;
+}
+
+
+static const value_string snmp_RegisterResponse_vals[] = {
+  {   0, "rRspPDU" },
+  {   1, "pDUs" },
+  { 0, NULL }
+};
+
+static const ber_choice_t RegisterResponse_choice[] = {
+  {   0, &hf_snmp_rRspPDU        , BER_CLASS_APP, 3, BER_FLAGS_NOOWNTAG, dissect_snmp_RRspPDU },
+  {   1, &hf_snmp_pDUs           , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG, dissect_snmp_PDUs },
+  { 0, NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_RegisterResponse(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_choice(actx, tree, tvb, offset,
+                                 RegisterResponse_choice, hf_index, ett_snmp_RegisterResponse,
+                                 NULL);
+
+  return offset;
+}
+
+
+static const value_string snmp_SOutPDU_U_vals[] = {
+  {   0, "commit" },
+  {   1, "rollback" },
+  { 0, NULL }
+};
+
+
+static int
+dissect_snmp_SOutPDU_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_snmp_SOutPDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
+                                      hf_index, BER_CLASS_APP, 4, TRUE, dissect_snmp_SOutPDU_U);
+
+  return offset;
+}
+
+
+static const value_string snmp_SMUX_PDUs_vals[] = {
+  {   0, "open" },
+  {   1, "close" },
+  {   2, "registerRequest" },
+  {   3, "registerResponse" },
+  {   4, "commitOrRollback" },
+  { 0, NULL }
+};
+
+static const ber_choice_t SMUX_PDUs_choice[] = {
+  {   0, &hf_snmp_open           , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG, dissect_snmp_OpenPDU },
+  {   1, &hf_snmp_close          , BER_CLASS_APP, 1, BER_FLAGS_NOOWNTAG, dissect_snmp_ClosePDU },
+  {   2, &hf_snmp_registerRequest, BER_CLASS_APP, 2, BER_FLAGS_NOOWNTAG, dissect_snmp_RReqPDU },
+  {   3, &hf_snmp_registerResponse, BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG, dissect_snmp_RegisterResponse },
+  {   4, &hf_snmp_commitOrRollback, BER_CLASS_APP, 4, BER_FLAGS_NOOWNTAG, dissect_snmp_SOutPDU },
+  { 0, NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_snmp_SMUX_PDUs(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_choice(actx, tree, tvb, offset,
+                                 SMUX_PDUs_choice, hf_index, ett_snmp_SMUX_PDUs,
+                                 NULL);
+
+  return offset;
+}
+
+/*--- PDUs ---*/
 
-       if (parameters_length < 1)
-               return;
-       proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
-           "contextSelector: %s", bytes_to_str(parameters, parameters_length));
+static void dissect_SMUX_PDUs_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {
+  asn1_ctx_t asn1_ctx;
+  asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
+  dissect_snmp_SMUX_PDUs(FALSE, tvb, 0, &asn1_ctx, tree, hf_snmp_SMUX_PDUs_PDU);
 }
 
+
+/*--- End of included file: packet-snmp-fn.c ---*/
+#line 1496 "../../asn1/snmp/packet-snmp-template.c"
+
+
 guint
 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, int proto, gint ett, gboolean is_tcp)
+                proto_tree *tree, int proto, gint ett, gboolean is_tcp)
 {
+
        guint length_remaining;
-       ASN1_SCK asn1;
-       int start;
-       gboolean def;
-       gboolean encrypted;
-       guint length;
+       gint8 class;
+       gboolean pc, ind = 0;
+       gint32 tag;
+       guint32 len;
        guint message_length;
-       guint global_length;
-
-       guint32 version;
-       guint32 msgid;
-       guint32 msgmax;
-       guint32 msgsec;
-       guint32 engineboots;
-       guint32 enginetime;
-
-       guchar *msgflags;
-       gchar *commustr;
-       guchar *community;
-       guchar *secparm;
-       guchar *cengineid;
-       guchar *cname;
-       guchar *cryptpdu;
-       guchar *aengineid;
-       guchar *username;
-       guchar *authpar;
-       guchar *privpar;
-       guint msgflags_length;
-       guint community_length;
-       guint secparm_length;
-       guint cengineid_length;
-       guint cname_length;
-       guint cryptpdu_length;
-       guint aengineid_length;
-       guint username_length;
-       guint authpar_length;
-       guint privpar_length;
-
-       guint pdu_type;
-       guint pdu_length;
+       int start_offset = offset;
+       guint32 version = 0;
+       tvbuff_t        *next_tvb;
 
        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;
+       asn1_ctx_t asn1_ctx;
+       asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
+
+
+       usm_p.msg_tvb = tvb;
+       usm_p.start_offset = tvb_offset_from_real_beginning(tvb);
+       usm_p.engine_tvb = NULL;
+       usm_p.user_tvb = NULL;
+       usm_p.auth_item = NULL;
+       usm_p.auth_tvb = NULL;
+       usm_p.auth_offset = 0;
+       usm_p.priv_tvb = NULL;
+       usm_p.user_assoc = NULL;
+       usm_p.authenticated = FALSE;
+       usm_p.encrypted = FALSE;
+       usm_p.boots = 0;
+       usm_p.time = 0;
+       usm_p.authOK = FALSE;
 
        /*
         * This will throw an exception if we don't have any data left.
@@ -1586,13 +2780,21 @@ dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
                 * This is TCP, and we should, and can, do reassembly.
                 *
                 * Is the "Sequence Of" header split across segment
-                * boundaries?  We requre at least 6 bytes for the
+                * boundaries?  We require at least 6 bytes for the
                 * header, which allows for a 4-byte length (ASN.1
                 * BER).
                 */
                if (length_remaining < 6) {
+                       /*
+                        * Yes.  Tell the TCP dissector where the data
+                        * for this message starts in the data it handed
+                        * us and that we need "some more data."  Don't tell
+                        * it exactly how many bytes we need because if/when
+                        * we ask for even more (after the header) that will
+                        * break reassembly.
+                        */
                        pinfo->desegment_offset = offset;
-                       pinfo->desegment_len = 6 - length_remaining;
+                       pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
 
                        /*
                         * Return 0, which means "I didn't dissect anything
@@ -1607,46 +2809,15 @@ dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
         * OK, try to read the "Sequence Of" header; this gets the total
         * length of the SNMP message.
         */
-       asn1_open(&asn1, tvb, offset);
-       ret = asn1_sequence_decode(&asn1, &message_length, &length);
-       if (ret != ASN1_ERR_NOERROR) {
-               if (tree) {
-                       item = proto_tree_add_item(tree, proto, tvb, offset,
-                           -1, FALSE);
-                       snmp_tree = proto_item_add_subtree(item, ett);
-               }
-               dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                       "message header", ret);
-
-               /*
-                * Return the length remaining in the tvbuff, so
-                * if this is SNMP-over-TCP, our caller thinks there's
-                * nothing left to dissect.
-                */
-               return length_remaining;
-       }
+       /* Set tree to 0 to not display internal BER fields if option used.*/
+       offset = dissect_ber_identifier(pinfo, 0, tvb, offset, &class, &pc, &tag);
+       /*Get the total octet length of the SNMP data*/
+       offset = dissect_ber_length(pinfo, 0, tvb, offset, &len, &ind);
+       message_length = len + 2;
 
-       /*
-        * Add the length of the "Sequence Of" header to the message
-        * length.
-        */
-       message_length += length;
-       if (message_length < length) {
-               /*
-                * The message length was probably so large that the
-                * total length overflowed.
-                *
-                * Report this as an error.
-                */
-               show_reported_bounds_error(tvb, pinfo, tree);
+       /*Get the SNMP version data*/
+       offset = dissect_ber_integer(FALSE, &asn1_ctx, 0, tvb, offset, -1, &version);
 
-               /*
-                * Return the length remaining in the tvbuff, so
-                * if this is SNMP-over-TCP, our caller thinks there's
-                * nothing left to dissect.
-                */
-               return length_remaining;
-       }
 
        /*
         * If this is SNMP-over-TCP, we might have to do reassembly
@@ -1663,9 +2834,9 @@ dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
                         * us, and how many more bytes we need, and
                         * return.
                         */
-                       pinfo->desegment_offset = offset;
+                       pinfo->desegment_offset = start_offset;
                        pinfo->desegment_len =
-                           message_length - length_remaining;
+                       message_length - length_remaining;
 
                        /*
                         * Return 0, which means "I didn't dissect anything
@@ -1676,626 +2847,100 @@ dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
                }
        }
 
-       if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
-               col_set_str(pinfo->cinfo, COL_PROTOCOL,
-                   proto_get_protocol_short_name(find_protocol_by_id(proto)));
-       }
+       next_tvb_init(&var_list);
+
+       col_set_str(pinfo->cinfo, COL_PROTOCOL,
+           proto_get_protocol_short_name(find_protocol_by_id(proto)));
 
        if (tree) {
-               item = proto_tree_add_item(tree, proto, tvb, offset,
-                   message_length, FALSE);
+               item = proto_tree_add_item(tree, proto, tvb, start_offset,
+                                          message_length, ENC_BIG_ENDIAN);
                snmp_tree = proto_item_add_subtree(item, ett);
        }
-       offset += length;
-
-       ret = asn1_uint32_decode (&asn1, &version, &length);
-       if (ret != ASN1_ERR_NOERROR) {
-               dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                   "version number", ret);
-               return message_length;
-       }
-       if (snmp_tree) {
-               proto_tree_add_uint(snmp_tree, hf_snmp_version, tvb, offset,
-                   length, version);
-       }
-       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) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                           "community", ret);
-                       return message_length;
-               }
-               if (tree) {
-                       commustr = g_malloc(community_length+1);
-                       memcpy(commustr, community, community_length);
-                       commustr[community_length] = '\0';
-
-                       proto_tree_add_string(snmp_tree, hf_snmp_community,
-                           tvb, offset, length, commustr);
-                       g_free(commustr);
-               }
-               g_free(community);
-               offset += length;
+       case 0: /* v1 */
+       case 1: /* v2c */
+               offset = dissect_snmp_Message(FALSE , tvb, start_offset, &asn1_ctx, snmp_tree, -1);
                break;
-       case SNMP_VERSION_2u:
-               ret = asn1_octet_string_decode (&asn1, &community,
-                   &community_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                               "community (2u)", ret);
-                       return message_length;
-               }
-               if (tree) {
-                       dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
-                           community, community_length);
-               }
-               g_free(community);
-               offset += length;
+       case 2: /* v2u */
+               offset = dissect_snmp_Messagev2u(FALSE , tvb, start_offset, &asn1_ctx, snmp_tree, -1);
                break;
-       case SNMP_VERSION_3:
-               ret = asn1_sequence_decode(&asn1, &global_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                               "message global header", ret);
-                       return message_length;
-               }
-               if (snmp_tree) {
-                       item = proto_tree_add_text(snmp_tree, tvb, offset,
-                           global_length + length, "Message Global Header");
-                       global_tree = proto_item_add_subtree(item, ett_global);
-                       proto_tree_add_text(global_tree, tvb, offset,
-                           length,
-                           "Message Global Header Length: %d", global_length);
-               }
-               offset += length;
-               ret = asn1_uint32_decode (&asn1, &msgid, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                           "message id", ret);
-                       return message_length;
-               }
-               if (global_tree) {
-                       proto_tree_add_text(global_tree, tvb, offset,
-                           length, "Message ID: %d", msgid);
-               }
-               offset += length;
-               ret = asn1_uint32_decode (&asn1, &msgmax, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                           "message max size", ret);
-                       return message_length;
-               }
-               if (global_tree) {
-                       proto_tree_add_text(global_tree, tvb, offset,
-                           length, "Message Max Size: %d", msgmax);
-               }
-               offset += length;
-               ret = asn1_octet_string_decode (&asn1, &msgflags,
-                   &msgflags_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                           "message flags", ret);
-                       return message_length;
-               }
-               if (msgflags_length != 1) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                           "message flags wrong length", ret);
-                       g_free(msgflags);
-                       return message_length;
-               }
-               if (global_tree) {
-                       item = proto_tree_add_uint_format(global_tree,
-                           hf_snmpv3_flags, tvb, offset, length,
-                           msgflags[0], "Flags: 0x%02x", msgflags[0]);
-                       flags_tree = proto_item_add_subtree(item, ett_flags);
-                       proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
-                           tvb, offset, length, msgflags[0]);
-                       proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
-                           tvb, offset, length, msgflags[0]);
-                       proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
-                           tvb, offset, length, msgflags[0]);
-               }
-               encrypted = msgflags[0] & TH_CRYPT;
-               g_free(msgflags);
-               offset += length;
-               ret = asn1_uint32_decode (&asn1, &msgsec, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                           "message security model", ret);
-                       return message_length;
-               }
-               if (global_tree) {
-                       proto_tree_add_text(global_tree, tvb, offset,
-                           length, "Message Security Model: %s",
-                           val_to_str(msgsec, sec_models,
-                           "Unknown model %#x"));
-               }
-               offset += length;
-               switch(msgsec) {
-               case SNMP_SEC_USM:
-                       start = asn1.offset;
-                       ret = asn1_header_decode (&asn1, &cls, &con, &tag,
-                           &def, &secparm_length);
-                       length = asn1.offset - start;
-                       if (cls != ASN1_UNI && con != ASN1_PRI &&
-                           tag != ASN1_OTS) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree, "Message Security Parameters",
-                                   ASN1_ERR_WRONG_TYPE);
-                               return message_length;
-                       }
-                       if (snmp_tree) {
-                               item = proto_tree_add_text(snmp_tree, tvb,
-                                   offset, secparm_length + length,
-                                   "Message Security Parameters");
-                               secur_tree = proto_item_add_subtree(item,
-                                   ett_secur);
-                               proto_tree_add_text(secur_tree, tvb, offset,
-                                   length,
-                                   "Message Security Parameters Length: %d",
-                                   secparm_length);
-                       }
-                       offset += length;
-                       ret = asn1_sequence_decode(&asn1, &secparm_length,
-                           &length);
-                       if (ret != ASN1_ERR_NOERROR) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree, "USM sequence header", ret);
-                               return message_length;
-                       }
-                       offset += length;
-                       ret = asn1_octet_string_decode (&asn1, &aengineid,
-                           &aengineid_length, &length);
-                       if (ret != ASN1_ERR_NOERROR) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree, "authoritative engine id", ret);
-                               return message_length;
-                       }
-                       if (secur_tree) {
-                               proto_tree_add_text(secur_tree, tvb, offset,
-                                   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) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree, "engine boots", ret);
-                               return message_length;
-                       }
-                       if (secur_tree) {
-                               proto_tree_add_text(secur_tree, tvb,
-                                   offset, length, "Engine Boots: %d",
-                                   engineboots);
-                       }
-                       offset += length;
-                       ret = asn1_uint32_decode (&asn1, &enginetime, &length);
-                       if (ret != ASN1_ERR_NOERROR) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree,  "engine time", ret);
-                               return message_length;
-                       }
-                       if (secur_tree) {
-                               proto_tree_add_text(secur_tree, tvb,
-                                   offset, length, "Engine Time: %d",
-                                   enginetime);
-                       }
-                       offset += length;
-                       ret = asn1_octet_string_decode (&asn1, &username,
-                           &username_length, &length);
-                       if (ret != ASN1_ERR_NOERROR) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree, "user name", ret);
-                               return message_length;
-                       }
-                       if (secur_tree) {
-                               proto_tree_add_text(secur_tree, tvb, offset,
-                                   length, "User Name: %s",
-                                   SAFE_STRING(username, username_length));
-                       }
-                       g_free(username);
-                       offset += length;
-                       ret = asn1_octet_string_decode (&asn1, &authpar,
-                           &authpar_length, &length);
-                       if (ret != ASN1_ERR_NOERROR) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree, "authentication parameter", ret);
-                               return message_length;
-                       }
-                       if (secur_tree) {
-                               proto_tree_add_text(secur_tree, tvb, offset,
-                                   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) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree, "privacy parameter", ret);
-                               return message_length;
-                       }
-                       if (secur_tree) {
-                               proto_tree_add_text(secur_tree, tvb, offset,
-                                   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) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree, "Message Security Parameters",
-                                   ret);
-                               return message_length;
-                       }
-                       if (snmp_tree) {
-                               proto_tree_add_text(snmp_tree, tvb, offset,
-                                   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) {
-                               dissect_snmp_parse_error(tvb, offset, pinfo,
-                                   snmp_tree, "encrypted PDU header", ret);
-                               return message_length;
-                       }
-                       proto_tree_add_text(snmp_tree, tvb, offset, length,
-                           "Encrypted PDU (%d bytes)", length);
-                       g_free(cryptpdu);
-                       if (check_col(pinfo->cinfo, COL_INFO))
-                               col_set_str(pinfo->cinfo, COL_INFO, "Encrypted PDU");
-                       return message_length;
-               }
-               ret = asn1_sequence_decode(&asn1, &global_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                               "PDU header", ret);
-                       return message_length;
-               }
-               offset += length;
-               ret = asn1_octet_string_decode (&asn1, &cengineid,
-                   &cengineid_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                           "context engine id", ret);
-                       return message_length;
-               }
-               if (snmp_tree) {
-                       proto_tree_add_text(snmp_tree, tvb, offset, length,
-                           "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) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                           "context name", ret);
-                       return message_length;
-               }
-               if (snmp_tree) {
-                       proto_tree_add_text(snmp_tree, tvb, offset, length,
-                           "Context Name: %s",
-                           SAFE_STRING(cname, cname_length));
-               }
-               g_free(cname);
-               offset += length;
+                       /* v3 */
+       case 3:
+               offset = dissect_snmp_SNMPv3Message(FALSE , tvb, start_offset, &asn1_ctx, snmp_tree, -1);
                break;
        default:
-               dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
-                   "PDU for unknown version of SNMP");
-               return message_length;
+               /*
+                * Return the length remaining in the tvbuff, so
+                * if this is SNMP-over-TCP, our caller thinks there's
+                * nothing left to dissect.
+                */
+               proto_tree_add_text(snmp_tree, tvb, offset, -1,"Unknown version");
+               return length_remaining;
+               break;
        }
 
-       start = asn1.offset;
-       ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
-           &pdu_length);
-       if (ret != ASN1_ERR_NOERROR) {
-               dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                   "PDU type", ret);
-               return message_length;
-       }
-       if (cls != ASN1_CTX || con != ASN1_CON) {
-               dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
-                   "PDU type", ASN1_ERR_WRONG_TYPE);
-               return message_length;
+       /* There may be appended data after the SNMP data, so treat as raw
+        * data which needs to be dissected in case of UDP as UDP is PDU oriented.
+        */
+       if((!is_tcp) && (length_remaining > (guint)offset)) {
+               next_tvb = tvb_new_subset_remaining(tvb, offset);
+               call_dissector(data_handle, next_tvb, pinfo, tree);
+       } else {
+               next_tvb_call(&var_list, pinfo, tree, NULL, data_handle);
        }
-       dissect_common_pdu(tvb, offset, pinfo, snmp_tree, tree, asn1, pdu_type, start);
-       return message_length;
+
+       return offset;
 }
 
-static void
-dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
-    proto_tree *tree, int proto, gint ett)
+static gint
+dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       ASN1_SCK asn1;
-       int start;
-       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;
-       guint password_length;
-
-       guchar *application;
-       guint application_length;
-
-       subid_t *regid;
-       guint regid_length;
-
-       gchar *oid_string;
-
-       proto_tree *smux_tree = NULL;
-       proto_item *item = NULL;
-       int ret;
-       guint cls, con;
-
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
-
-       if (tree) {
-               item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
-               smux_tree = proto_item_add_subtree(item, ett);
-       }
+       conversation_t  *conversation;
+       int offset;
+       gint8 tmp_class;
+       gboolean tmp_pc;
+       gint32 tmp_tag;
+       guint32 tmp_length;
+       gboolean tmp_ind;
 
-       /* 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.
+       /*
+        * See if this looks like SNMP or not. if not, return 0 so
+        * wireshark can try som other dissector instead.
         */
-       /* parse the SNMP header */
-       asn1_open(&asn1, tvb, offset);
-       start = asn1.offset;
-       ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
-           &pdu_length);
-       if (ret != ASN1_ERR_NOERROR) {
-               dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                   "PDU type", ret);
-               return;
-       }
-
-       /* Dissect SMUX here */
-       if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
-               pdu_type_string = val_to_str(pdu_type, smux_types,
-                   "Unknown PDU type %#x");
-               if (check_col(pinfo->cinfo, COL_INFO))
-                       col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
-               length = asn1.offset - start;
-               if (tree) {
-                       proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
-                           offset, length, pdu_type);
-               }
-               offset += length;
-               ret = asn1_uint32_decode (&asn1, &version, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "version", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_uint(smux_tree, hf_smux_version, tvb,
-                           offset, length, version);
-               }
-               offset += length;
-
-               ret = asn1_oid_decode (&asn1, &regid, &regid_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "registration OID", ret);
-                       return;
-               }
-               if (tree) {
-                       oid_string = format_oid(regid, regid_length);
-                       proto_tree_add_text(smux_tree, tvb, offset, length,
-                           "Registration: %s", oid_string);
-                       g_free(oid_string);
-               }
-               g_free(regid);
-               offset += length;
-
-               ret = asn1_octet_string_decode (&asn1, &application,
-                   &application_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "application", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_text(smux_tree, tvb, offset, length,
-                           "Application: %s",
-                            SAFE_STRING(application, application_length));
-               }
-               g_free(application);
-               offset += length;
-
-               ret = asn1_octet_string_decode (&asn1, &password,
-                   &password_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "password", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_text(smux_tree, tvb, offset, length,
-                           "Password: %s",
-                           SAFE_STRING(password, password_length));
-               }
-               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");
-               if (check_col(pinfo->cinfo, COL_INFO))
-                       col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
-               length = asn1.offset - start;
-               if (tree) {
-                       proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
-                           offset, length, pdu_type);
-               }
-               offset += length;
-               ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "cause", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_text(smux_tree, tvb, offset,
-                           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");
-               if (check_col(pinfo->cinfo, COL_INFO))
-                       col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
-               length = asn1.offset - start;
-               if (tree) {
-                       proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
-                           offset, length, pdu_type);
-               }
-               offset += length;
-               ret = asn1_oid_decode (&asn1, &regid, &regid_length, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "registration subtree", ret);
-                       return;
-               }
-               if (tree) {
-                       oid_string = format_oid(regid, regid_length);
-                       proto_tree_add_text(smux_tree, tvb, offset, length,
-                           "Registration: %s", oid_string);
-                       g_free(oid_string);
-               }
-               g_free(regid);
-               offset += length;
-
-               ret = asn1_uint32_decode (&asn1, &priority, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "priority", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_text(smux_tree, tvb, offset, length,
-                           "Priority: %d", priority);
-               }
-               offset += length;
-
-               ret = asn1_uint32_decode (&asn1, &operation, &length);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "operation", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_text(smux_tree, tvb, offset, length,
-                           "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");
-               if (check_col(pinfo->cinfo, COL_INFO))
-                       col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
-               length = asn1.offset - start;
-               if (tree) {
-                       proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
-                           offset, length, pdu_type);
-               }
-               offset += length;
-               ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "priority", ret);
-                       return;
-               }
-               if (tree) {
-                       proto_tree_add_text(smux_tree, tvb, offset,
-                           pdu_length, "%s",
-                           val_to_str(priority, smux_prio,
-                               "Priority: %#x"));
-               }
-               offset += pdu_length;
-               return;
+       /* All SNMP packets are BER encoded and consist of a SEQUENCE
+        * that spans the entire PDU. The first item is an INTEGER that
+        * has the values 0-2 (version 1-3).
+        * if not it is not snmp.
+        */
+       /* SNMP starts with a SEQUENCE */
+       offset = get_ber_identifier(tvb, 0, &tmp_class, &tmp_pc, &tmp_tag);
+       if((tmp_class!=BER_CLASS_UNI)||(tmp_tag!=BER_UNI_TAG_SEQUENCE)) {
+               return 0;
        }
-       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");
-               if (check_col(pinfo->cinfo, COL_INFO))
-                       col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
-               length = asn1.offset - start;
-               if (tree) {
-                       proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
-                           offset, length, pdu_type);
-               }
-               offset += length;
-               ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
-               if (ret != ASN1_ERR_NOERROR) {
-                       dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                           "commit", ret);
-                       return;
+       /* then comes a length which spans the rest of the tvb */
+       offset = get_ber_length(tvb, offset, &tmp_length, &tmp_ind);
+       /* if(tmp_length!=(guint32)tvb_reported_length_remaining(tvb, offset)) {
+        * Losen the heuristic a bit to handle the case where data has intentionally
+        * been added after the snmp PDU ( UDP case)
+        */
+       if ( pinfo->ptype == PT_UDP ) {
+               if(tmp_length>(guint32)tvb_reported_length_remaining(tvb, offset)) {
+                       return 0;
                }
-               if (tree) {
-                       proto_tree_add_text(smux_tree, tvb, offset,
-                           pdu_length, "%s",
-                           val_to_str(commit, smux_sout,
-                               "Unknown SOUT Value: %#x"));
+       }else{
+               if(tmp_length!=(guint32)tvb_reported_length_remaining(tvb, offset)) {
+                       return 0;
                }
-               offset += pdu_length;
-               return;
        }
-       if (cls != ASN1_CTX || con != ASN1_CON) {
-               dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
-                   "PDU type", ASN1_ERR_WRONG_TYPE);
-               return;
+       /* then comes an INTEGER (version)*/
+       get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
+       if((tmp_class!=BER_CLASS_UNI)||(tmp_tag!=BER_UNI_TAG_INTEGER)) {
+               return 0;
        }
-       dissect_common_pdu(tvb, offset, pinfo, smux_tree, tree, asn1, pdu_type, start);
-}
+       /* do we need to test that version is 0 - 2 (version1-3) ? */
 
-static void
-dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-       conversation_t  *conversation;
 
        /*
         * The first SNMP packet goes to the SNMP port; the second one
@@ -2316,16 +2961,16 @@ dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         * wildcarded, and give it the SNMP dissector as a dissector.
         */
        if (pinfo->destport == UDP_PORT_SNMP) {
-         conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
+         conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_UDP,
                                           pinfo->srcport, 0, NO_PORT_B);
-         if (conversation == NULL) {
-           conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
+         if( (conversation == NULL) || (conversation->dissector_handle!=snmp_handle) ) {
+           conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_UDP,
                                            pinfo->srcport, 0, NO_PORT2);
            conversation_set_dissector(conversation, snmp_handle);
          }
        }
 
-       dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_snmp, ett_snmp, FALSE);
+       return dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_snmp, ett_snmp, FALSE);
 }
 
 static void
@@ -2336,7 +2981,7 @@ dissect_snmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
                message_len = dissect_snmp_pdu(tvb, 0, pinfo, tree,
-                   proto_snmp, ett_snmp, TRUE);
+                                              proto_snmp, ett_snmp, TRUE);
                if (message_len == 0) {
                        /*
                         * We don't have all the data for that message,
@@ -2352,202 +2997,802 @@ dissect_snmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 static void
 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
+       proto_tree *smux_tree = NULL;
+       proto_item *item = NULL;
+
+       next_tvb_init(&var_list);
+
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
+
+       if (tree) {
+               item = proto_tree_add_item(tree, proto_smux, tvb, 0, -1, ENC_BIG_ENDIAN);
+               smux_tree = proto_item_add_subtree(item, ett_smux);
+       }
+
+       dissect_SMUX_PDUs_PDU(tvb, pinfo, smux_tree);
 }
 
+
+/*
+  MD5 Password to Key Algorithm
+  from RFC 3414 A.2.1
+*/
 static void
-process_prefs(void)
+snmp_usm_password_to_key_md5(const guint8 *password, guint passwordlen,
+                            const guint8 *engineID, guint   engineLength,
+                            guint8 *key)
 {
-#ifdef HAVE_SOME_SNMP
-       gchar *tmp_mib_modules;
-       static gboolean mibs_loaded = FALSE;
+       md5_state_t     MD;
+       guint8     *cp, password_buf[64];
+       guint32      password_index = 0;
+       guint32      count = 0, i;
+       guint8          key1[16];
+       md5_init(&MD);   /* initialize MD5 */
+
+       /**********************************************/
+       /* Use while loop until we've done 1 Megabyte */
+       /**********************************************/
+       while (count < 1048576) {
+               cp = password_buf;
+               for (i = 0; i < 64; i++) {
+                       /*************************************************/
+                       /* Take the next octet of the password, wrapping */
+                       /* to the beginning of the password as necessary.*/
+                       /*************************************************/
+                       *cp++ = password[password_index++ % passwordlen];
+               }
+               md5_append(&MD, password_buf, 64);
+               count += 64;
+       }
+       md5_finish(&MD, key1);          /* tell MD5 we're done */
+
+       /*****************************************************/
+       /* Now localize the key with the engineID and pass   */
+       /* through MD5 to produce final key                  */
+       /* We ignore invalid engineLengths here. More strict */
+       /* checking is done in snmp_users_update_cb.         */
+       /*****************************************************/
+
+       md5_init(&MD);
+       md5_append(&MD, key1, 16);
+       md5_append(&MD, engineID, engineLength);
+       md5_append(&MD, key1, 16);
+       md5_finish(&MD, key);
+
+       return;
+}
 
-       if (mibs_loaded) {
-               /*
-                * Unload the MIBs, as we'll be reloading them based on
-                * the current preference setting.
-                */
-               shutdown_mib(); /* unload MIBs */
+
+
+
+/*
+   SHA1 Password to Key Algorithm COPIED from RFC 3414 A.2.2
+ */
+
+static void
+snmp_usm_password_to_key_sha1(const guint8 *password, guint passwordlen,
+                             const guint8 *engineID, guint engineLength,
+                             guint8 *key)
+{
+       sha1_context     SH;
+       guint8     *cp, password_buf[64];
+       guint32      password_index = 0;
+       guint32      count = 0, i;
+
+       sha1_starts(&SH);   /* initialize SHA */
+
+       /**********************************************/
+       /* Use while loop until we've done 1 Megabyte */
+       /**********************************************/
+       while (count < 1048576) {
+               cp = password_buf;
+               for (i = 0; i < 64; i++) {
+                       /*************************************************/
+                       /* Take the next octet of the password, wrapping */
+                       /* to the beginning of the password as necessary.*/
+                       /*************************************************/
+                       *cp++ = password[password_index++ % passwordlen];
+               }
+               sha1_update (&SH, password_buf, 64);
+               count += 64;
        }
+       sha1_finish(&SH, key);
 
-       /*
-        * Cannot check if MIBS is already set, as it could be set by Ethereal.
-        *
-        * If we have a list of modules to load, put that list in MIBS,
-        * otherwise clear MIBS.
-        */
-       if (mib_modules != NULL) {
-               tmp_mib_modules = g_strconcat("MIBS=", mib_modules, NULL);
+       /*****************************************************/
+       /* Now localize the key with the engineID and pass   */
+       /* through SHA to produce final key                  */
+       /* We ignore invalid engineLengths here. More strict */
+       /* checking is done in snmp_users_update_cb.         */
+       /*****************************************************/
 
-#ifdef _WIN32
-               _putenv(tmp_mib_modules);
-#else
-               putenv(tmp_mib_modules);
-#endif /*_WIN32*/
-       } else {
-#ifdef _WIN32
-               _putenv("MIBS");
-#else
-               putenv("MIBS");
-#endif  /* _WIN32 */
+       sha1_starts(&SH);
+       sha1_update(&SH, key, 20);
+       sha1_update(&SH, engineID, engineLength);
+       sha1_update(&SH, key, 20);
+       sha1_finish(&SH, key);
+       return;
+ }
+
+
+static void
+process_prefs(void)
+{
+}
+
+static void*
+snmp_users_copy_cb(void* dest, const void* orig, size_t len _U_)
+{
+       const snmp_ue_assoc_t* o = orig;
+       snmp_ue_assoc_t* d = dest;
+
+       d->auth_model = o->auth_model;
+       d->user.authModel = auth_models[o->auth_model];
+
+       d->priv_proto = o->priv_proto;
+       d->user.privProtocol = priv_protos[o->priv_proto];
+
+       d->user.userName.data = g_memdup(o->user.userName.data,o->user.userName.len);
+       d->user.userName.len = o->user.userName.len;
+
+       d->user.authPassword.data = o->user.authPassword.data ? g_memdup(o->user.authPassword.data,o->user.authPassword.len) : NULL;
+       d->user.authPassword.len = o->user.authPassword.len;
+
+       d->user.privPassword.data = o->user.privPassword.data ? g_memdup(o->user.privPassword.data,o->user.privPassword.len) : NULL;
+       d->user.privPassword.len = o->user.privPassword.len;
+
+       d->engine.len = o->engine.len;
+       if (o->engine.data) {
+               d->engine.data = g_memdup(o->engine.data,o->engine.len);
        }
 
-       /*
-        * Load the MIBs.
-        */
-       register_mib_handlers();
-       read_premib_configs();
-       init_mib();
-       read_configs();
-       mibs_loaded = TRUE;
-#endif /* HAVE_SOME_SNMP */
+       d->user.authKey.data = o->user.authKey.data ? g_memdup(o->user.authKey.data,o->user.authKey.len) : NULL;
+       d->user.authKey.len = o->user.authKey.len;
+
+       d->user.privKey.data = o->user.privKey.data ? g_memdup(o->user.privKey.data,o->user.privKey.len) : NULL;
+       d->user.privKey.len = o->user.privKey.len;
+
+       return d;
 }
 
-void
-proto_register_snmp(void)
+static void
+snmp_users_free_cb(void* p)
 {
-#if defined(_WIN32) && defined(HAVE_SOME_SNMP)
-       char *mib_path;
-#define MIB_PATH_APPEND "snmp\\mibs"
-#endif
-       gchar *tmp_mib_modules;
+       snmp_ue_assoc_t* ue = p;
+       g_free(ue->user.userName.data);
+       g_free(ue->user.authPassword.data);
+       g_free(ue->user.privPassword.data);
+       g_free(ue->user.authKey.data);
+       g_free(ue->user.privKey.data);
+       g_free(ue->engine.data);
+}
 
-       static hf_register_info hf[] = {
-               { &hf_snmp_version,
-               { "Version", "snmp.version", FT_UINT8, BASE_DEC, VALS(versions),
-                   0x0, "", HFILL }},
-               { &hf_snmp_community,
-               { "Community", "snmp.community", FT_STRING, BASE_NONE, NULL,
-                   0x0, "", HFILL }},
-               { &hf_snmp_request_id,
-               { "Request Id", "snmp.id", FT_UINT32, BASE_HEX, NULL,
-                   0x0, "Id for this transaction", HFILL }},
-               { &hf_snmp_pdutype,
-               { "PDU type", "snmp.pdutype", FT_UINT8, BASE_DEC, VALS(pdu_types),
-                   0x0, "", HFILL }},
-               { &hf_snmp_agent,
-               { "Agent address", "snmp.agent", FT_IPv4, BASE_NONE, NULL,
-                   0x0, "", HFILL }},
-               { &hf_snmp_enterprise,
-               { "Enterprise", "snmp.enterprise", FT_STRING, BASE_NONE, NULL,
-                   0x0, "", HFILL }},
-               { &hf_snmp_error_status,
-               { "Error Status", "snmp.error", FT_UINT8, BASE_DEC, VALS(error_statuses),
-                   0x0, "", HFILL }},
-               { &hf_snmp_oid,
-               { "Object identifier", "snmp.oid", FT_STRING, BASE_NONE, NULL,
-                   0x0, "", HFILL }},
-               { &hf_snmp_traptype,
-               { "Trap type", "snmp.traptype", FT_UINT8, BASE_DEC, VALS(trap_types),
-                   0x0, "", HFILL }},
-               { &hf_snmp_spectraptype,
-               { "Specific trap type", "snmp.spectraptype", FT_UINT32, BASE_DEC, NULL,
-                   0x0, "", HFILL }},
-               { &hf_snmp_timestamp,
-               { "Timestamp", "snmp.timestamp", FT_UINT8, BASE_DEC, NULL,
-                   0x0, "", HFILL }},
-               { &hf_snmpv3_flags,
-               { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
-                   0x0, "", HFILL }},
-               { &hf_snmpv3_flags_auth,
-               { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
-                   TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
-               { &hf_snmpv3_flags_crypt,
-               { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
-                   TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
-               { &hf_snmpv3_flags_report,
-               { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
-                   TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
-       };
-       static gint *ett[] = {
-               &ett_snmp,
-               &ett_parameters,
-               &ett_parameters_qos,
-               &ett_global,
-               &ett_flags,
-               &ett_secur,
-       };
-       module_t *snmp_module;
+static void
+snmp_users_update_cb(void* p _U_, const char** err)
+{
+       snmp_ue_assoc_t* ue = p;
+       GString* es = g_string_new("");
+       unsigned i;
 
-#ifdef HAVE_SOME_SNMP
+       *err = NULL;
 
-#ifdef _WIN32
-       /* Set MIBDIRS so that the SNMP library can find its mibs. */
-       /* XXX - Should we set MIBS or MIBFILES as well? */
+       if (num_ueas == 0)
+               /* Nothing to update */
+               return;
 
-       mib_path = g_malloc (strlen(get_datafile_dir()) + strlen(MIB_PATH_APPEND) + 20);
-       sprintf (mib_path, "MIBDIRS=%s\\%s", get_datafile_dir(), MIB_PATH_APPEND);
-       /* Amazingly enough, Windows does not provide setenv(). */
-       if (getenv("MIBDIRS") == NULL)
-               _putenv(mib_path);
-       g_free(mib_path);
+       if (! ue->user.userName.len)
+               g_string_append_printf(es,"no userName\n");
 
-#endif /* _WIN32 */
+       for (i=0; i<num_ueas-1; i++) {
+               snmp_ue_assoc_t* u = &(ueas[i]);
 
-       /*
-        * Suppress warnings about unknown tokens - we aren't initializing
-        * UCD SNMP in its entirety, we're just initializing the
-        * MIB-handling part because that's all we're using, which
-        * means that entries in the configuration file for other
-        * pars of the library will not be handled, and we don't want
-        * the config file reading code to whine about that.
-        */
-       netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
-                               NETSNMP_DS_LIB_NO_TOKEN_WARNINGS, TRUE);
-       netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
-                           NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 2);
-#endif /* HAVE_SOME_SNMP */
-       proto_snmp = proto_register_protocol("Simple Network Management Protocol",
-           "SNMP", "snmp");
-       proto_register_field_array(proto_snmp, hf, array_length(hf));
-       proto_register_subtree_array(ett, array_length(ett));
-       register_dissector("snmp", dissect_snmp, proto_snmp);
+               /* RFC 3411 section 5 */
+               if ((u->engine.len > 0) && (u->engine.len < 5 || u->engine.len > 32)) {
+                       g_string_append_printf(es, "Invalid engineId length (%u). Must be between 5 and 32 (10 and 64 hex digits)\n", u->engine.len);
+               }
 
-       /* Register configuration preferences */
-       snmp_module = prefs_register_protocol(proto_snmp, process_prefs);
-       prefs_register_bool_preference(snmp_module, "display_oid",
-               "Show SNMP OID in info column",
-               "Whether the SNMP OID should be shown in the info column",
-               &display_oid);
 
-       /*
-        * Set the default value of "mib_modules".
-        *
-        * If the MIBS environment variable is set, make its value
-        * the value of "mib_modules", otherwise, set "mib_modules"
-        * to DEF_MIB_MODULES.
-        */
-       tmp_mib_modules = getenv("MIBS");
-       if (tmp_mib_modules != NULL)
-               mib_modules = tmp_mib_modules;
-       prefs_register_string_preference(snmp_module, "mib_modules",
-           "MIB modules to load",
-           "List of MIB modules to load (the list is set to environment variable MIBS if the variable is not already set)",
-           &mib_modules);
-       prefs_register_bool_preference(snmp_module, "desegment",
-           "Reassemble SNMP-over-TCP messages\nspanning multiple TCP segments",
-           "Whether the SNMP dissector should reassemble messages spanning multiple TCP segments."
-           " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
-           &snmp_desegment);
+               if ( u->user.userName.len == ue->user.userName.len
+                       && u->engine.len == ue->engine.len ) {
+
+                       if (u->engine.len > 0 && memcmp( u->engine.data,   ue->engine.data,  u->engine.len ) == 0) {
+                               if ( memcmp( u->user.userName.data, ue->user.userName.data, ue->user.userName.len ) == 0 ) {
+                                       /* XXX: make a string for the engineId */
+                                       g_string_append_printf(es,"Duplicate key (userName='%s')\n",ue->user.userName.data);
+                               }
+                       }
+
+                       if (u->engine.len == 0) {
+                               if ( memcmp( u->user.userName.data, ue->user.userName.data, ue->user.userName.len ) == 0 ) {
+                                       g_string_append_printf(es,"Duplicate key (userName='%s' engineId=NONE)\n",ue->user.userName.data);
+                               }
+                       }
+               }
+       }
+
+       if (es->len) {
+               g_string_truncate(es,es->len-1);
+               *err = ep_strdup(es->str);
+       }
+
+       g_string_free(es,TRUE);
+
+       return;
 }
 
-void
-proto_reg_handoff_snmp(void)
+
+UAT_LSTRING_CB_DEF(snmp_users,userName,snmp_ue_assoc_t,user.userName.data,user.userName.len)
+UAT_LSTRING_CB_DEF(snmp_users,authPassword,snmp_ue_assoc_t,user.authPassword.data,user.authPassword.len)
+UAT_LSTRING_CB_DEF(snmp_users,privPassword,snmp_ue_assoc_t,user.privPassword.data,user.privPassword.len)
+UAT_BUFFER_CB_DEF(snmp_users,engine_id,snmp_ue_assoc_t,engine.data,engine.len)
+UAT_VS_DEF(snmp_users,auth_model,snmp_ue_assoc_t,0,"MD5")
+UAT_VS_DEF(snmp_users,priv_proto,snmp_ue_assoc_t,0,"DES")
+
+static void *
+snmp_specific_trap_copy_cb(void *dest, const void *orig, size_t len _U_)
+{
+       snmp_st_assoc_t *u = dest;
+       const snmp_st_assoc_t *o = orig;
+
+       u->enterprise = g_strdup(o->enterprise);
+       u->trap = o->trap;
+       u->desc = g_strdup(o->desc);
+
+       return dest;
+}
+
+static void
+snmp_specific_trap_free_cb(void *r)
 {
+       snmp_st_assoc_t *u = r;
+
+       g_free(u->enterprise);
+       g_free(u->desc);
+}
+
+UAT_CSTRING_CB_DEF(specific_traps, enterprise, snmp_st_assoc_t)
+UAT_DEC_CB_DEF(specific_traps, trap, snmp_st_assoc_t)
+UAT_CSTRING_CB_DEF(specific_traps, desc, snmp_st_assoc_t)
+
+       /*--- proto_register_snmp -------------------------------------------*/
+void proto_register_snmp(void) {
+  /* List of fields */
+  static hf_register_info hf[] = {
+               { &hf_snmp_v3_flags_auth,
+               { "Authenticated", "snmp.v3.flags.auth", FT_BOOLEAN, 8,
+                   TFS(&tfs_set_notset), TH_AUTH, NULL, HFILL }},
+               { &hf_snmp_v3_flags_crypt,
+               { "Encrypted", "snmp.v3.flags.crypt", FT_BOOLEAN, 8,
+                   TFS(&tfs_set_notset), TH_CRYPT, NULL, HFILL }},
+               { &hf_snmp_v3_flags_report,
+               { "Reportable", "snmp.v3.flags.report", FT_BOOLEAN, 8,
+                   TFS(&tfs_set_notset), TH_REPORT, NULL, HFILL }},
+               { &hf_snmp_engineid_conform, {
+                   "Engine ID Conformance", "snmp.engineid.conform", FT_BOOLEAN, 8,
+                   TFS(&tfs_snmp_engineid_conform), F_SNMP_ENGINEID_CONFORM, "Engine ID RFC3411 Conformance", HFILL }},
+               { &hf_snmp_engineid_enterprise, {
+                   "Engine Enterprise ID", "snmp.engineid.enterprise", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
+                   &sminmpec_values_ext, 0, NULL, HFILL }},
+               { &hf_snmp_engineid_format, {
+                   "Engine ID Format", "snmp.engineid.format", FT_UINT8, BASE_DEC,
+                   VALS(snmp_engineid_format_vals), 0, NULL, HFILL }},
+               { &hf_snmp_engineid_ipv4, {
+                   "Engine ID Data: IPv4 address", "snmp.engineid.ipv4", FT_IPv4, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_engineid_ipv6, {
+                   "Engine ID Data: IPv6 address", "snmp.engineid.ipv6", FT_IPv6, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_engineid_cisco_type, {
+                   "Engine ID Data: Cisco type", "snmp.engineid.cisco.type", FT_UINT8, BASE_NONE,
+                   VALS(snmp_engineid_cisco_type_vals), 0, NULL, HFILL }},
+               { &hf_snmp_engineid_mac, {
+                   "Engine ID Data: MAC address", "snmp.engineid.mac", FT_ETHER, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_engineid_text, {
+                   "Engine ID Data: Text", "snmp.engineid.text", FT_STRING, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_engineid_time, {
+                   "Engine ID Data: Creation Time", "snmp.engineid.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_engineid_data, {
+                   "Engine ID Data", "snmp.engineid.data", FT_BYTES, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_msgAuthentication, {
+                   "Authentication", "snmp.v3.auth", FT_BOOLEAN, BASE_NONE,
+                   TFS(&auth_flags), 0, NULL, HFILL }},
+               { &hf_snmp_decryptedPDU, {
+                   "Decrypted ScopedPDU", "snmp.decrypted_pdu", FT_BYTES, BASE_NONE,
+                   NULL, 0, "Decrypted PDU", HFILL }},
+               { &hf_snmp_noSuchObject, {
+                   "noSuchObject", "snmp.noSuchObject", FT_NONE, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_noSuchInstance, {
+                   "noSuchInstance", "snmp.noSuchInstance", FT_NONE, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_endOfMibView, {
+                   "endOfMibView", "snmp.endOfMibView", FT_NONE, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_unSpecified, {
+                   "unSpecified", "snmp.unSpecified", FT_NONE, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+
+               { &hf_snmp_integer32_value, {
+                   "Value (Integer32)", "snmp.value.int", FT_INT64, BASE_DEC,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_octetstring_value, {
+                   "Value (OctetString)", "snmp.value.octets", FT_BYTES, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_oid_value, {
+                   "Value (OID)", "snmp.value.oid", FT_OID, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_null_value, {
+                   "Value (Null)", "snmp.value.null", FT_NONE, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_ipv4_value, {
+                   "Value (IpAddress)", "snmp.value.ipv4", FT_IPv4, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_ipv6_value, {
+                   "Value (IpAddress)", "snmp.value.ipv6", FT_IPv6, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_anyaddress_value, {
+                   "Value (IpAddress)", "snmp.value.addr", FT_BYTES, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_unsigned32_value, {
+                   "Value (Unsigned32)", "snmp.value.u32", FT_INT64, BASE_DEC,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_gauge32_value, {
+                   "Value (Gauge32)", "snmp.value.g32", FT_INT64, BASE_DEC,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_unknown_value, {
+                   "Value (Unknown)", "snmp.value.unk", FT_BYTES, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_counter_value, {
+                   "Value (Counter32)", "snmp.value.counter", FT_UINT64, BASE_DEC,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_big_counter_value, {
+                   "Value (Counter64)", "snmp.value.counter", FT_UINT64, BASE_DEC,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_nsap_value, {
+                   "Value (NSAP)", "snmp.value.nsap", FT_UINT64, BASE_DEC,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_timeticks_value, {
+                   "Value (Timeticks)", "snmp.value.timeticks", FT_UINT64, BASE_DEC,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_opaque_value, {
+                   "Value (Opaque)", "snmp.value.opaque", FT_BYTES, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_objectname, {
+                   "Object Name", "snmp.name", FT_OID, BASE_NONE,
+                   NULL, 0, NULL, HFILL }},
+               { &hf_snmp_scalar_instance_index, {
+                   "Scalar Instance Index", "snmp.name.index", FT_UINT64, BASE_DEC,
+                   NULL, 0, NULL, HFILL }},
+
+
+
+/*--- Included file: packet-snmp-hfarr.c ---*/
+#line 1 "../../asn1/snmp/packet-snmp-hfarr.c"
+    { &hf_snmp_SMUX_PDUs_PDU,
+      { "SMUX-PDUs", "snmp.SMUX_PDUs",
+        FT_UINT32, BASE_DEC, VALS(snmp_SMUX_PDUs_vals), 0,
+        NULL, HFILL }},
+    { &hf_snmp_version,
+      { "version", "snmp.version",
+        FT_INT32, BASE_DEC, VALS(snmp_Version_vals), 0,
+        NULL, HFILL }},
+    { &hf_snmp_community,
+      { "community", "snmp.community",
+        FT_STRING, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_data,
+      { "data", "snmp.data",
+        FT_UINT32, BASE_DEC, VALS(snmp_PDUs_vals), 0,
+        "PDUs", HFILL }},
+    { &hf_snmp_parameters,
+      { "parameters", "snmp.parameters",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        "OCTET_STRING", HFILL }},
+    { &hf_snmp_datav2u,
+      { "datav2u", "snmp.datav2u",
+        FT_UINT32, BASE_DEC, VALS(snmp_T_datav2u_vals), 0,
+        NULL, HFILL }},
+    { &hf_snmp_v2u_plaintext,
+      { "plaintext", "snmp.plaintext",
+        FT_UINT32, BASE_DEC, VALS(snmp_PDUs_vals), 0,
+        "PDUs", HFILL }},
+    { &hf_snmp_encrypted,
+      { "encrypted", "snmp.encrypted",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        "OCTET_STRING", HFILL }},
+    { &hf_snmp_msgAuthoritativeEngineID,
+      { "msgAuthoritativeEngineID", "snmp.msgAuthoritativeEngineID",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_msgAuthoritativeEngineBoots,
+      { "msgAuthoritativeEngineBoots", "snmp.msgAuthoritativeEngineBoots",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_msgAuthoritativeEngineTime,
+      { "msgAuthoritativeEngineTime", "snmp.msgAuthoritativeEngineTime",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_msgUserName,
+      { "msgUserName", "snmp.msgUserName",
+        FT_STRING, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_msgAuthenticationParameters,
+      { "msgAuthenticationParameters", "snmp.msgAuthenticationParameters",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_msgPrivacyParameters,
+      { "msgPrivacyParameters", "snmp.msgPrivacyParameters",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_msgVersion,
+      { "msgVersion", "snmp.msgVersion",
+        FT_INT32, BASE_DEC, VALS(snmp_Version_vals), 0,
+        "Version", HFILL }},
+    { &hf_snmp_msgGlobalData,
+      { "msgGlobalData", "snmp.msgGlobalData",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "HeaderData", HFILL }},
+    { &hf_snmp_msgSecurityParameters,
+      { "msgSecurityParameters", "snmp.msgSecurityParameters",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_msgData,
+      { "msgData", "snmp.msgData",
+        FT_UINT32, BASE_DEC, VALS(snmp_ScopedPduData_vals), 0,
+        "ScopedPduData", HFILL }},
+    { &hf_snmp_msgID,
+      { "msgID", "snmp.msgID",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "INTEGER_0_2147483647", HFILL }},
+    { &hf_snmp_msgMaxSize,
+      { "msgMaxSize", "snmp.msgMaxSize",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "INTEGER_484_2147483647", HFILL }},
+    { &hf_snmp_msgFlags,
+      { "msgFlags", "snmp.msgFlags",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_msgSecurityModel,
+      { "msgSecurityModel", "snmp.msgSecurityModel",
+        FT_UINT32, BASE_DEC, VALS(sec_models), 0,
+        NULL, HFILL }},
+    { &hf_snmp_plaintext,
+      { "plaintext", "snmp.plaintext",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "ScopedPDU", HFILL }},
+    { &hf_snmp_encryptedPDU,
+      { "encryptedPDU", "snmp.encryptedPDU",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_contextEngineID,
+      { "contextEngineID", "snmp.contextEngineID",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        "SnmpEngineID", HFILL }},
+    { &hf_snmp_contextName,
+      { "contextName", "snmp.contextName",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        "OCTET_STRING", HFILL }},
+    { &hf_snmp_get_request,
+      { "get-request", "snmp.get_request",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "GetRequest_PDU", HFILL }},
+    { &hf_snmp_get_next_request,
+      { "get-next-request", "snmp.get_next_request",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "GetNextRequest_PDU", HFILL }},
+    { &hf_snmp_get_response,
+      { "get-response", "snmp.get_response",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "GetResponse_PDU", HFILL }},
+    { &hf_snmp_set_request,
+      { "set-request", "snmp.set_request",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "SetRequest_PDU", HFILL }},
+    { &hf_snmp_trap,
+      { "trap", "snmp.trap",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "Trap_PDU", HFILL }},
+    { &hf_snmp_getBulkRequest,
+      { "getBulkRequest", "snmp.getBulkRequest",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "GetBulkRequest_PDU", HFILL }},
+    { &hf_snmp_informRequest,
+      { "informRequest", "snmp.informRequest",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "InformRequest_PDU", HFILL }},
+    { &hf_snmp_snmpV2_trap,
+      { "snmpV2-trap", "snmp.snmpV2_trap",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "SNMPv2_Trap_PDU", HFILL }},
+    { &hf_snmp_report,
+      { "report", "snmp.report",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "Report_PDU", HFILL }},
+    { &hf_snmp_request_id,
+      { "request-id", "snmp.request_id",
+        FT_INT32, BASE_DEC, NULL, 0,
+        "INTEGER", HFILL }},
+    { &hf_snmp_error_status,
+      { "error-status", "snmp.error_status",
+        FT_INT32, BASE_DEC, VALS(snmp_T_error_status_vals), 0,
+        NULL, HFILL }},
+    { &hf_snmp_error_index,
+      { "error-index", "snmp.error_index",
+        FT_INT32, BASE_DEC, NULL, 0,
+        "INTEGER", HFILL }},
+    { &hf_snmp_variable_bindings,
+      { "variable-bindings", "snmp.variable_bindings",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "VarBindList", HFILL }},
+    { &hf_snmp_bulkPDU_request_id,
+      { "request-id", "snmp.request_id",
+        FT_INT32, BASE_DEC, NULL, 0,
+        "Integer32", HFILL }},
+    { &hf_snmp_non_repeaters,
+      { "non-repeaters", "snmp.non_repeaters",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "INTEGER_0_2147483647", HFILL }},
+    { &hf_snmp_max_repetitions,
+      { "max-repetitions", "snmp.max_repetitions",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "INTEGER_0_2147483647", HFILL }},
+    { &hf_snmp_enterprise,
+      { "enterprise", "snmp.enterprise",
+        FT_OID, BASE_NONE, NULL, 0,
+        "EnterpriseOID", HFILL }},
+    { &hf_snmp_agent_addr,
+      { "agent-addr", "snmp.agent_addr",
+        FT_IPv4, BASE_NONE, NULL, 0,
+        "NetworkAddress", HFILL }},
+    { &hf_snmp_generic_trap,
+      { "generic-trap", "snmp.generic_trap",
+        FT_INT32, BASE_DEC, VALS(snmp_GenericTrap_vals), 0,
+        "GenericTrap", HFILL }},
+    { &hf_snmp_specific_trap,
+      { "specific-trap", "snmp.specific_trap",
+        FT_INT32, BASE_DEC, NULL, 0,
+        "SpecificTrap", HFILL }},
+    { &hf_snmp_time_stamp,
+      { "time-stamp", "snmp.time_stamp",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "TimeTicks", HFILL }},
+    { &hf_snmp_name,
+      { "name", "snmp.name",
+        FT_OID, BASE_NONE, NULL, 0,
+        "ObjectName", HFILL }},
+    { &hf_snmp_valueType,
+      { "valueType", "snmp.valueType",
+        FT_NONE, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_VarBindList_item,
+      { "VarBind", "snmp.VarBind",
+        FT_NONE, BASE_NONE, NULL, 0,
+        NULL, HFILL }},
+    { &hf_snmp_open,
+      { "open", "snmp.open",
+        FT_UINT32, BASE_DEC, VALS(snmp_OpenPDU_vals), 0,
+        "OpenPDU", HFILL }},
+    { &hf_snmp_close,
+      { "close", "snmp.close",
+        FT_INT32, BASE_DEC, VALS(snmp_ClosePDU_U_vals), 0,
+        "ClosePDU", HFILL }},
+    { &hf_snmp_registerRequest,
+      { "registerRequest", "snmp.registerRequest",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "RReqPDU", HFILL }},
+    { &hf_snmp_registerResponse,
+      { "registerResponse", "snmp.registerResponse",
+        FT_UINT32, BASE_DEC, VALS(snmp_RegisterResponse_vals), 0,
+        NULL, HFILL }},
+    { &hf_snmp_commitOrRollback,
+      { "commitOrRollback", "snmp.commitOrRollback",
+        FT_INT32, BASE_DEC, VALS(snmp_SOutPDU_U_vals), 0,
+        "SOutPDU", HFILL }},
+    { &hf_snmp_rRspPDU,
+      { "rRspPDU", "snmp.rRspPDU",
+        FT_INT32, BASE_DEC, VALS(snmp_RRspPDU_U_vals), 0,
+        NULL, HFILL }},
+    { &hf_snmp_pDUs,
+      { "pDUs", "snmp.pDUs",
+        FT_UINT32, BASE_DEC, VALS(snmp_PDUs_vals), 0,
+        NULL, HFILL }},
+    { &hf_snmp_smux_simple,
+      { "smux-simple", "snmp.smux_simple",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "SimpleOpen", HFILL }},
+    { &hf_snmp_smux_version,
+      { "smux-version", "snmp.smux_version",
+        FT_INT32, BASE_DEC, VALS(snmp_T_smux_version_vals), 0,
+        NULL, HFILL }},
+    { &hf_snmp_identity,
+      { "identity", "snmp.identity",
+        FT_OID, BASE_NONE, NULL, 0,
+        "OBJECT_IDENTIFIER", HFILL }},
+    { &hf_snmp_description,
+      { "description", "snmp.description",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        "DisplayString", HFILL }},
+    { &hf_snmp_password,
+      { "password", "snmp.password",
+        FT_BYTES, BASE_NONE, NULL, 0,
+        "OCTET_STRING", HFILL }},
+    { &hf_snmp_subtree,
+      { "subtree", "snmp.subtree",
+        FT_OID, BASE_NONE, NULL, 0,
+        "ObjectName", HFILL }},
+    { &hf_snmp_priority,
+      { "priority", "snmp.priority",
+        FT_INT32, BASE_DEC, NULL, 0,
+        "INTEGER_M1_2147483647", HFILL }},
+    { &hf_snmp_operation,
+      { "operation", "snmp.operation",
+        FT_INT32, BASE_DEC, VALS(snmp_T_operation_vals), 0,
+        NULL, HFILL }},
+
+/*--- End of included file: packet-snmp-hfarr.c ---*/
+#line 2148 "../../asn1/snmp/packet-snmp-template.c"
+  };
+
+  /* List of subtrees */
+  static gint *ett[] = {
+         &ett_snmp,
+         &ett_engineid,
+         &ett_msgFlags,
+         &ett_encryptedPDU,
+         &ett_decrypted,
+         &ett_authParameters,
+         &ett_internet,
+         &ett_varbind,
+         &ett_name,
+         &ett_value,
+         &ett_decoding_error,
+
+/*--- Included file: packet-snmp-ettarr.c ---*/
+#line 1 "../../asn1/snmp/packet-snmp-ettarr.c"
+    &ett_snmp_Message,
+    &ett_snmp_Messagev2u,
+    &ett_snmp_T_datav2u,
+    &ett_snmp_UsmSecurityParameters,
+    &ett_snmp_SNMPv3Message,
+    &ett_snmp_HeaderData,
+    &ett_snmp_ScopedPduData,
+    &ett_snmp_ScopedPDU,
+    &ett_snmp_PDUs,
+    &ett_snmp_PDU,
+    &ett_snmp_BulkPDU,
+    &ett_snmp_Trap_PDU_U,
+    &ett_snmp_VarBind,
+    &ett_snmp_VarBindList,
+    &ett_snmp_SMUX_PDUs,
+    &ett_snmp_RegisterResponse,
+    &ett_snmp_OpenPDU,
+    &ett_snmp_SimpleOpen_U,
+    &ett_snmp_RReqPDU_U,
+
+/*--- End of included file: packet-snmp-ettarr.c ---*/
+#line 2164 "../../asn1/snmp/packet-snmp-template.c"
+  };
+  module_t *snmp_module;
+
+  static uat_field_t users_fields[] = {
+         UAT_FLD_BUFFER(snmp_users,engine_id,"Engine ID","Engine-id for this entry (empty = any)"),
+         UAT_FLD_LSTRING(snmp_users,userName,"Username","The username"),
+         UAT_FLD_VS(snmp_users,auth_model,"Authentication model",auth_types,"Algorithm to be used for authentication."),
+         UAT_FLD_LSTRING(snmp_users,authPassword,"Password","The password used for authenticating packets for this entry"),
+         UAT_FLD_VS(snmp_users,priv_proto,"Privacy protocol",priv_types,"Algorithm to be used for privacy."),
+         UAT_FLD_LSTRING(snmp_users,privPassword,"Privacy password","The password used for encrypting packets for this entry"),
+         UAT_END_FIELDS
+  };
+
+  uat_t *assocs_uat = uat_new("SNMP Users",
+                             sizeof(snmp_ue_assoc_t),
+                             "snmp_users",
+                             TRUE,
+                             (void*)&ueas,
+                             &num_ueas,
+                             UAT_CAT_CRYPTO,
+                             "ChSNMPUsersSection",
+                             snmp_users_copy_cb,
+                             snmp_users_update_cb,
+                             snmp_users_free_cb,
+                             renew_ue_cache,
+                             users_fields);
+
+  static uat_field_t specific_traps_flds[] = {
+    UAT_FLD_CSTRING(specific_traps,enterprise,"Enterprise OID","Enterprise Object Identifier"),
+    UAT_FLD_DEC(specific_traps,trap,"Trap Id","The specific-trap value"),
+    UAT_FLD_CSTRING(specific_traps,desc,"Description","Trap type description"),
+    UAT_END_FIELDS
+  };
+
+  uat_t* specific_traps_uat = uat_new("SNMP Enterprise Specific Trap Types",
+                                      sizeof(snmp_st_assoc_t),
+                                      "snmp_specific_traps",
+                                      TRUE,
+                                      (void*) &specific_traps,
+                                      &num_specific_traps,
+                                      UAT_CAT_GENERAL,
+                                      "ChSNMPEnterpriseSpecificTrapTypes",
+                                      snmp_specific_trap_copy_cb,
+                                      NULL,
+                                      snmp_specific_trap_free_cb,
+                                                                         NULL,
+                                      specific_traps_flds);
+
+  /* Register protocol */
+  proto_snmp = proto_register_protocol(PNAME, PSNAME, PFNAME);
+  new_register_dissector("snmp", dissect_snmp, proto_snmp);
+
+  /* Register fields and subtrees */
+  proto_register_field_array(proto_snmp, hf, array_length(hf));
+  proto_register_subtree_array(ett, array_length(ett));
+
+
+  /* Register configuration preferences */
+  snmp_module = prefs_register_protocol(proto_snmp, process_prefs);
+  prefs_register_bool_preference(snmp_module, "display_oid",
+                       "Show SNMP OID in info column",
+                       "Whether the SNMP OID should be shown in the info column",
+                       &display_oid);
+
+  prefs_register_obsolete_preference(snmp_module, "mib_modules");
+  prefs_register_obsolete_preference(snmp_module, "users_file");
+
+  prefs_register_bool_preference(snmp_module, "desegment",
+                       "Reassemble SNMP-over-TCP messages\nspanning multiple TCP segments",
+                       "Whether the SNMP dissector should reassemble messages spanning multiple TCP segments."
+                       " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+                       &snmp_desegment);
+
+  prefs_register_bool_preference(snmp_module, "var_in_tree",
+                       "Display dissected variables inside SNMP tree",
+                       "ON - display dissected variables inside SNMP tree, OFF - display dissected variables in root tree after SNMP",
+                       &snmp_var_in_tree);
+
+  prefs_register_uat_preference(snmp_module, "users_table",
+                               "Users Table",
+                               "Table of engine-user associations used for authentication and decryption",
+                               assocs_uat);
+
+  prefs_register_uat_preference(snmp_module, "specific_traps_table",
+                               "Enterprise Specific Trap Types",
+                               "Table of enterprise specific-trap type descriptions",
+                               specific_traps_uat);
+
+#ifdef HAVE_LIBSMI
+  prefs_register_static_text_preference(snmp_module, "info_mibs",
+                                       "MIB settings can be changed in the Name Resolution preferences",
+                                       "MIB settings can be changed in the Name Resolution preferences");
+#endif
+
+  value_sub_dissectors_table = register_dissector_table("snmp.variable_oid","SNMP Variable OID", FT_STRING, BASE_NONE);
+
+  register_init_routine(renew_ue_cache);
+
+  register_ber_syntax_dissector("SNMP", proto_snmp, dissect_snmp_tcp);
+}
+
+
+/*--- proto_reg_handoff_snmp ---------------------------------------*/
+void proto_reg_handoff_snmp(void) {
        dissector_handle_t snmp_tcp_handle;
 
        snmp_handle = find_dissector("snmp");
 
-       dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
-       dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_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);
-       dissector_add("hpext.dxsap", HPEXT_SNMP, snmp_handle);
+       dissector_add_uint("udp.port", UDP_PORT_SNMP, snmp_handle);
+       dissector_add_uint("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
+       dissector_add_uint("udp.port", UDP_PORT_SNMP_PATROL, snmp_handle);
+       dissector_add_uint("ethertype", ETHERTYPE_SNMP, snmp_handle);
+       dissector_add_uint("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
+       dissector_add_uint("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
+       dissector_add_uint("hpext.dxsap", HPEXT_SNMP, snmp_handle);
 
        snmp_tcp_handle = create_dissector_handle(dissect_snmp_tcp, proto_snmp);
-       dissector_add("tcp.port", TCP_PORT_SNMP, snmp_tcp_handle);
-       dissector_add("tcp.port", TCP_PORT_SNMP_TRAP, snmp_tcp_handle);
+       dissector_add_uint("tcp.port", TCP_PORT_SNMP, snmp_tcp_handle);
+       dissector_add_uint("tcp.port", TCP_PORT_SNMP_TRAP, snmp_tcp_handle);
 
        data_handle = find_dissector("data");
 
@@ -2559,6 +3804,7 @@ proto_reg_handoff_snmp(void)
         * that all dissector preferences have been registered).
         */
        process_prefs();
+
 }
 
 void
@@ -2567,10 +3813,10 @@ proto_register_smux(void)
        static hf_register_info hf[] = {
                { &hf_smux_version,
                { "Version", "smux.version", FT_UINT8, BASE_DEC, NULL,
-                   0x0, "", HFILL }},
+                   0x0, NULL, HFILL }},
                { &hf_smux_pdutype,
                { "PDU type", "smux.pdutype", FT_UINT8, BASE_DEC, VALS(smux_types),
-                   0x0, "", HFILL }},
+                   0x0, NULL, HFILL }},
        };
        static gint *ett[] = {
                &ett_smux,
@@ -2581,9 +3827,6 @@ proto_register_smux(void)
        proto_register_field_array(proto_smux, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
 
-       variable_oid_dissector_table =
-           register_dissector_table("snmp.variable_oid",
-             "SNMP Variable OID", FT_STRING, BASE_NONE);
 }
 
 void
@@ -2592,5 +3835,5 @@ proto_reg_handoff_smux(void)
        dissector_handle_t smux_handle;
 
        smux_handle = create_dissector_handle(dissect_smux, proto_smux);
-       dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);
+       dissector_add_uint("tcp.port", TCP_PORT_SMUX, smux_handle);
 }