Add a const.
[obnox/wireshark/wip.git] / epan / dissectors / packet-snmp.c
1 /* Do not modify this file.                                                   */
2 /* It is created automatically by the ASN.1 to Wireshark dissector compiler   */
3 /* packet-snmp.c                                                              */
4 /* ../../tools/asn2wrs.py -b -p snmp -c ./snmp.cnf -s ./packet-snmp-template -D . snmp.asn */
5
6 /* Input file: packet-snmp-template.c */
7
8 #line 1 "packet-snmp-template.c"
9 /* packet-snmp.c
10  * Routines for SNMP (simple network management protocol)
11  * Copyright (C) 1998 Didier Jorand
12  *
13  * See RFC 1157 for SNMPv1.
14  *
15  * See RFCs 1901, 1905, and 1906 for SNMPv2c.
16  *
17  * See RFCs 1905, 1906, 1909, and 1910 for SNMPv2u [historic].
18  *
19  * See RFCs 2570-2576 for SNMPv3
20  * Updated to use the asn2wrs compiler made by Tomas Kukosa
21  * Copyright (C) 2005 - 2006 Anders Broman [AT] ericsson.com
22  *
23  * See RFC 3414 for User-based Security Model for SNMPv3
24  * See RFC 3826 for  (AES) Cipher Algorithm in the SNMP USM
25  * See RFC 2578 for Structure of Management Information Version 2 (SMIv2)
26  * Copyright (C) 2007 Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
27  *
28  * $Id$
29  *
30  * Wireshark - Network traffic analyzer
31  * By Gerald Combs <gerald@wireshark.org>
32  * Copyright 1998 Gerald Combs
33  *
34  * Some stuff from:
35  *
36  * GXSNMP -- An snmp mangament application
37  * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
38  * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
39  *
40  * This program is free software; you can redistribute it and/or
41  * modify it under the terms of the GNU General Public License
42  * as published by the Free Software Foundation; either version 2
43  * of the License, or (at your option) any later version.
44  *
45  * This program is distributed in the hope that it will be useful,
46  * but WITHOUT ANY WARRANTY; without even the implied warranty of
47  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
48  * GNU General Public License for more details.
49  *
50  * You should have received a copy of the GNU General Public License
51  * along with this program; if not, write to the Free Software
52  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
53  */
54
55 #define D(args) do {printf args; fflush(stdout); } while(0)
56
57 #ifdef HAVE_CONFIG_H
58 # include "config.h"
59 #endif
60
61 #include <stdio.h>
62 #include <string.h>
63 #include <ctype.h>
64
65 #include <glib.h>
66
67 #include <epan/packet.h>
68 #include <epan/strutil.h>
69 #include <epan/conversation.h>
70 #include "etypes.h"
71 #include <epan/prefs.h>
72 #include <epan/sminmpec.h>
73 #include <epan/emem.h>
74 #include <epan/next_tvb.h>
75 #include <epan/uat.h>
76 #include <epan/asn1.h>
77 #include "packet-ipx.h"
78 #include "packet-hpext.h"
79
80
81 #include "packet-ber.h"
82
83 #include "packet-snmp.h"
84
85 #include <epan/crypt/crypt-sha1.h>
86 #include <epan/crypt/crypt-md5.h>
87 #include <epan/expert.h>
88 #include <epan/report_err.h>
89 #include <epan/oids.h>
90
91
92 #ifdef HAVE_LIBGCRYPT
93 #ifdef _WIN32
94 #include <winposixtype.h>
95 #endif /* _WIN32 */
96 #include <gcrypt.h>
97 #endif
98
99 /* Take a pointer that may be null and return a pointer that's not null
100    by turning null pointers into pointers to the above null string,
101    and, if the argument pointer wasn't null, make sure we handle
102    non-printable characters in the string by escaping them. */
103 #define SAFE_STRING(s, l)       (((s) != NULL) ? format_text((s), (l)) : "")
104
105 #define PNAME  "Simple Network Management Protocol"
106 #define PSNAME "SNMP"
107 #define PFNAME "snmp"
108
109 #define UDP_PORT_SNMP           161
110 #define UDP_PORT_SNMP_TRAP      162
111 #define TCP_PORT_SNMP           161
112 #define TCP_PORT_SNMP_TRAP      162
113 #define TCP_PORT_SMUX           199
114 #define UDP_PORT_SNMP_PATROL 8161
115
116 /* Initialize the protocol and registered fields */
117 static int proto_snmp = -1;
118 static int proto_smux = -1;
119
120 static gboolean display_oid = TRUE;
121 static gboolean snmp_var_in_tree = TRUE;
122
123 static gboolean snmp_usm_auth_md5(snmp_usm_params_t* p, guint8**, guint*, gchar const**);
124 static gboolean snmp_usm_auth_sha1(snmp_usm_params_t* p, guint8**, guint*, gchar const**);
125
126 static tvbuff_t* snmp_usm_priv_des(snmp_usm_params_t*, tvbuff_t*, gchar const**);
127 static tvbuff_t* snmp_usm_priv_aes(snmp_usm_params_t*, tvbuff_t*, gchar const**);
128
129
130 static void snmp_usm_password_to_key_md5(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
131 static void snmp_usm_password_to_key_sha1(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
132
133
134 static snmp_usm_auth_model_t model_md5 = {snmp_usm_password_to_key_md5, snmp_usm_auth_md5, 16};
135 static snmp_usm_auth_model_t model_sha1 = {snmp_usm_password_to_key_sha1, snmp_usm_auth_sha1, 20};
136
137 static value_string auth_types[] = {
138         {0,"MD5"},
139         {1,"SHA1"},
140         {0,NULL}
141 };
142 static snmp_usm_auth_model_t* auth_models[] = {&model_md5,&model_sha1};
143
144
145 static value_string priv_types[] = {
146         {0,"DES"},
147         {1,"AES"},
148         {0,NULL}
149 };
150 static snmp_usm_decoder_t priv_protos[] = {snmp_usm_priv_des, snmp_usm_priv_aes};
151
152 static snmp_ue_assoc_t* ueas = NULL;
153 static guint num_ueas = 0;
154 static uat_t* assocs_uat = NULL;
155 static snmp_ue_assoc_t* localized_ues = NULL;
156 static snmp_ue_assoc_t* unlocalized_ues = NULL;
157 /****/
158
159
160
161 static snmp_usm_params_t usm_p = {FALSE,FALSE,0,0,0,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,FALSE};
162
163 #define TH_AUTH   0x01
164 #define TH_CRYPT  0x02
165 #define TH_REPORT 0x04
166
167 /* desegmentation of SNMP-over-TCP */
168 static gboolean snmp_desegment = TRUE;
169
170 /* Global variables */
171
172 guint32 MsgSecurityModel;
173 tvbuff_t *oid_tvb=NULL;
174 tvbuff_t *value_tvb=NULL;
175
176 static dissector_handle_t snmp_handle;
177 static dissector_handle_t data_handle;
178
179 static next_tvb_list_t var_list;
180
181 static int hf_snmp_v3_flags_auth = -1;
182 static int hf_snmp_v3_flags_crypt = -1;
183 static int hf_snmp_v3_flags_report = -1;
184
185 static int hf_snmp_engineid_conform = -1;
186 static int hf_snmp_engineid_enterprise = -1;
187 static int hf_snmp_engineid_format = -1;
188 static int hf_snmp_engineid_ipv4 = -1;
189 static int hf_snmp_engineid_ipv6 = -1;
190 static int hf_snmp_engineid_mac = -1;
191 static int hf_snmp_engineid_text = -1;
192 static int hf_snmp_engineid_time = -1;
193 static int hf_snmp_engineid_data = -1;
194 static int hf_snmp_decryptedPDU = -1;
195 static int hf_snmp_msgAuthentication = -1;
196
197 static int hf_snmp_noSuchObject = -1;
198 static int hf_snmp_noSuchInstance = -1;
199 static int hf_snmp_endOfMibView = -1;
200 static int hf_snmp_unSpecified = -1;
201
202 static int hf_snmp_integer32_value = -1;
203 static int hf_snmp_octetstring_value = -1;
204 static int hf_snmp_oid_value = -1;
205 static int hf_snmp_null_value = -1;
206 static int hf_snmp_ipv4_value = -1;
207 static int hf_snmp_ipv6_value = -1;
208 static int hf_snmp_anyaddress_value = -1;
209 static int hf_snmp_unsigned32_value = -1;
210 static int hf_snmp_unknown_value = -1;
211 static int hf_snmp_opaque_value = -1;
212 static int hf_snmp_nsap_value = -1;
213 static int hf_snmp_counter_value = -1;
214 static int hf_snmp_timeticks_value = -1;
215 static int hf_snmp_big_counter_value = -1;
216 static int hf_snmp_gauge32_value = -1;
217
218 static int hf_snmp_objectname = -1;
219 static int hf_snmp_scalar_instance_index = -1;
220
221
222
223 /*--- Included file: packet-snmp-hf.c ---*/
224 #line 1 "packet-snmp-hf.c"
225 static int hf_snmp_SMUX_PDUs_PDU = -1;            /* SMUX_PDUs */
226 static int hf_snmp_version = -1;                  /* Version */
227 static int hf_snmp_community = -1;                /* OCTET_STRING */
228 static int hf_snmp_data = -1;                     /* PDUs */
229 static int hf_snmp_parameters = -1;               /* OCTET_STRING */
230 static int hf_snmp_datav2u = -1;                  /* T_datav2u */
231 static int hf_snmp_v2u_plaintext = -1;            /* PDUs */
232 static int hf_snmp_encrypted = -1;                /* OCTET_STRING */
233 static int hf_snmp_msgAuthoritativeEngineID = -1;  /* T_msgAuthoritativeEngineID */
234 static int hf_snmp_msgAuthoritativeEngineBoots = -1;  /* T_msgAuthoritativeEngineBoots */
235 static int hf_snmp_msgAuthoritativeEngineTime = -1;  /* T_msgAuthoritativeEngineTime */
236 static int hf_snmp_msgUserName = -1;              /* T_msgUserName */
237 static int hf_snmp_msgAuthenticationParameters = -1;  /* T_msgAuthenticationParameters */
238 static int hf_snmp_msgPrivacyParameters = -1;     /* T_msgPrivacyParameters */
239 static int hf_snmp_msgVersion = -1;               /* Version */
240 static int hf_snmp_msgGlobalData = -1;            /* HeaderData */
241 static int hf_snmp_msgSecurityParameters = -1;    /* T_msgSecurityParameters */
242 static int hf_snmp_msgData = -1;                  /* ScopedPduData */
243 static int hf_snmp_msgID = -1;                    /* INTEGER_0_2147483647 */
244 static int hf_snmp_msgMaxSize = -1;               /* INTEGER_484_2147483647 */
245 static int hf_snmp_msgFlags = -1;                 /* T_msgFlags */
246 static int hf_snmp_msgSecurityModel = -1;         /* T_msgSecurityModel */
247 static int hf_snmp_plaintext = -1;                /* ScopedPDU */
248 static int hf_snmp_encryptedPDU = -1;             /* T_encryptedPDU */
249 static int hf_snmp_contextEngineID = -1;          /* SnmpEngineID */
250 static int hf_snmp_contextName = -1;              /* OCTET_STRING */
251 static int hf_snmp_get_request = -1;              /* GetRequest_PDU */
252 static int hf_snmp_get_next_request = -1;         /* GetNextRequest_PDU */
253 static int hf_snmp_get_response = -1;             /* GetResponse_PDU */
254 static int hf_snmp_set_request = -1;              /* SetRequest_PDU */
255 static int hf_snmp_trap = -1;                     /* Trap_PDU */
256 static int hf_snmp_getBulkRequest = -1;           /* GetBulkRequest_PDU */
257 static int hf_snmp_informRequest = -1;            /* InformRequest_PDU */
258 static int hf_snmp_sNMPv2_Trap = -1;              /* SNMPv2_Trap_PDU */
259 static int hf_snmp_report = -1;                   /* Report_PDU */
260 static int hf_snmp_request_id = -1;               /* INTEGER */
261 static int hf_snmp_error_status = -1;             /* T_error_status */
262 static int hf_snmp_error_index = -1;              /* INTEGER */
263 static int hf_snmp_variable_bindings = -1;        /* VarBindList */
264 static int hf_snmp_bulkPDU_request_id = -1;       /* Integer32 */
265 static int hf_snmp_non_repeaters = -1;            /* INTEGER_0_2147483647 */
266 static int hf_snmp_max_repetitions = -1;          /* INTEGER_0_2147483647 */
267 static int hf_snmp_enterprise = -1;               /* EnterpriseOID */
268 static int hf_snmp_agent_addr = -1;               /* NetworkAddress */
269 static int hf_snmp_generic_trap = -1;             /* T_generic_trap */
270 static int hf_snmp_specific_trap = -1;            /* INTEGER */
271 static int hf_snmp_time_stamp = -1;               /* TimeTicks */
272 static int hf_snmp_name = -1;                     /* ObjectName */
273 static int hf_snmp_valueType = -1;                /* NULL */
274 static int hf_snmp_VarBindList_item = -1;         /* VarBind */
275 static int hf_snmp_open = -1;                     /* OpenPDU */
276 static int hf_snmp_close = -1;                    /* ClosePDU */
277 static int hf_snmp_registerRequest = -1;          /* RReqPDU */
278 static int hf_snmp_registerResponse = -1;         /* RegisterResponse */
279 static int hf_snmp_commitOrRollback = -1;         /* SOutPDU */
280 static int hf_snmp_rRspPDU = -1;                  /* RRspPDU */
281 static int hf_snmp_pDUs = -1;                     /* PDUs */
282 static int hf_snmp_smux_simple = -1;              /* SimpleOpen */
283 static int hf_snmp_smux_version = -1;             /* T_smux_version */
284 static int hf_snmp_identity = -1;                 /* OBJECT_IDENTIFIER */
285 static int hf_snmp_description = -1;              /* DisplayString */
286 static int hf_snmp_password = -1;                 /* OCTET_STRING */
287 static int hf_snmp_subtree = -1;                  /* ObjectName */
288 static int hf_snmp_priority = -1;                 /* INTEGER_M1_2147483647 */
289 static int hf_snmp_operation = -1;                /* T_operation */
290
291 /*--- End of included file: packet-snmp-hf.c ---*/
292 #line 215 "packet-snmp-template.c"
293
294 static int hf_smux_version = -1;
295 static int hf_smux_pdutype = -1;
296
297 /* Initialize the subtree pointers */
298 static gint ett_smux = -1;
299 static gint ett_snmp = -1;
300 static gint ett_engineid = -1;
301 static gint ett_msgFlags = -1;
302 static gint ett_encryptedPDU = -1;
303 static gint ett_decrypted = -1;
304 static gint ett_authParameters = -1;
305 static gint ett_internet = -1;
306 static gint ett_varbind = -1;
307 static gint ett_name = -1;
308 static gint ett_value = -1;
309 static gint ett_decoding_error = -1;
310
311
312 /*--- Included file: packet-snmp-ett.c ---*/
313 #line 1 "packet-snmp-ett.c"
314 static gint ett_snmp_Message = -1;
315 static gint ett_snmp_Messagev2u = -1;
316 static gint ett_snmp_T_datav2u = -1;
317 static gint ett_snmp_UsmSecurityParameters = -1;
318 static gint ett_snmp_SNMPv3Message = -1;
319 static gint ett_snmp_HeaderData = -1;
320 static gint ett_snmp_ScopedPduData = -1;
321 static gint ett_snmp_ScopedPDU = -1;
322 static gint ett_snmp_PDUs = -1;
323 static gint ett_snmp_PDU = -1;
324 static gint ett_snmp_BulkPDU = -1;
325 static gint ett_snmp_Trap_PDU_U = -1;
326 static gint ett_snmp_VarBind = -1;
327 static gint ett_snmp_VarBindList = -1;
328 static gint ett_snmp_SMUX_PDUs = -1;
329 static gint ett_snmp_RegisterResponse = -1;
330 static gint ett_snmp_OpenPDU = -1;
331 static gint ett_snmp_SimpleOpen_U = -1;
332 static gint ett_snmp_RReqPDU_U = -1;
333
334 /*--- End of included file: packet-snmp-ett.c ---*/
335 #line 234 "packet-snmp-template.c"
336
337 static const true_false_string auth_flags = {
338         "OK",
339         "Failed"
340 };
341
342 /* Security Models */
343
344 #define SNMP_SEC_ANY                    0
345 #define SNMP_SEC_V1                             1
346 #define SNMP_SEC_V2C                    2
347 #define SNMP_SEC_USM                    3
348
349 static const value_string sec_models[] = {
350         { SNMP_SEC_ANY,                 "Any" },
351         { SNMP_SEC_V1,                  "V1" },
352         { SNMP_SEC_V2C,                 "V2C" },
353         { SNMP_SEC_USM,                 "USM" },
354         { 0,                            NULL }
355 };
356
357 /* SMUX PDU types */
358 #define SMUX_MSG_OPEN           0
359 #define SMUX_MSG_CLOSE          1
360 #define SMUX_MSG_RREQ           2
361 #define SMUX_MSG_RRSP           3
362 #define SMUX_MSG_SOUT           4
363
364 static const value_string smux_types[] = {
365         { SMUX_MSG_OPEN,        "Open" },
366         { SMUX_MSG_CLOSE,       "Close" },
367         { SMUX_MSG_RREQ,        "Registration Request" },
368         { SMUX_MSG_RRSP,        "Registration Response" },
369         { SMUX_MSG_SOUT,        "Commit Or Rollback" },
370         { 0,                    NULL }
371 };
372
373
374 #define SNMP_IPA    0           /* IP Address */
375 #define SNMP_CNT    1           /* Counter (Counter32) */
376 #define SNMP_GGE    2           /* Gauge (Gauge32) */
377 #define SNMP_TIT    3           /* TimeTicks */
378 #define SNMP_OPQ    4           /* Opaque */
379 #define SNMP_NSP    5           /* NsapAddress */
380 #define SNMP_C64    6           /* Counter64 */
381 #define SNMP_U32    7           /* Uinteger32 */
382
383 #define SERR_NSO    0
384 #define SERR_NSI    1
385 #define SERR_EOM    2
386
387
388 dissector_table_t value_sub_dissectors_table;
389
390 /*
391  *  dissect_snmp_VarBind
392  *  this routine dissects variable bindings, looking for the oid information in our oid reporsitory
393  *  to format and add the value adequatelly.
394  *
395  * The choice to handwrite this code instead of using the asn compiler is to avoid having tons
396  * of uses of global variables distributed in very different parts of the code.
397  * Other than that there's a cosmetic thing: the tree from ASN generated code would be so
398  * convoluted due to the nesting of CHOICEs in the definition of VarBind/value.
399  *
400  * XXX: the length of this function (~400 lines) is an aberration!
401  *  oid_key_t:key_type could become a series of callbacks instead of an enum
402  *  the (! oid_info_is_ok) switch could be made into an array (would be slower)
403  *
404
405         NetworkAddress ::=  CHOICE { internet IpAddress }
406         IpAddress ::= [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4))
407         TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
408         Integer32 ::= INTEGER (-2147483648..2147483647)
409         ObjectName ::= OBJECT IDENTIFIER
410         Counter32 ::= [APPLICATION 1] IMPLICIT INTEGER (0..4294967295)
411         Gauge32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
412         Unsigned32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
413         Integer-value ::=  INTEGER (-2147483648..2147483647)
414         Integer32 ::= INTEGER (-2147483648..2147483647)
415         ObjectID-value ::= OBJECT IDENTIFIER
416         Empty ::= NULL
417         TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
418         Opaque ::= [APPLICATION 4] IMPLICIT OCTET STRING
419         Counter64 ::= [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615)
420
421         ObjectSyntax ::= CHOICE {
422                  simple SimpleSyntax,
423                  application-wide ApplicationSyntax
424         }
425
426         SimpleSyntax ::= CHOICE {
427            integer-value Integer-value,
428            string-value String-value,
429            objectID-value ObjectID-value,
430            empty  Empty
431         }
432
433         ApplicationSyntax ::= CHOICE {
434            ipAddress-value IpAddress,
435            counter-value Counter32,
436            timeticks-value TimeTicks,
437            arbitrary-value Opaque,
438            big-counter-value Counter64,
439            unsigned-integer-value Unsigned32
440         }
441
442         ValueType ::=  CHOICE {
443            value ObjectSyntax,
444            unSpecified NULL,
445            noSuchObject[0] IMPLICIT NULL,
446            noSuchInstance[1] IMPLICIT NULL,
447            endOfMibView[2] IMPLICIT NULL
448         }
449
450         VarBind ::= SEQUENCE {
451            name ObjectName,
452            valueType ValueType
453         }
454
455  */
456
457 extern int dissect_snmp_VarBind(gboolean implicit_tag _U_,
458                                                                 tvbuff_t *tvb,
459                                                                 int offset,
460                                                                 asn1_ctx_t *actx,
461                                                                 proto_tree *tree,
462                                                                 int hf_index _U_) {
463         int seq_offset, name_offset, value_offset, value_start;
464         guint32 seq_len, name_len, value_len;
465         gint8 ber_class;
466         gboolean pc;
467         gint32 tag;
468         gboolean ind;
469         guint32* subids;
470         guint8* oid_bytes;
471         oid_info_t* oid_info = NULL;
472         guint oid_matched, oid_left;
473         proto_item *pi_name, *pi_varbind, *pi_value = NULL;
474         proto_tree *pt, *pt_varbind, *pt_name, *pt_value;
475         char label[ITEM_LABEL_LENGTH];
476         char* repr = NULL;
477         const char* info_oid = NULL;
478         char* valstr;
479         int hfid = -1;
480         int min_len = 0, max_len = 0;
481         gboolean oid_info_is_ok;
482         const char* oid_string = NULL;
483         enum {BER_NO_ERROR, BER_WRONG_LENGTH, BER_WRONG_TAG} format_error = BER_NO_ERROR;
484
485         seq_offset = offset;
486
487         /* first have the VarBind's sequence header */
488         offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
489         offset = get_ber_length(tvb, offset, &seq_len, &ind);
490
491         seq_len += offset - seq_offset;
492
493         if (!pc && ber_class==BER_CLASS_UNI && tag==BER_UNI_TAG_SEQUENCE) {
494                 proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"VarBind must be an universal class sequence");
495                 pt = proto_item_add_subtree(pi,ett_decoding_error);
496                 expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "VarBind is not an universal class sequence");
497                 return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
498         }
499
500         if (ind){
501                 proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"Indicator must be clear in VarBind");
502                 pt = proto_item_add_subtree(pi,ett_decoding_error);
503                 expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "VarBind has indicator set");
504                 return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
505         }
506
507         /* then we have the ObjectName's header */
508
509         offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
510         name_offset = offset = get_ber_length(tvb, offset, &name_len, &ind);
511
512         if (! ( !pc && ber_class==BER_CLASS_UNI && tag==BER_UNI_TAG_OID) ) {
513                 proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"ObjectName must be an OID in primitive encoding");
514                 pt = proto_item_add_subtree(pi,ett_decoding_error);
515                 expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "ObjectName not an OID");
516                 return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
517         }
518
519         if (ind){
520                 proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"Indicator must be clear in ObjectName");
521                 pt = proto_item_add_subtree(pi,ett_decoding_error);
522                 expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "ObjectName has indicator set");
523                 return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
524         }
525
526         offset += name_len;
527         value_start = offset;
528
529         /* then we have the  value's header */
530         offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
531         value_offset = offset = get_ber_length(tvb, offset, &value_len, &ind);
532
533         if (! (!pc) ) {
534                 proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"the value must be in primitive encoding");
535                 pt = proto_item_add_subtree(pi,ett_decoding_error);
536                 expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "value not in primitive encoding");
537                 return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
538         }
539
540         /* Now, we know where everithing is */
541
542
543
544         /* we add the varbind tree root with a dummy label we'll fill later on */
545         pi_varbind = proto_tree_add_text(tree,tvb,seq_offset,seq_len,"VarBind");
546         pt_varbind = proto_item_add_subtree(pi_varbind,ett_varbind);
547         *label = '\0';
548
549         pi_name = proto_tree_add_item(pt_varbind,hf_snmp_objectname,tvb,name_offset,name_len,FALSE);
550         pt_name = proto_item_add_subtree(pi_name,ett_name);
551
552         /* fetch ObjectName and its relative oid_info */
553         oid_bytes = ep_tvb_memdup(tvb, name_offset, name_len);
554         oid_info = oid_get_from_encoded(oid_bytes, name_len, &subids, &oid_matched, &oid_left);
555
556         add_oid_debug_subtree(oid_info,pt_name);
557
558         if (subids && oid_matched+oid_left) {
559                 oid_string = oid_subid2string(subids,oid_matched+oid_left);
560         }
561
562         if (ber_class == BER_CLASS_CON) {
563                 /* if we have an error value just add it and get out the way ASAP */
564                 proto_item* pi;
565                 const char* note;
566
567                 if (value_len != 0) {
568                         min_len = max_len = 0;
569                         format_error = BER_WRONG_LENGTH;
570                 }
571
572                 switch (tag) {
573                         case SERR_NSO:
574                                 hfid = hf_snmp_noSuchObject;
575                                 note = "noSuchObject";
576                                 break;
577                         case SERR_NSI:
578                                 hfid = hf_snmp_noSuchInstance;
579                                 note = "noSuchInstance";
580                                 break;
581                         case SERR_EOM:
582                                 hfid = hf_snmp_endOfMibView;
583                                 note = "endOfMibView";
584                                 break;
585                         default: {
586                                 pi = proto_tree_add_text(pt_varbind,tvb,0,0,"Wrong tag for Error Value: expected 0, 1, or 2 but got: %d",tag);
587                                 pt = proto_item_add_subtree(pi,ett_decoding_error);
588                                 expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong tag for SNMP VarBind error value");
589                                 return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
590                         }
591                 }
592
593                 pi = proto_tree_add_item(pt_varbind,hfid,tvb,value_offset,value_len,FALSE);
594                 expert_add_info_format(actx->pinfo, pi, PI_RESPONSE_CODE, PI_NOTE, "%s",note);
595                 g_strlcpy (label, note, ITEM_LABEL_LENGTH);
596                 goto set_label;
597         }
598
599         /* 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 */
600         switch (oid_info->kind) {
601                 case OID_KIND_SCALAR:
602                         if (oid_left  == 1) {
603                                 /* OK: we got the instance sub-id */
604                                 proto_tree_add_uint64(pt_name,hf_snmp_scalar_instance_index,tvb,name_offset,name_len,subids[oid_matched]);
605                                 oid_info_is_ok = TRUE;
606                                 goto indexing_done;
607                         } else if (oid_left  == 0) {
608                                 if (ber_class == BER_CLASS_UNI && tag == BER_UNI_TAG_NULL) {
609                                         /* unSpecified  does not require an instance sub-id add the new value and get off the way! */
610                                         pi_value = proto_tree_add_item(pt_varbind,hf_snmp_unSpecified,tvb,value_offset,value_len,FALSE);
611                                         goto set_label;
612                                 } else {
613                                         proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"A scalar should have one instance sub-id this one has none");
614                                         expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "No instance sub-id in scalar value");
615                                         oid_info_is_ok = FALSE;
616                                         goto indexing_done;
617                                 }
618                         } else {
619                                 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);
620                                 expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong number of instance sub-ids in scalar value");
621                                 oid_info_is_ok = FALSE;
622                                 goto indexing_done;
623                         }
624                 break;
625                 case OID_KIND_COLUMN:
626                         if ( oid_info->parent->kind == OID_KIND_ROW) {
627                                 oid_key_t* k = oid_info->parent->key;
628                                 guint key_start = oid_matched;
629                                 guint key_len = oid_left;
630                                 oid_info_is_ok = TRUE;
631
632                                 if ( key_len == 0 && ber_class == BER_CLASS_UNI && tag == BER_UNI_TAG_NULL) {
633                                         /* unSpecified  does not require an instance sub-id add the new value and get off the way! */
634                                         pi_value = proto_tree_add_item(pt_varbind,hf_snmp_unSpecified,tvb,value_offset,value_len,FALSE);
635                                         goto set_label;
636                                 }
637
638                                 if (k) {
639                                         for (;k;k = k->next) {
640                                                 guint suboid_len;
641
642                                                 if (key_start >= oid_matched+oid_left) {
643                                                         proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"index sub-oid shorter than expected");
644                                                         expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "index sub-oid shorter than expected");
645                                                         oid_info_is_ok = FALSE;
646                                                         goto indexing_done;
647                                                 }
648
649                                                 switch(k->key_type) {
650                                                         case OID_KEY_TYPE_WRONG: {
651                                                                 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 developpers");
652                                                                 expert_add_info_format(actx->pinfo, pi, PI_UNDECODED, PI_WARN, "Unimplemented instance index");
653                                                                 oid_info_is_ok = FALSE;
654                                                                 goto indexing_done;
655                                                         }
656                                                         case OID_KEY_TYPE_INTEGER: {
657                                                                 if (IS_FT_INT(k->ft_type)) {
658                                                                         proto_tree_add_int(pt_name,k->hfid,tvb,name_offset,name_len,(guint)subids[key_start]);
659                                                                 } else { /* if it's not an unsigned int let proto_tree_add_uint throw a warning */
660                                                                         proto_tree_add_uint(pt_name,k->hfid,tvb,name_offset,name_len,(guint)subids[key_start]);
661                                                                 }
662                                                                 key_start++;
663                                                                 key_len--;
664                                                                 continue; /* k->next */
665                                                         }
666                                                         case OID_KEY_TYPE_IMPLIED_OID:
667                                                                 suboid_len = key_len;
668
669                                                                 goto show_oid_index;
670
671                                                         case OID_KEY_TYPE_OID: {
672                                                                 guint8* suboid_buf;
673                                                                 guint suboid_buf_len;
674                                                                 guint32* suboid;
675
676                                                                 suboid_len = subids[key_start++];
677                                                                 key_len--;
678
679 show_oid_index:
680                                                                 suboid = &(subids[key_start]);
681
682                                                                 if( suboid_len == 0 ) {
683                                                                         proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"an index sub-oid OID cannot be 0 bytes long!");
684                                                                         expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "index sub-oid OID with len=0");
685                                                                         oid_info_is_ok = FALSE;
686                                                                         goto indexing_done;
687                                                                 }
688
689                                                                 if( key_len < suboid_len ) {
690                                                                         proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"index sub-oid should not be longer than remaining oid size");
691                                                                         expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "index sub-oid longer than remaining oid size");
692                                                                         oid_info_is_ok = FALSE;
693                                                                         goto indexing_done;
694                                                                 }
695
696                                                                 suboid_buf_len = oid_subid2encoded(suboid_len, suboid, &suboid_buf);
697
698                                                                 DISSECTOR_ASSERT(suboid_buf_len);
699
700                                                                 proto_tree_add_oid(pt_name,k->hfid,tvb,name_offset, suboid_buf_len, suboid_buf);
701
702                                                                 key_start += suboid_len;
703                                                                 key_len -= suboid_len + 1;
704                                                                 continue; /* k->next */
705                                                         }
706                                                         default: {
707                                                                 guint8* buf;
708                                                                 guint buf_len;
709                                                                 guint32* suboid;
710                                                                 guint i;
711
712
713                                                                 switch (k->key_type) {
714                                                                         case OID_KEY_TYPE_IPADDR:
715                                                                                 suboid = &(subids[key_start]);
716                                                                                 buf_len = 4;
717                                                                                 break;
718                                                                         case OID_KEY_TYPE_IMPLIED_STRING:
719                                                                         case OID_KEY_TYPE_IMPLIED_BYTES:
720                                                                                 suboid = &(subids[key_start]);
721                                                                                 buf_len = key_len;
722                                                                                 break;
723                                                                         default:
724                                                                                 buf_len = k->num_subids;
725                                                                                 suboid = &(subids[key_start]);
726
727                                                                                 if(!buf_len) {
728                                                                                         buf_len = *suboid++;
729                                                                                         key_len--;
730                                                                                         key_start++;
731                                                                                 }
732                                                                                 break;
733                                                                 }
734
735                                                                 if( key_len < buf_len ) {
736                                                                         proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"index string should not be longer than remaining oid size");
737                                                                         expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "index string longer than remaining oid size");
738                                                                         oid_info_is_ok = FALSE;
739                                                                         goto indexing_done;
740                                                                 }
741
742                                                                 buf = ep_alloc(buf_len+1);
743                                                                 for (i = 0; i < buf_len; i++)
744                                                                         buf[i] = (guint8)suboid[i];
745                                                                 buf[i] = '\0';
746
747                                                                 switch(k->key_type) {
748                                                                         case OID_KEY_TYPE_STRING:
749                                                                         case OID_KEY_TYPE_IMPLIED_STRING:
750                                                                                 proto_tree_add_string(pt_name,k->hfid,tvb,name_offset,buf_len, buf);
751                                                                                 break;
752                                                                         case OID_KEY_TYPE_BYTES:
753                                                                         case OID_KEY_TYPE_NSAP:
754                                                                         case OID_KEY_TYPE_IMPLIED_BYTES:
755                                                                                 proto_tree_add_bytes(pt_name,k->hfid,tvb,name_offset,buf_len, buf);
756                                                                                 break;
757                                                                         case OID_KEY_TYPE_IPADDR: {
758                                                                                 guint32* ipv4_p = (void*)buf;
759                                                                                 proto_tree_add_ipv4(pt_name,k->hfid,tvb,name_offset,buf_len, *ipv4_p);
760                                                                                 break;
761                                                                         default:
762                                                                                 DISSECTOR_ASSERT_NOT_REACHED();
763                                                                                 break;
764                                                                         }
765                                                                 }
766
767                                                                 key_start += buf_len;
768                                                                 key_len -= buf_len;
769                                                                 continue; /* k->next*/
770                                                         }
771                                                 }
772                                         }
773                                         goto indexing_done;
774                                 } else {
775                                         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");
776                                         expert_add_info_format(actx->pinfo, pi, PI_UNDECODED, PI_WARN, "Unimplemented instance index");
777                                         oid_info_is_ok = FALSE;
778                                         goto indexing_done;
779                                 }
780                         } else {
781                                 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.");
782                                 expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_ERROR, "COLUMS's parent is not a ROW");
783                                 oid_info_is_ok = FALSE;
784                                 goto indexing_done;
785                         }
786                 default: {
787 /*                      proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"This kind OID should have no value");
788                         expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "This kind OID should have no value"); */
789                         oid_info_is_ok = FALSE;
790                         goto indexing_done;
791                 }
792         }
793 indexing_done:
794
795         if (oid_info_is_ok) {
796                 if (ber_class == BER_CLASS_UNI && tag == BER_UNI_TAG_NULL) {
797                         pi_value = proto_tree_add_item(pt_varbind,hf_snmp_unSpecified,tvb,value_offset,value_len,FALSE);
798                 }  else {
799                         if ((oid_info->value_type->ber_class != BER_CLASS_ANY) &&
800                                 (ber_class != oid_info->value_type->ber_class))
801                                 format_error = BER_WRONG_TAG;
802
803                         if ((oid_info->value_type->ber_tag != BER_TAG_ANY) &&
804                                 (tag != oid_info->value_type->ber_tag))
805                                 format_error = BER_WRONG_TAG;
806
807                         max_len = oid_info->value_type->max_len == -1 ? 0xffffff : oid_info->value_type->max_len;
808                         min_len  = oid_info->value_type->min_len;
809
810                         if ((int)value_len < min_len || (int)value_len > max_len)
811                                 format_error = BER_WRONG_LENGTH;
812
813                         pi_value = proto_tree_add_item(pt_varbind,oid_info->value_hfid,tvb,value_offset,value_len,FALSE);
814                 }
815         } else {
816                 switch(ber_class|(tag<<4)) {
817                         case BER_CLASS_UNI|(BER_UNI_TAG_INTEGER<<4):
818                                 max_len = 4; min_len = 1;
819                                 if (value_len > (guint)max_len && value_len < (guint)min_len) format_error = BER_WRONG_LENGTH;
820                                 hfid = hf_snmp_integer32_value;
821                                 break;
822                         case BER_CLASS_UNI|(BER_UNI_TAG_OCTETSTRING<<4):
823                                 hfid = hf_snmp_octetstring_value;
824                                 break;
825                         case BER_CLASS_UNI|(BER_UNI_TAG_OID<<4):
826                                 max_len = -1; min_len = 1;
827                                 if (value_len < (guint)min_len) format_error = BER_WRONG_LENGTH;
828                                 hfid = hf_snmp_oid_value;
829                                 break;
830                         case BER_CLASS_UNI|(BER_UNI_TAG_NULL<<4):
831                                 max_len = 0; min_len = 0;
832                                 if (value_len != 0) format_error = BER_WRONG_LENGTH;
833                                 hfid = hf_snmp_null_value;
834                                 break;
835                         case BER_CLASS_APP: /* | (SNMP_IPA<<4)*/
836                                 switch(value_len) {
837                                         case 4: hfid = hf_snmp_ipv4_value; break;
838                                         case 16: hfid = hf_snmp_ipv6_value; break;
839                                         default: hfid = hf_snmp_anyaddress_value; break;
840                                 }
841                                 break;
842                         case BER_CLASS_APP|(SNMP_U32<<4):
843                                 hfid = hf_snmp_unsigned32_value;
844                                 break;
845                         case BER_CLASS_APP|(SNMP_GGE<<4):
846                                 hfid = hf_snmp_gauge32_value;
847                                 break;
848                         case BER_CLASS_APP|(SNMP_CNT<<4):
849                                 hfid = hf_snmp_counter_value;
850                                 break;
851                         case BER_CLASS_APP|(SNMP_TIT<<4):
852                                 hfid = hf_snmp_timeticks_value;
853                                 break;
854                         case BER_CLASS_APP|(SNMP_OPQ<<4):
855                                 hfid = hf_snmp_opaque_value;
856                                 break;
857                         case BER_CLASS_APP|(SNMP_NSP<<4):
858                                 hfid = hf_snmp_nsap_value;
859                                 break;
860                         case BER_CLASS_APP|(SNMP_C64<<4):
861                                 hfid = hf_snmp_big_counter_value;
862                                 break;
863                         default:
864                                 hfid = hf_snmp_unknown_value;
865                                 break;
866                 }
867
868                 pi_value = proto_tree_add_item(pt_varbind,hfid,tvb,value_offset,value_len,FALSE);
869                 expert_add_info_format(actx->pinfo, pi_value, PI_UNDECODED, PI_NOTE, "Unresolved value, Missing MIB");
870                 oid_info_is_ok = FALSE;
871         }
872
873         pt_value = proto_item_add_subtree(pi_value,ett_value);
874
875         if (value_len > 0 && oid_string) {
876                 tvbuff_t* sub_tvb = tvb_new_subset(tvb, value_offset, value_len, value_len);
877
878                 next_tvb_add_string(&var_list, sub_tvb, (snmp_var_in_tree) ? pt_value : NULL, value_sub_dissectors_table, oid_string);
879         }
880
881
882 set_label:
883         if (pi_value) proto_item_fill_label(pi_value->finfo, label);
884
885         if (oid_info && oid_info->name) {
886                 if (oid_left >= 1) {
887                         repr  = ep_strdup_printf("%s.%s (%s)",
888                                                                          oid_info->name,
889                                                                          oid_subid2string(&(subids[oid_matched]),oid_left),
890                                                                          oid_subid2string(subids,oid_matched+oid_left));
891                         info_oid = ep_strdup_printf("%s.%s", oid_info->name,
892                                                     oid_subid2string(&(subids[oid_matched]),oid_left));
893                 } else {
894                         repr  = ep_strdup_printf("%s (%s)",
895                                                                          oid_info->name,
896                                                                          oid_subid2string(subids,oid_matched));
897                         info_oid = oid_info->name;
898                 }
899         } else if (oid_string) {
900                 repr  = ep_strdup(oid_string);
901                 info_oid = oid_string;
902         } else {
903                 repr  = ep_strdup("[Bad OID]");
904         }
905
906         valstr = strstr(label,": ");
907         valstr = valstr ? valstr+2 : label;
908
909         proto_item_set_text(pi_varbind,"%s: %s",repr,valstr);
910
911         if (display_oid && info_oid && check_col(actx->pinfo->cinfo, COL_INFO)) {
912           col_append_fstr (actx->pinfo->cinfo, COL_INFO, " %s", info_oid);
913         }
914
915         switch (format_error) {
916                 case BER_WRONG_LENGTH: {
917                         proto_tree* pt = proto_item_add_subtree(pi_value,ett_decoding_error);
918                         proto_item* pi = proto_tree_add_text(pt,tvb,0,0,"Wrong value length: %u  expecting: %u <= len <= %u",
919                                                                                                  value_len,
920                                                                                                  min_len,
921                                                                                                  max_len == -1 ? 0xFFFFFF : max_len);
922                         pt = proto_item_add_subtree(pi,ett_decoding_error);
923                         expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong length for SNMP VarBind/value");
924                         return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
925                 }
926                 case BER_WRONG_TAG: {
927                         proto_tree* pt = proto_item_add_subtree(pi_value,ett_decoding_error);
928                         proto_item* pi = proto_tree_add_text(pt,tvb,0,0,"Wrong class/tag for Value expected: %d,%d got: %d,%d",
929                                                                                                  oid_info->value_type->ber_class,
930                                                                                                  oid_info->value_type->ber_tag,
931                                                                                                  ber_class,
932                                                                                                  tag);
933                         pt = proto_item_add_subtree(pi,ett_decoding_error);
934                         expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong class/tag for SNMP VarBind/value");
935                         return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
936                 }
937                 default:
938                         break;
939         }
940
941         return seq_offset + seq_len;
942 }
943
944
945 #define F_SNMP_ENGINEID_CONFORM 0x80
946 #define SNMP_ENGINEID_RFC1910 0x00
947 #define SNMP_ENGINEID_RFC3411 0x01
948
949 static const true_false_string tfs_snmp_engineid_conform = {
950   "RFC3411 (SNMPv3)",
951   "RFC1910 (Non-SNMPv3)"
952 };
953
954 #define SNMP_ENGINEID_FORMAT_IPV4 0x01
955 #define SNMP_ENGINEID_FORMAT_IPV6 0x02
956 #define SNMP_ENGINEID_FORMAT_MACADDRESS 0x03
957 #define SNMP_ENGINEID_FORMAT_TEXT 0x04
958 #define SNMP_ENGINEID_FORMAT_OCTETS 0x05
959
960 static const value_string snmp_engineid_format_vals[] = {
961         { SNMP_ENGINEID_FORMAT_IPV4,    "IPv4 address" },
962         { SNMP_ENGINEID_FORMAT_IPV6,    "IPv6 address" },
963         { SNMP_ENGINEID_FORMAT_MACADDRESS,      "MAC address" },
964         { SNMP_ENGINEID_FORMAT_TEXT,    "Text, administratively assigned" },
965         { SNMP_ENGINEID_FORMAT_OCTETS,  "Octets, administratively assigned" },
966         { 0,    NULL }
967 };
968
969 /*
970  * SNMP Engine ID dissection according to RFC 3411 (SnmpEngineID TC)
971  * or historic RFC 1910 (AgentID)
972  */
973 int dissect_snmp_engineid(proto_tree *tree, tvbuff_t *tvb, int offset, int len) {
974     proto_item *item = NULL;
975     guint8 conformance, format;
976     guint32 enterpriseid, seconds;
977     nstime_t ts;
978     int len_remain = len;
979
980     /* first bit: engine id conformance */
981     if (len_remain<4) return offset;
982     conformance = ((tvb_get_guint8(tvb, offset)>>7) && 0x01);
983     proto_tree_add_item(tree, hf_snmp_engineid_conform, tvb, offset, 1, FALSE);
984
985     /* 4-byte enterprise number/name */
986     if (len_remain<4) return offset;
987     enterpriseid = tvb_get_ntohl(tvb, offset);
988     if (conformance)
989       enterpriseid -= 0x80000000; /* ignore first bit */
990     proto_tree_add_uint(tree, hf_snmp_engineid_enterprise, tvb, offset, 4, enterpriseid);
991     offset+=4;
992     len_remain-=4;
993
994     switch(conformance) {
995
996     case SNMP_ENGINEID_RFC1910:
997       /* 12-byte AgentID w/ 8-byte trailer */
998       if (len_remain==8) {
999         proto_tree_add_text(tree, tvb, offset, 8, "AgentID Trailer: 0x%s",
1000                             tvb_bytes_to_str(tvb, offset, 8));
1001         offset+=8;
1002         len_remain-=8;
1003       } else {
1004         proto_tree_add_text(tree, tvb, offset, len_remain, "<Data not conforming to RFC1910>");
1005         return offset;
1006       }
1007       break;
1008
1009     case SNMP_ENGINEID_RFC3411: /* variable length: 5..32 */
1010
1011       /* 1-byte format specifier */
1012       if (len_remain<1) return offset;
1013       format = tvb_get_guint8(tvb, offset);
1014       item = proto_tree_add_uint_format(tree, hf_snmp_engineid_format, tvb, offset, 1, format, "Engine ID Format: %s (%d)",
1015                           val_to_str(format, snmp_engineid_format_vals, "Reserved/Enterprise-specific"), format);
1016       offset+=1;
1017       len_remain-=1;
1018
1019       switch(format) {
1020       case SNMP_ENGINEID_FORMAT_IPV4:
1021         /* 4-byte IPv4 address */
1022         if (len_remain==4) {
1023           proto_tree_add_item(tree, hf_snmp_engineid_ipv4, tvb, offset, 4, FALSE);
1024           offset+=4;
1025           len_remain=0;
1026         }
1027         break;
1028       case SNMP_ENGINEID_FORMAT_IPV6:
1029         /* 16-byte IPv6 address */
1030         if (len_remain==16) {
1031           proto_tree_add_item(tree, hf_snmp_engineid_ipv6, tvb, offset, 16, FALSE);
1032           offset+=16;
1033           len_remain=0;
1034         }
1035         break;
1036       case SNMP_ENGINEID_FORMAT_MACADDRESS:
1037         /* 6-byte MAC address */
1038         if (len_remain==6) {
1039           proto_tree_add_item(tree, hf_snmp_engineid_mac, tvb, offset, 6, FALSE);
1040           offset+=6;
1041           len_remain=0;
1042         }
1043         break;
1044       case SNMP_ENGINEID_FORMAT_TEXT:
1045         /* max. 27-byte string, administratively assigned */
1046         if (len_remain<=27) {
1047           proto_tree_add_item(tree, hf_snmp_engineid_text, tvb, offset, len_remain, FALSE);
1048           offset+=len_remain;
1049           len_remain=0;
1050         }
1051         break;
1052       case 128:
1053         /* most common enterprise-specific format: (ucd|net)-snmp random */
1054         if ((enterpriseid==2021)||(enterpriseid==8072)) {
1055           proto_item_append_text(item, (enterpriseid==2021) ? ": UCD-SNMP Random" : ": Net-SNMP Random");
1056           /* demystify: 4B random, 4B epoch seconds */
1057           if (len_remain==8) {
1058             proto_tree_add_item(tree, hf_snmp_engineid_data, tvb, offset, 4, FALSE);
1059             seconds = tvb_get_letohl(tvb, offset+4);
1060             ts.secs = seconds;
1061             proto_tree_add_time_format(tree, hf_snmp_engineid_time, tvb, offset+4, 4,
1062                                   &ts, "Engine ID Data: Creation Time: %s",
1063                                   abs_time_secs_to_str(seconds));
1064             offset+=8;
1065             len_remain=0;
1066           }
1067         }
1068         break;
1069       case SNMP_ENGINEID_FORMAT_OCTETS:
1070       default:
1071         /* max. 27 bytes, administratively assigned or unknown format */
1072         if (len_remain<=27) {
1073           proto_tree_add_item(tree, hf_snmp_engineid_data, tvb, offset, len_remain, FALSE);
1074           offset+=len_remain;
1075           len_remain=0;
1076         }
1077         break;
1078       }
1079     }
1080
1081     if (len_remain>0) {
1082       proto_tree_add_text(tree, tvb, offset, len_remain, "<Data not conforming to RFC3411>");
1083       offset+=len_remain;
1084     }
1085     return offset;
1086 }
1087
1088
1089 static void set_ue_keys(snmp_ue_assoc_t* n ) {
1090         guint key_size = n->user.authModel->key_size;
1091
1092         n->user.authKey.data = se_alloc(key_size);
1093         n->user.authKey.len = key_size;
1094         n->user.authModel->pass2key(n->user.authPassword.data,
1095                                                                 n->user.authPassword.len,
1096                                                                 n->engine.data,
1097                                                                 n->engine.len,
1098                                                                 n->user.authKey.data);
1099
1100         n->user.privKey.data = se_alloc(key_size);
1101         n->user.privKey.len = key_size;
1102         n->user.authModel->pass2key(n->user.privPassword.data,
1103                                                                 n->user.privPassword.len,
1104                                                                 n->engine.data,
1105                                                                 n->engine.len,
1106                                                                 n->user.privKey.data);
1107 }
1108
1109 static snmp_ue_assoc_t* ue_se_dup(snmp_ue_assoc_t* o) {
1110         snmp_ue_assoc_t* d = se_memdup(o,sizeof(snmp_ue_assoc_t));
1111
1112         d->user.authModel = o->user.authModel;
1113
1114         d->user.privProtocol = o->user.privProtocol;
1115
1116         d->user.userName.data = se_memdup(o->user.userName.data,o->user.userName.len);
1117         d->user.userName.len = o->user.userName.len;
1118
1119         d->user.authPassword.data = o->user.authPassword.data ? se_memdup(o->user.authPassword.data,o->user.authPassword.len) : NULL;
1120         d->user.authPassword.len = o->user.authPassword.len;
1121
1122         d->user.privPassword.data = o->user.privPassword.data ? se_memdup(o->user.privPassword.data,o->user.privPassword.len) : NULL;
1123         d->user.privPassword.len = o->user.privPassword.len;
1124
1125         d->engine.len = o->engine.len;
1126
1127         if (d->engine.len) {
1128                 d->engine.data = se_memdup(o->engine.data,o->engine.len);
1129                 set_ue_keys(d);
1130         }
1131
1132         return d;
1133
1134 }
1135
1136
1137 #define CACHE_INSERT(c,a) if (c) { snmp_ue_assoc_t* t = c; c = a; c->next = t; } else { c = a; a->next = NULL; }
1138
1139 static void renew_ue_cache(void) {
1140         if (num_ueas) {
1141                 guint i;
1142
1143                 localized_ues = NULL;
1144                 unlocalized_ues = NULL;
1145
1146                 for(i = 0; i < num_ueas; i++) {
1147                         snmp_ue_assoc_t* a = ue_se_dup(&(ueas[i]));
1148
1149                         if (a->engine.len) {
1150                                 CACHE_INSERT(localized_ues,a);
1151
1152                         } else {
1153                                 CACHE_INSERT(unlocalized_ues,a);
1154                         }
1155
1156                 }
1157         } else {
1158                 localized_ues = NULL;
1159                 unlocalized_ues = NULL;
1160         }
1161 }
1162
1163
1164 static snmp_ue_assoc_t* localize_ue( snmp_ue_assoc_t* o, const guint8* engine, guint engine_len ) {
1165         snmp_ue_assoc_t* n = se_memdup(o,sizeof(snmp_ue_assoc_t));
1166
1167         n->engine.data = se_memdup(engine,engine_len);
1168         n->engine.len = engine_len;
1169
1170         set_ue_keys(n);
1171
1172         return n;
1173 }
1174
1175
1176 #define localized_match(a,u,ul,e,el) \
1177         ( a->user.userName.len == ul \
1178         && a->engine.len == el \
1179         && memcmp( a->user.userName.data, u, (a->user.userName.len < ul) ? a->user.userName.len : ul ) == 0 \
1180         && memcmp( a->engine.data,   e, (a->engine.len   < el) ? a->engine.len   : el ) == 0 )
1181
1182 #define unlocalized_match(a,u,l) \
1183         ( a->user.userName.len == l && memcmp( a->user.userName.data, u, a->user.userName.len < l ? a->user.userName.len : l) == 0 )
1184
1185 static snmp_ue_assoc_t* get_user_assoc(tvbuff_t* engine_tvb, tvbuff_t* user_tvb) {
1186         static snmp_ue_assoc_t* a;
1187         guint given_username_len;
1188         guint8* given_username;
1189         guint given_engine_len;
1190         guint8* given_engine;
1191
1192         if ( ! (localized_ues || unlocalized_ues ) ) return NULL;
1193
1194         if (! ( user_tvb && engine_tvb ) ) return NULL;
1195
1196         given_username_len = tvb_length_remaining(user_tvb,0);
1197         given_username = ep_tvb_memdup(user_tvb,0,-1);
1198         given_engine_len = tvb_length_remaining(engine_tvb,0);
1199         given_engine = ep_tvb_memdup(engine_tvb,0,-1);
1200
1201         for (a = localized_ues; a; a = a->next) {
1202                 if ( localized_match(a, given_username, given_username_len, given_engine, given_engine_len) ) {
1203                         return a;
1204                 }
1205         }
1206
1207         for (a = unlocalized_ues; a; a = a->next) {
1208                 if ( unlocalized_match(a, given_username, given_username_len) ) {
1209                         snmp_ue_assoc_t* n = localize_ue( a, given_engine, given_engine_len );
1210                         CACHE_INSERT(localized_ues,n);
1211                         return n;
1212                 }
1213         }
1214
1215         return NULL;
1216 }
1217
1218 static gboolean snmp_usm_auth_md5(snmp_usm_params_t* p, guint8** calc_auth_p, guint* calc_auth_len_p, gchar const** error) {
1219         guint msg_len;
1220         guint8* msg;
1221         guint auth_len;
1222         guint8* auth;
1223         guint8* key;
1224         guint key_len;
1225         guint8 calc_auth[16];
1226         guint start;
1227         guint end;
1228         guint i;
1229
1230         if (!p->auth_tvb) {
1231                 *error = "No Authenticator";
1232                 return FALSE;
1233         }
1234
1235         key = p->user_assoc->user.authKey.data;
1236         key_len = p->user_assoc->user.authKey.len;
1237
1238         if (! key ) {
1239                 *error = "User has no authKey";
1240                 return FALSE;
1241         }
1242
1243
1244         auth_len = tvb_length_remaining(p->auth_tvb,0);
1245
1246         if (auth_len != 12) {
1247                 *error = "Authenticator length wrong";
1248                 return FALSE;
1249         }
1250
1251         msg_len = tvb_length_remaining(p->msg_tvb,0);
1252         msg = ep_tvb_memdup(p->msg_tvb,0,msg_len);
1253
1254
1255         auth = ep_tvb_memdup(p->auth_tvb,0,auth_len);
1256
1257         start = p->auth_offset - p->start_offset;
1258         end =   start + auth_len;
1259
1260         /* fill the authenticator with zeros */
1261         for ( i = start ; i < end ; i++ ) {
1262                 msg[i] = '\0';
1263         }
1264
1265         md5_hmac(msg, msg_len, key, key_len, calc_auth);
1266
1267         if (calc_auth_p) *calc_auth_p = calc_auth;
1268         if (calc_auth_len_p) *calc_auth_len_p = 12;
1269
1270         return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
1271 }
1272
1273
1274 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_) {
1275         guint msg_len;
1276         guint8* msg;
1277         guint auth_len;
1278         guint8* auth;
1279         guint8* key;
1280         guint key_len;
1281         guint8 calc_auth[20];
1282         guint start;
1283         guint end;
1284         guint i;
1285
1286         if (!p->auth_tvb) {
1287                 *error = "No Authenticator";
1288                 return FALSE;
1289         }
1290
1291         key = p->user_assoc->user.authKey.data;
1292         key_len = p->user_assoc->user.authKey.len;
1293
1294         if (! key ) {
1295                 *error = "User has no authKey";
1296                 return FALSE;
1297         }
1298
1299
1300         auth_len = tvb_length_remaining(p->auth_tvb,0);
1301
1302
1303         if (auth_len != 12) {
1304                 *error = "Authenticator length wrong";
1305                 return FALSE;
1306         }
1307
1308         msg_len = tvb_length_remaining(p->msg_tvb,0);
1309         msg = ep_tvb_memdup(p->msg_tvb,0,msg_len);
1310
1311         auth = ep_tvb_memdup(p->auth_tvb,0,auth_len);
1312
1313         start = p->auth_offset - p->start_offset;
1314         end =   start + auth_len;
1315
1316         /* fill the authenticator with zeros */
1317         for ( i = start ; i < end ; i++ ) {
1318                 msg[i] = '\0';
1319         }
1320
1321         sha1_hmac(key, key_len, msg, msg_len, calc_auth);
1322
1323         if (calc_auth_p) *calc_auth_p = calc_auth;
1324         if (calc_auth_len_p) *calc_auth_len_p = 12;
1325
1326         return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
1327 }
1328
1329 static tvbuff_t* snmp_usm_priv_des(snmp_usm_params_t* p _U_, tvbuff_t* encryptedData _U_, gchar const** error _U_) {
1330 #ifdef HAVE_LIBGCRYPT
1331     gcry_error_t err;
1332     gcry_cipher_hd_t hd = NULL;
1333
1334         guint8* cleartext;
1335         guint8* des_key = p->user_assoc->user.privKey.data; /* first 8 bytes */
1336         guint8* pre_iv = &(p->user_assoc->user.privKey.data[8]); /* last 8 bytes */
1337         guint8* salt;
1338         gint salt_len;
1339         gint cryptgrm_len;
1340         guint8* cryptgrm;
1341         tvbuff_t* clear_tvb;
1342         guint8 iv[8];
1343         guint i;
1344
1345
1346         salt_len = tvb_length_remaining(p->priv_tvb,0);
1347
1348         if (salt_len != 8)  {
1349                 *error = "decryptionError: msgPrivacyParameters length != 8";
1350                 return NULL;
1351         }
1352
1353         salt = ep_tvb_memdup(p->priv_tvb,0,salt_len);
1354
1355         /*
1356          The resulting "salt" is XOR-ed with the pre-IV to obtain the IV.
1357          */
1358         for (i=0; i<8; i++) {
1359                 iv[i] = pre_iv[i] ^ salt[i];
1360         }
1361
1362         cryptgrm_len = tvb_length_remaining(encryptedData,0);
1363
1364         if (cryptgrm_len % 8) {
1365                 *error = "decryptionError: the length of the encrypted data is not a mutiple of 8 octets";
1366                 return NULL;
1367         }
1368
1369         cryptgrm = ep_tvb_memdup(encryptedData,0,-1);
1370
1371         cleartext = ep_alloc(cryptgrm_len);
1372
1373         err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC, 0);
1374         if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1375
1376     err = gcry_cipher_setiv(hd, iv, 8);
1377         if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1378
1379         err = gcry_cipher_setkey(hd,des_key,8);
1380         if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1381
1382         err = gcry_cipher_decrypt(hd, cleartext, cryptgrm_len, cryptgrm, cryptgrm_len);
1383         if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1384
1385         gcry_cipher_close(hd);
1386
1387         clear_tvb = tvb_new_real_data(cleartext, cryptgrm_len, cryptgrm_len);
1388
1389         return clear_tvb;
1390
1391 on_gcry_error:
1392         *error = (void*)gpg_strerror(err);
1393         if (hd) gcry_cipher_close(hd);
1394         return NULL;
1395 #else
1396         *error = "libgcrypt not present, cannot decrypt";
1397         return NULL;
1398 #endif
1399 }
1400
1401 static tvbuff_t* snmp_usm_priv_aes(snmp_usm_params_t* p _U_, tvbuff_t* encryptedData _U_, gchar const** error _U_) {
1402 #ifdef HAVE_LIBGCRYPT
1403     gcry_error_t err;
1404     gcry_cipher_hd_t hd = NULL;
1405
1406         guint8* cleartext;
1407         guint8* aes_key = p->user_assoc->user.privKey.data; /* first 16 bytes */
1408         guint8 iv[16];
1409         gint priv_len;
1410         gint cryptgrm_len;
1411         guint8* cryptgrm;
1412         tvbuff_t* clear_tvb;
1413
1414         priv_len = tvb_length_remaining(p->priv_tvb,0);
1415
1416         if (priv_len != 8)  {
1417                 *error = "decryptionError: msgPrivacyParameters length != 8";
1418                 return NULL;
1419         }
1420
1421         iv[0] = (p->boots & 0xff000000) >> 24;
1422         iv[1] = (p->boots & 0x00ff0000) >> 16;
1423         iv[2] = (p->boots & 0x0000ff00) >> 8;
1424         iv[3] = (p->boots & 0x000000ff);
1425         iv[4] = (p->time & 0xff000000) >> 24;
1426         iv[5] = (p->time & 0x00ff0000) >> 16;
1427         iv[6] = (p->time & 0x0000ff00) >> 8;
1428         iv[7] = (p->time & 0x000000ff);
1429         tvb_memcpy(p->priv_tvb,&(iv[8]),0,8);
1430
1431         cryptgrm_len = tvb_length_remaining(encryptedData,0);
1432         cryptgrm = ep_tvb_memdup(encryptedData,0,-1);
1433
1434         cleartext = ep_alloc(cryptgrm_len);
1435
1436         err = gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CFB, 0);
1437         if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1438
1439     err = gcry_cipher_setiv(hd, iv, 16);
1440         if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1441
1442         err = gcry_cipher_setkey(hd,aes_key,16);
1443         if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1444
1445         err = gcry_cipher_decrypt(hd, cleartext, cryptgrm_len, cryptgrm, cryptgrm_len);
1446         if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1447
1448         gcry_cipher_close(hd);
1449
1450         clear_tvb = tvb_new_real_data(cleartext, cryptgrm_len, cryptgrm_len);
1451
1452         return clear_tvb;
1453
1454 on_gcry_error:
1455         *error = (void*)gpg_strerror(err);
1456         if (hd) gcry_cipher_close(hd);
1457         return NULL;
1458 #else
1459         *error = "libgcrypt not present, cannot decrypt";
1460         return NULL;
1461 #endif
1462 }
1463
1464
1465 gboolean check_ScopedPdu(tvbuff_t* tvb) {
1466         int offset;
1467         gint8 class;
1468         gboolean pc;
1469         gint32 tag;
1470         int hoffset, eoffset;
1471         guint32 len;
1472
1473         offset = get_ber_identifier(tvb, 0, &class, &pc, &tag);
1474         offset = get_ber_length(tvb, offset, NULL, NULL);
1475
1476         if ( ! (((class!=BER_CLASS_APP) && (class!=BER_CLASS_PRI) )
1477                         && ( (!pc) || (class!=BER_CLASS_UNI) || (tag!=BER_UNI_TAG_ENUMERATED) )
1478                         )) return FALSE;
1479
1480         if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0))
1481                 return TRUE;
1482
1483         hoffset = offset;
1484
1485         offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
1486         offset = get_ber_length(tvb, offset, &len, NULL);
1487         eoffset = offset + len;
1488
1489         if (eoffset <= hoffset) return FALSE;
1490
1491         if ((class!=BER_CLASS_APP)&&(class!=BER_CLASS_PRI))
1492                 if( (class!=BER_CLASS_UNI)
1493                         ||((tag<BER_UNI_TAG_NumericString)&&(tag!=BER_UNI_TAG_OCTETSTRING)&&(tag!=BER_UNI_TAG_UTF8String)) )
1494                         return FALSE;
1495
1496         return TRUE;
1497
1498 }
1499
1500
1501 /*--- Included file: packet-snmp-fn.c ---*/
1502 #line 1 "packet-snmp-fn.c"
1503
1504
1505
1506 static int
1507 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_) {
1508 #line 44 "snmp.cnf"
1509   tvbuff_t* param_tvb = NULL;
1510   const gchar* name;
1511   gint len;
1512
1513   offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, &param_tvb);
1514
1515   if (display_oid && param_tvb) {
1516     len = tvb_length_remaining (param_tvb, 0);
1517     name = oid_resolved_from_encoded(tvb_get_ptr(param_tvb, 0, len), len);
1518     if (name && check_col(actx->pinfo->cinfo, COL_INFO)) {
1519       col_append_fstr (actx->pinfo->cinfo, COL_INFO, " %s", name);
1520     }
1521   }
1522
1523
1524
1525   return offset;
1526 }
1527
1528
1529
1530 static int
1531 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_) {
1532   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1533                                        NULL);
1534
1535   return offset;
1536 }
1537
1538
1539
1540 static int
1541 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_) {
1542   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1543                                       hf_index, BER_CLASS_APP, 0, TRUE, dissect_snmp_OCTET_STRING_SIZE_4);
1544
1545   return offset;
1546 }
1547
1548
1549
1550 static int
1551 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_) {
1552   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1553                                                 NULL);
1554
1555   return offset;
1556 }
1557
1558
1559
1560 static int
1561 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_) {
1562   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1563                                       hf_index, BER_CLASS_APP, 3, TRUE, dissect_snmp_INTEGER_0_4294967295);
1564
1565   return offset;
1566 }
1567
1568
1569
1570 static int
1571 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_) {
1572   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1573                                                 NULL);
1574
1575   return offset;
1576 }
1577
1578
1579
1580 static int
1581 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_) {
1582   offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
1583
1584   return offset;
1585 }
1586
1587
1588 static const value_string snmp_Version_vals[] = {
1589   {   0, "version-1" },
1590   {   1, "v2c" },
1591   {   2, "v2u" },
1592   {   3, "snmpv3" },
1593   { 0, NULL }
1594 };
1595
1596
1597 static int
1598 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_) {
1599   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1600                                                 NULL);
1601
1602   return offset;
1603 }
1604
1605
1606
1607 static int
1608 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_) {
1609   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1610                                        NULL);
1611
1612   return offset;
1613 }
1614
1615
1616
1617 static int
1618 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_) {
1619   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1620                                                 NULL);
1621
1622   return offset;
1623 }
1624
1625
1626 static const value_string snmp_T_error_status_vals[] = {
1627   {   0, "noError" },
1628   {   1, "tooBig" },
1629   {   2, "noSuchName" },
1630   {   3, "badValue" },
1631   {   4, "readOnly" },
1632   {   5, "genErr" },
1633   {   6, "noAccess" },
1634   {   7, "wrongType" },
1635   {   8, "wrongLength" },
1636   {   9, "wrongEncoding" },
1637   {  10, "wrongValue" },
1638   {  11, "noCreation" },
1639   {  12, "inconsistentValue" },
1640   {  13, "resourceUnavailable" },
1641   {  14, "commitFailed" },
1642   {  15, "undoFailed" },
1643   {  16, "authorizationError" },
1644   {  17, "notWritable" },
1645   {  18, "inconsistentName" },
1646   { 0, NULL }
1647 };
1648
1649
1650 static int
1651 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_) {
1652   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1653                                                 NULL);
1654
1655   return offset;
1656 }
1657
1658
1659
1660 static int
1661 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_) {
1662   offset = dissect_ber_null(implicit_tag, actx, tree, tvb, offset, hf_index);
1663
1664   return offset;
1665 }
1666
1667
1668
1669 static const ber_sequence_t VarBindList_sequence_of[1] = {
1670   { &hf_snmp_VarBindList_item, BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_VarBind },
1671 };
1672
1673 static int
1674 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_) {
1675   offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset,
1676                                       VarBindList_sequence_of, hf_index, ett_snmp_VarBindList);
1677
1678   return offset;
1679 }
1680
1681
1682 static const ber_sequence_t PDU_sequence[] = {
1683   { &hf_snmp_request_id     , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER },
1684   { &hf_snmp_error_status   , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_error_status },
1685   { &hf_snmp_error_index    , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER },
1686   { &hf_snmp_variable_bindings, BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_VarBindList },
1687   { NULL, 0, 0, 0, NULL }
1688 };
1689
1690 static int
1691 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_) {
1692   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1693                                    PDU_sequence, hf_index, ett_snmp_PDU);
1694
1695   return offset;
1696 }
1697
1698
1699
1700 static int
1701 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_) {
1702   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1703                                       hf_index, BER_CLASS_CON, 0, TRUE, dissect_snmp_PDU);
1704
1705   return offset;
1706 }
1707
1708
1709
1710 static int
1711 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_) {
1712   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1713                                       hf_index, BER_CLASS_CON, 1, TRUE, dissect_snmp_PDU);
1714
1715   return offset;
1716 }
1717
1718
1719
1720 static int
1721 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_) {
1722   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1723                                       hf_index, BER_CLASS_CON, 2, TRUE, dissect_snmp_PDU);
1724
1725   return offset;
1726 }
1727
1728
1729
1730 static int
1731 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_) {
1732   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1733                                       hf_index, BER_CLASS_CON, 3, TRUE, dissect_snmp_PDU);
1734
1735   return offset;
1736 }
1737
1738
1739 static const value_string snmp_T_generic_trap_vals[] = {
1740   {   0, "coldStart" },
1741   {   1, "warmStart" },
1742   {   2, "linkDown" },
1743   {   3, "linkUp" },
1744   {   4, "authenticationFailure" },
1745   {   5, "egpNeighborLoss" },
1746   {   6, "enterpriseSpecific" },
1747   { 0, NULL }
1748 };
1749
1750
1751 static int
1752 dissect_snmp_T_generic_trap(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1753   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1754                                                 NULL);
1755
1756   return offset;
1757 }
1758
1759
1760 static const ber_sequence_t Trap_PDU_U_sequence[] = {
1761   { &hf_snmp_enterprise     , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_snmp_EnterpriseOID },
1762   { &hf_snmp_agent_addr     , BER_CLASS_APP, 0, BER_FLAGS_NOOWNTAG, dissect_snmp_NetworkAddress },
1763   { &hf_snmp_generic_trap   , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_generic_trap },
1764   { &hf_snmp_specific_trap  , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER },
1765   { &hf_snmp_time_stamp     , BER_CLASS_APP, 3, BER_FLAGS_NOOWNTAG, dissect_snmp_TimeTicks },
1766   { &hf_snmp_variable_bindings, BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_VarBindList },
1767   { NULL, 0, 0, 0, NULL }
1768 };
1769
1770 static int
1771 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_) {
1772   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1773                                    Trap_PDU_U_sequence, hf_index, ett_snmp_Trap_PDU_U);
1774
1775   return offset;
1776 }
1777
1778
1779
1780 static int
1781 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_) {
1782   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1783                                       hf_index, BER_CLASS_CON, 4, TRUE, dissect_snmp_Trap_PDU_U);
1784
1785   return offset;
1786 }
1787
1788
1789
1790 static int
1791 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_) {
1792   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1793                                                 NULL);
1794
1795   return offset;
1796 }
1797
1798
1799 static const ber_sequence_t BulkPDU_sequence[] = {
1800   { &hf_snmp_bulkPDU_request_id, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_Integer32 },
1801   { &hf_snmp_non_repeaters  , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_0_2147483647 },
1802   { &hf_snmp_max_repetitions, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_0_2147483647 },
1803   { &hf_snmp_variable_bindings, BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_VarBindList },
1804   { NULL, 0, 0, 0, NULL }
1805 };
1806
1807 static int
1808 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_) {
1809   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1810                                    BulkPDU_sequence, hf_index, ett_snmp_BulkPDU);
1811
1812   return offset;
1813 }
1814
1815
1816
1817 static int
1818 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_) {
1819   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1820                                       hf_index, BER_CLASS_CON, 5, TRUE, dissect_snmp_BulkPDU);
1821
1822   return offset;
1823 }
1824
1825
1826
1827 static int
1828 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_) {
1829   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1830                                       hf_index, BER_CLASS_CON, 6, TRUE, dissect_snmp_PDU);
1831
1832   return offset;
1833 }
1834
1835
1836
1837 static int
1838 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_) {
1839   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1840                                       hf_index, BER_CLASS_CON, 7, TRUE, dissect_snmp_PDU);
1841
1842   return offset;
1843 }
1844
1845
1846
1847 static int
1848 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_) {
1849   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1850                                       hf_index, BER_CLASS_CON, 8, TRUE, dissect_snmp_PDU);
1851
1852   return offset;
1853 }
1854
1855
1856 static const value_string snmp_PDUs_vals[] = {
1857   {   0, "get-request" },
1858   {   1, "get-next-request" },
1859   {   2, "get-response" },
1860   {   3, "set-request" },
1861   {   4, "trap" },
1862   {   5, "getBulkRequest" },
1863   {   6, "informRequest" },
1864   {   7, "sNMPv2-Trap" },
1865   {   8, "report" },
1866   { 0, NULL }
1867 };
1868
1869 static const ber_choice_t PDUs_choice[] = {
1870   {   0, &hf_snmp_get_request    , BER_CLASS_CON, 0, BER_FLAGS_NOOWNTAG, dissect_snmp_GetRequest_PDU },
1871   {   1, &hf_snmp_get_next_request, BER_CLASS_CON, 1, BER_FLAGS_NOOWNTAG, dissect_snmp_GetNextRequest_PDU },
1872   {   2, &hf_snmp_get_response   , BER_CLASS_CON, 2, BER_FLAGS_NOOWNTAG, dissect_snmp_GetResponse_PDU },
1873   {   3, &hf_snmp_set_request    , BER_CLASS_CON, 3, BER_FLAGS_NOOWNTAG, dissect_snmp_SetRequest_PDU },
1874   {   4, &hf_snmp_trap           , BER_CLASS_CON, 4, BER_FLAGS_NOOWNTAG, dissect_snmp_Trap_PDU },
1875   {   5, &hf_snmp_getBulkRequest , BER_CLASS_CON, 5, BER_FLAGS_NOOWNTAG, dissect_snmp_GetBulkRequest_PDU },
1876   {   6, &hf_snmp_informRequest  , BER_CLASS_CON, 6, BER_FLAGS_NOOWNTAG, dissect_snmp_InformRequest_PDU },
1877   {   7, &hf_snmp_sNMPv2_Trap    , BER_CLASS_CON, 7, BER_FLAGS_NOOWNTAG, dissect_snmp_SNMPv2_Trap_PDU },
1878   {   8, &hf_snmp_report         , BER_CLASS_CON, 8, BER_FLAGS_NOOWNTAG, dissect_snmp_Report_PDU },
1879   { 0, NULL, 0, 0, 0, NULL }
1880 };
1881
1882 static int
1883 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_) {
1884 #line 25 "snmp.cnf"
1885 gint pdu_type=-1;
1886
1887   if (check_col(actx->pinfo->cinfo, COL_INFO))
1888     col_clear(actx->pinfo->cinfo, COL_INFO);
1889
1890   offset = dissect_ber_choice(actx, tree, tvb, offset,
1891                                  PDUs_choice, hf_index, ett_snmp_PDUs,
1892                                  &pdu_type);
1893
1894   if( (pdu_type!=-1) && snmp_PDUs_vals[pdu_type].strptr ){
1895         if (check_col(actx->pinfo->cinfo, COL_INFO))
1896                 col_prepend_fstr(actx->pinfo->cinfo, COL_INFO, "%s", snmp_PDUs_vals[pdu_type].strptr);
1897   }
1898
1899
1900
1901   return offset;
1902 }
1903
1904
1905 static const ber_sequence_t Message_sequence[] = {
1906   { &hf_snmp_version        , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_Version },
1907   { &hf_snmp_community      , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_OCTET_STRING },
1908   { &hf_snmp_data           , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_snmp_PDUs },
1909   { NULL, 0, 0, 0, NULL }
1910 };
1911
1912 static int
1913 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_) {
1914   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1915                                    Message_sequence, hf_index, ett_snmp_Message);
1916
1917   return offset;
1918 }
1919
1920
1921 static const value_string snmp_T_datav2u_vals[] = {
1922   {   0, "plaintext" },
1923   {   1, "encrypted" },
1924   { 0, NULL }
1925 };
1926
1927 static const ber_choice_t T_datav2u_choice[] = {
1928   {   0, &hf_snmp_v2u_plaintext  , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG, dissect_snmp_PDUs },
1929   {   1, &hf_snmp_encrypted      , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_OCTET_STRING },
1930   { 0, NULL, 0, 0, 0, NULL }
1931 };
1932
1933 static int
1934 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_) {
1935   offset = dissect_ber_choice(actx, tree, tvb, offset,
1936                                  T_datav2u_choice, hf_index, ett_snmp_T_datav2u,
1937                                  NULL);
1938
1939   return offset;
1940 }
1941
1942
1943 static const ber_sequence_t Messagev2u_sequence[] = {
1944   { &hf_snmp_version        , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_Version },
1945   { &hf_snmp_parameters     , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_OCTET_STRING },
1946   { &hf_snmp_datav2u        , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_snmp_T_datav2u },
1947   { NULL, 0, 0, 0, NULL }
1948 };
1949
1950 static int
1951 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_) {
1952   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1953                                    Messagev2u_sequence, hf_index, ett_snmp_Messagev2u);
1954
1955   return offset;
1956 }
1957
1958
1959
1960 static int
1961 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_) {
1962 #line 81 "snmp.cnf"
1963         tvbuff_t* param_tvb = NULL;
1964
1965         offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1966                                        &param_tvb);
1967          if (param_tvb) {
1968                 proto_tree* engine_tree = proto_item_add_subtree(actx->created_item,ett_engineid);
1969                 dissect_snmp_engineid(engine_tree, param_tvb, 0, tvb_length_remaining(param_tvb,0));
1970         }
1971
1972
1973
1974   return offset;
1975 }
1976
1977
1978
1979 static int
1980 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_) {
1981 #line 72 "snmp.cnf"
1982
1983   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1984                                        &usm_p.engine_tvb);
1985          if (usm_p.engine_tvb) {
1986                 proto_tree* engine_tree = proto_item_add_subtree(actx->created_item,ett_engineid);
1987                 dissect_snmp_engineid(engine_tree, usm_p.engine_tvb, 0, tvb_length_remaining(usm_p.engine_tvb,0));
1988         }
1989
1990
1991
1992   return offset;
1993 }
1994
1995
1996
1997 static int
1998 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_) {
1999   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2000                                                 &usm_p.boots);
2001
2002   return offset;
2003 }
2004
2005
2006
2007 static int
2008 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_) {
2009   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2010                                                 &usm_p.time);
2011
2012   return offset;
2013 }
2014
2015
2016
2017 static int
2018 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_) {
2019   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
2020                                        &usm_p.user_tvb);
2021
2022   return offset;
2023 }
2024
2025
2026
2027 static int
2028 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_) {
2029 #line 94 "snmp.cnf"
2030         offset = dissect_ber_octet_string(FALSE, actx, tree, tvb, offset, hf_index, &usm_p.auth_tvb);
2031         if (usm_p.auth_tvb) {
2032                 usm_p.auth_item = actx->created_item;
2033                 usm_p.auth_offset = offset_from_real_beginning(usm_p.auth_tvb,0);
2034         }
2035
2036
2037   return offset;
2038 }
2039
2040
2041
2042 static int
2043 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_) {
2044   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
2045                                        &usm_p.priv_tvb);
2046
2047   return offset;
2048 }
2049
2050
2051 static const ber_sequence_t UsmSecurityParameters_sequence[] = {
2052   { &hf_snmp_msgAuthoritativeEngineID, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgAuthoritativeEngineID },
2053   { &hf_snmp_msgAuthoritativeEngineBoots, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgAuthoritativeEngineBoots },
2054   { &hf_snmp_msgAuthoritativeEngineTime, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgAuthoritativeEngineTime },
2055   { &hf_snmp_msgUserName    , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgUserName },
2056   { &hf_snmp_msgAuthenticationParameters, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgAuthenticationParameters },
2057   { &hf_snmp_msgPrivacyParameters, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgPrivacyParameters },
2058   { NULL, 0, 0, 0, NULL }
2059 };
2060
2061 static int
2062 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_) {
2063   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
2064                                    UsmSecurityParameters_sequence, hf_index, ett_snmp_UsmSecurityParameters);
2065
2066   return offset;
2067 }
2068
2069
2070
2071 static int
2072 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_) {
2073   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2074                                                 NULL);
2075
2076   return offset;
2077 }
2078
2079
2080
2081 static int
2082 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_) {
2083 #line 213 "snmp.cnf"
2084         tvbuff_t *parameter_tvb = NULL;
2085
2086    offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
2087                                        &parameter_tvb);
2088
2089  if (parameter_tvb){
2090         guint8 v3_flags = tvb_get_guint8(parameter_tvb, 0);
2091         proto_tree* flags_tree = proto_item_add_subtree(actx->created_item,ett_msgFlags);
2092         
2093         proto_tree_add_item(flags_tree, hf_snmp_v3_flags_report, parameter_tvb, 0, 1, FALSE);
2094         proto_tree_add_item(flags_tree, hf_snmp_v3_flags_crypt, parameter_tvb, 0, 1, FALSE);
2095         proto_tree_add_item(flags_tree, hf_snmp_v3_flags_auth, parameter_tvb, 0, 1, FALSE);
2096         
2097         usm_p.encrypted = v3_flags & TH_CRYPT ? TRUE : FALSE;
2098         usm_p.authenticated = v3_flags & TH_AUTH ? TRUE : FALSE;
2099   }
2100
2101
2102
2103
2104   return offset;
2105 }
2106
2107
2108
2109 static int
2110 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_) {
2111   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2112                                                 &MsgSecurityModel);
2113
2114   return offset;
2115 }
2116
2117
2118 static const ber_sequence_t HeaderData_sequence[] = {
2119   { &hf_snmp_msgID          , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_0_2147483647 },
2120   { &hf_snmp_msgMaxSize     , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_484_2147483647 },
2121   { &hf_snmp_msgFlags       , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgFlags },
2122   { &hf_snmp_msgSecurityModel, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgSecurityModel },
2123   { NULL, 0, 0, 0, NULL }
2124 };
2125
2126 static int
2127 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_) {
2128   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
2129                                    HeaderData_sequence, hf_index, ett_snmp_HeaderData);
2130
2131   return offset;
2132 }
2133
2134
2135
2136 static int
2137 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_) {
2138 #line 156 "snmp.cnf"
2139
2140         switch(MsgSecurityModel){
2141                 case SNMP_SEC_USM:      /* 3 */         
2142                         offset = dissect_snmp_UsmSecurityParameters(FALSE, tvb, offset+2, actx, tree, -1);
2143                         usm_p.user_assoc = get_user_assoc(usm_p.engine_tvb, usm_p.user_tvb);
2144                         break;
2145                 case SNMP_SEC_ANY:      /* 0 */
2146                 case SNMP_SEC_V1:       /* 1 */
2147                 case SNMP_SEC_V2C:      /* 2 */
2148                 default:
2149                           offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
2150                                        NULL);
2151
2152                         break;
2153         }
2154
2155
2156
2157   return offset;
2158 }
2159
2160
2161 static const ber_sequence_t ScopedPDU_sequence[] = {
2162   { &hf_snmp_contextEngineID, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_SnmpEngineID },
2163   { &hf_snmp_contextName    , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_OCTET_STRING },
2164   { &hf_snmp_data           , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_snmp_PDUs },
2165   { NULL, 0, 0, 0, NULL }
2166 };
2167
2168 static int
2169 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_) {
2170   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
2171                                    ScopedPDU_sequence, hf_index, ett_snmp_ScopedPDU);
2172
2173   return offset;
2174 }
2175
2176
2177
2178 static int
2179 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_) {
2180 #line 103 "snmp.cnf"
2181         tvbuff_t* crypt_tvb;
2182         offset = dissect_ber_octet_string(FALSE, actx, tree, tvb, offset, hf_snmp_encryptedPDU, &crypt_tvb);
2183
2184         if( usm_p.encrypted && crypt_tvb
2185                 && usm_p.user_assoc
2186                 && usm_p.user_assoc->user.privProtocol ) {
2187                 
2188                 const gchar* error = NULL;
2189                 proto_tree* encryptedpdu_tree = proto_item_add_subtree(actx->created_item,ett_encryptedPDU);
2190                 tvbuff_t* cleartext_tvb = usm_p.user_assoc->user.privProtocol(&usm_p, crypt_tvb, &error );
2191
2192                 if (! cleartext_tvb) {
2193                         proto_item* cause = proto_tree_add_text(encryptedpdu_tree, crypt_tvb, 0, -1,
2194                                 "Failed to decrypt encryptedPDU: %s", error);
2195                         
2196                         expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN,
2197                                 "Failed to decrypt encryptedPDU: %s", error);
2198
2199                         if (check_col(actx->pinfo->cinfo, COL_INFO))
2200                                 col_set_str(actx->pinfo->cinfo, COL_INFO, "encryptedPDU: Failed to decrypt");
2201                                 
2202                         return offset;
2203                 } else {
2204                         proto_item* decrypted_item;
2205                         proto_tree* decrypted_tree;
2206
2207                         if (! check_ScopedPdu(cleartext_tvb)) {
2208                                 proto_item* cause = proto_tree_add_text(encryptedpdu_tree, cleartext_tvb, 0, -1,
2209                                                                                         "Decrypted data not formated as expected, wrong key?");
2210                                 
2211                                 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN,
2212                                                                            "Decrypted data not formated as expected");
2213
2214                                 if (check_col(actx->pinfo->cinfo, COL_INFO))
2215                                         col_set_str(actx->pinfo->cinfo, COL_INFO, "encryptedPDU: Decrypted data not formated as expected");
2216                                 
2217                                 return offset;
2218                         }
2219
2220                         
2221             add_new_data_source(actx->pinfo, cleartext_tvb, "Decrypted ScopedPDU");
2222                         tvb_set_child_real_data_tvbuff(tvb, cleartext_tvb);
2223                         
2224                         decrypted_item = proto_tree_add_item(encryptedpdu_tree, hf_snmp_decryptedPDU,cleartext_tvb,0,-1,FALSE);
2225                         decrypted_tree = proto_item_add_subtree(decrypted_item,ett_decrypted);
2226                         dissect_snmp_ScopedPDU(FALSE, cleartext_tvb, 0, actx, decrypted_tree, -1);
2227                  }
2228         } else {
2229                         if (check_col(actx->pinfo->cinfo, COL_INFO))
2230                                 col_set_str(actx->pinfo->cinfo, COL_INFO, "encryptedPDU: privKey Unknown");
2231         }
2232
2233
2234
2235   return offset;
2236 }
2237
2238
2239 static const value_string snmp_ScopedPduData_vals[] = {
2240   {   0, "plaintext" },
2241   {   1, "encryptedPDU" },
2242   { 0, NULL }
2243 };
2244
2245 static const ber_choice_t ScopedPduData_choice[] = {
2246   {   0, &hf_snmp_plaintext      , BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_ScopedPDU },
2247   {   1, &hf_snmp_encryptedPDU   , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_encryptedPDU },
2248   { 0, NULL, 0, 0, 0, NULL }
2249 };
2250
2251 static int
2252 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_) {
2253   offset = dissect_ber_choice(actx, tree, tvb, offset,
2254                                  ScopedPduData_choice, hf_index, ett_snmp_ScopedPduData,
2255                                  NULL);
2256
2257   return offset;
2258 }
2259
2260
2261 static const ber_sequence_t SNMPv3Message_sequence[] = {
2262   { &hf_snmp_msgVersion     , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_Version },
2263   { &hf_snmp_msgGlobalData  , BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_snmp_HeaderData },
2264   { &hf_snmp_msgSecurityParameters, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_T_msgSecurityParameters },
2265   { &hf_snmp_msgData        , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_snmp_ScopedPduData },
2266   { NULL, 0, 0, 0, NULL }
2267 };
2268
2269 static int
2270 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_) {
2271   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
2272                                    SNMPv3Message_sequence, hf_index, ett_snmp_SNMPv3Message);
2273
2274 #line 171 "snmp.cnf"
2275
2276         if( usm_p.authenticated
2277                 && usm_p.user_assoc
2278                 && usm_p.user_assoc->user.authModel ) {
2279                 const gchar* error = NULL;
2280                 proto_item* authen_item;
2281                 proto_tree* authen_tree = proto_item_add_subtree(usm_p.auth_item,ett_authParameters);
2282                 guint8* calc_auth;
2283                 guint calc_auth_len;
2284                 
2285                 usm_p.authOK = usm_p.user_assoc->user.authModel->authenticate( &usm_p, &calc_auth, &calc_auth_len, &error );
2286
2287                 if (error) {
2288                         authen_item = proto_tree_add_text(authen_tree,tvb,0,0,"Error while verifying Messsage authenticity: %s", error);
2289                         PROTO_ITEM_SET_GENERATED(authen_item);
2290                         expert_add_info_format( actx->pinfo, authen_item, PI_MALFORMED, PI_ERROR, "Error while verifying Messsage authenticity: %s", error );
2291                 } else {
2292                         int severity;
2293                         gchar* fmt;                     
2294
2295                         authen_item = proto_tree_add_boolean(authen_tree, hf_snmp_msgAuthentication, tvb, 0, 0, usm_p.authOK);
2296                         PROTO_ITEM_SET_GENERATED(authen_item);
2297                         
2298                         if (usm_p.authOK) {
2299                                 fmt = "SNMP Authentication OK";
2300                                 severity = PI_CHAT;
2301                         } else {
2302                                 gchar* calc_auth_str = bytestring_to_str(calc_auth,calc_auth_len,' ');
2303                                 proto_item_append_text(authen_item, " calcuated = %s", calc_auth_str);
2304                                 fmt = "SNMP Authentication Error";
2305                                 severity = PI_WARN;
2306                         }
2307
2308                         expert_add_info_format( actx->pinfo, authen_item, PI_CHECKSUM, severity, fmt );
2309                 }
2310         }
2311
2312
2313   return offset;
2314 }
2315
2316
2317 static const value_string snmp_T_smux_version_vals[] = {
2318   {   0, "version-1" },
2319   { 0, NULL }
2320 };
2321
2322
2323 static int
2324 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_) {
2325   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2326                                                 NULL);
2327
2328   return offset;
2329 }
2330
2331
2332
2333 static int
2334 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_) {
2335   offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
2336
2337   return offset;
2338 }
2339
2340
2341
2342 static int
2343 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_) {
2344   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
2345                                        NULL);
2346
2347   return offset;
2348 }
2349
2350
2351 static const ber_sequence_t SimpleOpen_U_sequence[] = {
2352   { &hf_snmp_smux_version   , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_smux_version },
2353   { &hf_snmp_identity       , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_snmp_OBJECT_IDENTIFIER },
2354   { &hf_snmp_description    , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_DisplayString },
2355   { &hf_snmp_password       , BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, BER_FLAGS_NOOWNTAG, dissect_snmp_OCTET_STRING },
2356   { NULL, 0, 0, 0, NULL }
2357 };
2358
2359 static int
2360 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_) {
2361   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
2362                                    SimpleOpen_U_sequence, hf_index, ett_snmp_SimpleOpen_U);
2363
2364   return offset;
2365 }
2366
2367
2368
2369 static int
2370 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_) {
2371   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
2372                                       hf_index, BER_CLASS_APP, 0, TRUE, dissect_snmp_SimpleOpen_U);
2373
2374   return offset;
2375 }
2376
2377
2378 static const value_string snmp_OpenPDU_vals[] = {
2379   {   0, "smux-simple" },
2380   { 0, NULL }
2381 };
2382
2383 static const ber_choice_t OpenPDU_choice[] = {
2384   {   0, &hf_snmp_smux_simple    , BER_CLASS_APP, 0, BER_FLAGS_NOOWNTAG, dissect_snmp_SimpleOpen },
2385   { 0, NULL, 0, 0, 0, NULL }
2386 };
2387
2388 static int
2389 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_) {
2390   offset = dissect_ber_choice(actx, tree, tvb, offset,
2391                                  OpenPDU_choice, hf_index, ett_snmp_OpenPDU,
2392                                  NULL);
2393
2394   return offset;
2395 }
2396
2397
2398 static const value_string snmp_ClosePDU_U_vals[] = {
2399   {   0, "goingDown" },
2400   {   1, "unsupportedVersion" },
2401   {   2, "packetFormat" },
2402   {   3, "protocolError" },
2403   {   4, "internalError" },
2404   {   5, "authenticationFailure" },
2405   { 0, NULL }
2406 };
2407
2408
2409 static int
2410 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_) {
2411   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2412                                                 NULL);
2413
2414   return offset;
2415 }
2416
2417
2418
2419 static int
2420 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_) {
2421   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
2422                                       hf_index, BER_CLASS_APP, 1, TRUE, dissect_snmp_ClosePDU_U);
2423
2424   return offset;
2425 }
2426
2427
2428
2429 static int
2430 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_) {
2431   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2432                                                 NULL);
2433
2434   return offset;
2435 }
2436
2437
2438 static const value_string snmp_T_operation_vals[] = {
2439   {   0, "delete" },
2440   {   1, "readOnly" },
2441   {   2, "readWrite" },
2442   { 0, NULL }
2443 };
2444
2445
2446 static int
2447 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_) {
2448   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2449                                                 NULL);
2450
2451   return offset;
2452 }
2453
2454
2455 static const ber_sequence_t RReqPDU_U_sequence[] = {
2456   { &hf_snmp_subtree        , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_snmp_ObjectName },
2457   { &hf_snmp_priority       , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_INTEGER_M1_2147483647 },
2458   { &hf_snmp_operation      , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_snmp_T_operation },
2459   { NULL, 0, 0, 0, NULL }
2460 };
2461
2462 static int
2463 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_) {
2464   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
2465                                    RReqPDU_U_sequence, hf_index, ett_snmp_RReqPDU_U);
2466
2467   return offset;
2468 }
2469
2470
2471
2472 static int
2473 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_) {
2474   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
2475                                       hf_index, BER_CLASS_APP, 2, TRUE, dissect_snmp_RReqPDU_U);
2476
2477   return offset;
2478 }
2479
2480
2481 static const value_string snmp_RRspPDU_U_vals[] = {
2482   {  -1, "failure" },
2483   { 0, NULL }
2484 };
2485
2486
2487 static int
2488 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_) {
2489   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2490                                                 NULL);
2491
2492   return offset;
2493 }
2494
2495
2496
2497 static int
2498 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_) {
2499   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
2500                                       hf_index, BER_CLASS_APP, 3, TRUE, dissect_snmp_RRspPDU_U);
2501
2502   return offset;
2503 }
2504
2505
2506 static const value_string snmp_RegisterResponse_vals[] = {
2507   {   0, "rRspPDU" },
2508   {   1, "pDUs" },
2509   { 0, NULL }
2510 };
2511
2512 static const ber_choice_t RegisterResponse_choice[] = {
2513   {   0, &hf_snmp_rRspPDU        , BER_CLASS_APP, 3, BER_FLAGS_NOOWNTAG, dissect_snmp_RRspPDU },
2514   {   1, &hf_snmp_pDUs           , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG, dissect_snmp_PDUs },
2515   { 0, NULL, 0, 0, 0, NULL }
2516 };
2517
2518 static int
2519 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_) {
2520   offset = dissect_ber_choice(actx, tree, tvb, offset,
2521                                  RegisterResponse_choice, hf_index, ett_snmp_RegisterResponse,
2522                                  NULL);
2523
2524   return offset;
2525 }
2526
2527
2528 static const value_string snmp_SOutPDU_U_vals[] = {
2529   {   0, "commit" },
2530   {   1, "rollback" },
2531   { 0, NULL }
2532 };
2533
2534
2535 static int
2536 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_) {
2537   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
2538                                                 NULL);
2539
2540   return offset;
2541 }
2542
2543
2544
2545 static int
2546 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_) {
2547   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
2548                                       hf_index, BER_CLASS_APP, 4, TRUE, dissect_snmp_SOutPDU_U);
2549
2550   return offset;
2551 }
2552
2553
2554 static const value_string snmp_SMUX_PDUs_vals[] = {
2555   {   0, "open" },
2556   {   1, "close" },
2557   {   2, "registerRequest" },
2558   {   3, "registerResponse" },
2559   {   4, "commitOrRollback" },
2560   { 0, NULL }
2561 };
2562
2563 static const ber_choice_t SMUX_PDUs_choice[] = {
2564   {   0, &hf_snmp_open           , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG, dissect_snmp_OpenPDU },
2565   {   1, &hf_snmp_close          , BER_CLASS_APP, 1, BER_FLAGS_NOOWNTAG, dissect_snmp_ClosePDU },
2566   {   2, &hf_snmp_registerRequest, BER_CLASS_APP, 2, BER_FLAGS_NOOWNTAG, dissect_snmp_RReqPDU },
2567   {   3, &hf_snmp_registerResponse, BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG, dissect_snmp_RegisterResponse },
2568   {   4, &hf_snmp_commitOrRollback, BER_CLASS_APP, 4, BER_FLAGS_NOOWNTAG, dissect_snmp_SOutPDU },
2569   { 0, NULL, 0, 0, 0, NULL }
2570 };
2571
2572 static int
2573 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_) {
2574   offset = dissect_ber_choice(actx, tree, tvb, offset,
2575                                  SMUX_PDUs_choice, hf_index, ett_snmp_SMUX_PDUs,
2576                                  NULL);
2577
2578   return offset;
2579 }
2580
2581 /*--- PDUs ---*/
2582
2583 static void dissect_SMUX_PDUs_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {
2584   asn1_ctx_t asn1_ctx;
2585   asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
2586   dissect_snmp_SMUX_PDUs(FALSE, tvb, 0, &asn1_ctx, tree, hf_snmp_SMUX_PDUs_PDU);
2587 }
2588
2589
2590 /*--- End of included file: packet-snmp-fn.c ---*/
2591 #line 1399 "packet-snmp-template.c"
2592
2593
2594 guint
2595 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
2596     proto_tree *tree, int proto, gint ett, gboolean is_tcp)
2597 {
2598
2599         guint length_remaining;
2600         gint8 class;
2601         gboolean pc, ind = 0;
2602         gint32 tag;
2603         guint32 len;
2604         guint message_length;
2605         int start_offset = offset;
2606         guint32 version = 0;
2607
2608         proto_tree *snmp_tree = NULL;
2609         proto_item *item = NULL;
2610         asn1_ctx_t asn1_ctx;
2611         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
2612
2613
2614         usm_p.msg_tvb = tvb;
2615         usm_p.start_offset = offset_from_real_beginning(tvb,0) ;
2616         usm_p.engine_tvb = NULL;
2617         usm_p.user_tvb = NULL;
2618         usm_p.auth_item = NULL;
2619         usm_p.auth_tvb = NULL;
2620         usm_p.auth_offset = 0;
2621         usm_p.priv_tvb = NULL;
2622         usm_p.user_assoc = NULL;
2623         usm_p.authenticated = FALSE;
2624         usm_p.encrypted = FALSE;
2625         usm_p.boots = 0;
2626         usm_p.time = 0;
2627         usm_p.authOK = FALSE;
2628
2629         /*
2630          * This will throw an exception if we don't have any data left.
2631          * That's what we want.  (See "tcp_dissect_pdus()", which is
2632          * similar, but doesn't have to deal with ASN.1.
2633          * XXX - can we make "tcp_dissect_pdus()" provide enough
2634          * information to the "get_pdu_len" routine so that we could
2635          * have that routine deal with ASN.1, and just use
2636          * "tcp_dissect_pdus()"?)
2637          */
2638         length_remaining = tvb_ensure_length_remaining(tvb, offset);
2639
2640         /* NOTE: we have to parse the message piece by piece, since the
2641          * capture length may be less than the message length: a 'global'
2642          * parsing is likely to fail.
2643          */
2644
2645         /*
2646          * If this is SNMP-over-TCP, we might have to do reassembly
2647          * in order to read the "Sequence Of" header.
2648          */
2649         if (is_tcp && snmp_desegment && pinfo->can_desegment) {
2650                 /*
2651                  * This is TCP, and we should, and can, do reassembly.
2652                  *
2653                  * Is the "Sequence Of" header split across segment
2654                  * boundaries?  We requre at least 6 bytes for the
2655                  * header, which allows for a 4-byte length (ASN.1
2656                  * BER).
2657                  */
2658                 if (length_remaining < 6) {
2659                         pinfo->desegment_offset = offset;
2660                         pinfo->desegment_len = 6 - length_remaining;
2661
2662                         /*
2663                          * Return 0, which means "I didn't dissect anything
2664                          * because I don't have enough data - we need
2665                          * to desegment".
2666                          */
2667                         return 0;
2668                 }
2669         }
2670
2671         /*
2672          * OK, try to read the "Sequence Of" header; this gets the total
2673          * length of the SNMP message.
2674          */
2675         /* Set tree to 0 to not display internakl BER fields if option used.*/
2676         offset = dissect_ber_identifier(pinfo, 0, tvb, offset, &class, &pc, &tag);
2677         offset = dissect_ber_length(pinfo, 0, tvb, offset, &len, &ind);
2678
2679         message_length = len + 2;
2680         offset = dissect_ber_integer(FALSE, &asn1_ctx, 0, tvb, offset, -1, &version);
2681
2682
2683         /*
2684          * If this is SNMP-over-TCP, we might have to do reassembly
2685          * to get all of this message.
2686          */
2687         if (is_tcp && snmp_desegment && pinfo->can_desegment) {
2688                 /*
2689                  * Yes - is the message split across segment boundaries?
2690                  */
2691                 if (length_remaining < message_length) {
2692                         /*
2693                          * Yes.  Tell the TCP dissector where the data
2694                          * for this message starts in the data it handed
2695                          * us, and how many more bytes we need, and
2696                          * return.
2697                          */
2698                         pinfo->desegment_offset = start_offset;
2699                         pinfo->desegment_len =
2700                             message_length - length_remaining;
2701
2702                         /*
2703                          * Return 0, which means "I didn't dissect anything
2704                          * because I don't have enough data - we need
2705                          * to desegment".
2706                          */
2707                         return 0;
2708                 }
2709         }
2710
2711         next_tvb_init(&var_list);
2712
2713         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2714                 col_set_str(pinfo->cinfo, COL_PROTOCOL,
2715                     proto_get_protocol_short_name(find_protocol_by_id(proto)));
2716         }
2717
2718         if (tree) {
2719                 item = proto_tree_add_item(tree, proto, tvb, offset,
2720                     message_length, FALSE);
2721                 snmp_tree = proto_item_add_subtree(item, ett);
2722         }
2723
2724         switch (version){
2725         case 0: /* v1 */
2726         case 1: /* v2c */
2727                 offset = dissect_snmp_Message(FALSE , tvb, start_offset, &asn1_ctx, snmp_tree, -1);
2728                 break;
2729         case 2: /* v2u */
2730                 offset = dissect_snmp_Messagev2u(FALSE , tvb, start_offset, &asn1_ctx, snmp_tree, -1);
2731                 break;
2732                         /* v3 */
2733         case 3:
2734                 offset = dissect_snmp_SNMPv3Message(FALSE , tvb, start_offset, &asn1_ctx, snmp_tree, -1);
2735                 break;
2736         default:
2737                 /*
2738                  * Return the length remaining in the tvbuff, so
2739                  * if this is SNMP-over-TCP, our caller thinks there's
2740                  * nothing left to dissect.
2741                  */
2742                 proto_tree_add_text(snmp_tree, tvb, offset, -1,"Unknown version");
2743                 return length_remaining;
2744                 break;
2745         }
2746
2747         next_tvb_call(&var_list, pinfo, tree, NULL, data_handle);
2748
2749         return offset;
2750 }
2751
2752 static gint
2753 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2754 {
2755         conversation_t  *conversation;
2756         int offset;
2757         gint8 tmp_class;
2758         gboolean tmp_pc;
2759         gint32 tmp_tag;
2760         guint32 tmp_length;
2761         gboolean tmp_ind;
2762
2763         /*
2764          * See if this looks like SNMP or not. if not, return 0 so
2765          * wireshark can try som other dissector instead.
2766          */
2767         /* All SNMP packets are BER encoded and consist of a SEQUENCE
2768          * that spans the entire PDU. The first item is an INTEGER that
2769          * has the values 0-2 (version 1-3).
2770          * if not it is not snmp.
2771          */
2772         /* SNMP starts with a SEQUENCE */
2773         offset = get_ber_identifier(tvb, 0, &tmp_class, &tmp_pc, &tmp_tag);
2774         if((tmp_class!=BER_CLASS_UNI)||(tmp_tag!=BER_UNI_TAG_SEQUENCE)){
2775                 return 0;
2776         }
2777         /* then comes a length which spans the rest of the tvb */
2778         offset = get_ber_length(tvb, offset, &tmp_length, &tmp_ind);
2779         if(tmp_length!=(guint32)tvb_reported_length_remaining(tvb, offset)){
2780                 return 0;
2781         }
2782         /* then comes an INTEGER (version)*/
2783         offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
2784         if((tmp_class!=BER_CLASS_UNI)||(tmp_tag!=BER_UNI_TAG_INTEGER)){
2785                 return 0;
2786         }
2787         /* do we need to test that version is 0 - 2 (version1-3) ? */
2788
2789
2790         /*
2791          * The first SNMP packet goes to the SNMP port; the second one
2792          * may come from some *other* port, but goes back to the same
2793          * IP address and port as the ones from which the first packet
2794          * came; all subsequent packets presumably go between those two
2795          * IP addresses and ports.
2796          *
2797          * If this packet went to the SNMP port, we check to see if
2798          * there's already a conversation with one address/port pair
2799          * matching the source IP address and port of this packet,
2800          * the other address matching the destination IP address of this
2801          * packet, and any destination port.
2802          *
2803          * If not, we create one, with its address 1/port 1 pair being
2804          * the source address/port of this packet, its address 2 being
2805          * the destination address of this packet, and its port 2 being
2806          * wildcarded, and give it the SNMP dissector as a dissector.
2807          */
2808         if (pinfo->destport == UDP_PORT_SNMP) {
2809           conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_UDP,
2810                                            pinfo->srcport, 0, NO_PORT_B);
2811           if( (conversation == NULL) || (conversation->dissector_handle!=snmp_handle) ){
2812             conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, PT_UDP,
2813                                             pinfo->srcport, 0, NO_PORT2);
2814             conversation_set_dissector(conversation, snmp_handle);
2815           }
2816         }
2817
2818         return dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_snmp, ett_snmp, FALSE);
2819 }
2820 static void
2821 dissect_snmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2822 {
2823         int offset = 0;
2824         guint message_len;
2825
2826         while (tvb_reported_length_remaining(tvb, offset) > 0) {
2827                 message_len = dissect_snmp_pdu(tvb, 0, pinfo, tree,
2828                     proto_snmp, ett_snmp, TRUE);
2829                 if (message_len == 0) {
2830                         /*
2831                          * We don't have all the data for that message,
2832                          * so we need to do desegmentation;
2833                          * "dissect_snmp_pdu()" has set that up.
2834                          */
2835                         break;
2836                 }
2837                 offset += message_len;
2838         }
2839 }
2840
2841 static void
2842 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2843 {
2844         proto_tree *smux_tree = NULL;
2845         proto_item *item = NULL;
2846
2847         next_tvb_init(&var_list);
2848
2849         if (check_col(pinfo->cinfo, COL_PROTOCOL))
2850                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
2851
2852         if (tree) {
2853                 item = proto_tree_add_item(tree, proto_smux, tvb, 0, -1, FALSE);
2854                 smux_tree = proto_item_add_subtree(item, ett_smux);
2855         }
2856
2857         dissect_SMUX_PDUs_PDU(tvb, pinfo, tree);
2858 }
2859
2860
2861 /*
2862   MD5 Password to Key Algorithm
2863   from RFC 3414 A.2.1
2864 */
2865 static void snmp_usm_password_to_key_md5(const guint8 *password,
2866                                                                   guint   passwordlen,
2867                                                                   const guint8 *engineID,
2868                                                                   guint   engineLength,
2869                                                                   guint8 *key)  {
2870         md5_state_t     MD;
2871         guint8     *cp, password_buf[64];
2872         guint32      password_index = 0;
2873         guint32      count = 0, i;
2874         guint8          key1[16];
2875         md5_init(&MD);   /* initialize MD5 */
2876
2877         /**********************************************/
2878         /* Use while loop until we've done 1 Megabyte */
2879         /**********************************************/
2880         while (count < 1048576) {
2881                 cp = password_buf;
2882                 for (i = 0; i < 64; i++) {
2883                         /*************************************************/
2884                         /* Take the next octet of the password, wrapping */
2885                         /* to the beginning of the password as necessary.*/
2886                         /*************************************************/
2887                         *cp++ = password[password_index++ % passwordlen];
2888                 }
2889                 md5_append(&MD, password_buf, 64);
2890                 count += 64;
2891         }
2892         md5_finish(&MD, key1);          /* tell MD5 we're done */
2893
2894         /*****************************************************/
2895         /* Now localize the key with the engineID and pass   */
2896         /* through MD5 to produce final key                  */
2897         /* May want to ensure that engineLength <= 32,       */
2898         /* otherwise need to use a buffer larger than 64     */
2899         /*****************************************************/
2900
2901         md5_init(&MD);
2902         md5_append(&MD, key1, 16);
2903         md5_append(&MD, engineID, engineLength);
2904         md5_append(&MD, key1, 16);
2905         md5_finish(&MD, key);
2906
2907         return;
2908 }
2909
2910
2911
2912
2913 /*
2914    SHA1 Password to Key Algorithm COPIED from RFC 3414 A.2.2
2915  */
2916
2917 static void snmp_usm_password_to_key_sha1(const guint8 *password,
2918                                                                    guint   passwordlen,
2919                                                                    const guint8 *engineID,
2920                                                                    guint   engineLength,
2921                                                                    guint8 *key ) {
2922         sha1_context     SH;
2923         guint8     *cp, password_buf[72];
2924         guint32      password_index = 0;
2925         guint32      count = 0, i;
2926
2927         sha1_starts(&SH);   /* initialize SHA */
2928
2929         /**********************************************/
2930         /* Use while loop until we've done 1 Megabyte */
2931         /**********************************************/
2932         while (count < 1048576) {
2933                 cp = password_buf;
2934                 for (i = 0; i < 64; i++) {
2935                         /*************************************************/
2936                         /* Take the next octet of the password, wrapping */
2937                         /* to the beginning of the password as necessary.*/
2938                         /*************************************************/
2939                         *cp++ = password[password_index++ % passwordlen];
2940                 }
2941                 sha1_update (&SH, password_buf, 64);
2942                 count += 64;
2943         }
2944         sha1_finish(&SH, key);
2945
2946         /*****************************************************/
2947         /* Now localize the key with the engineID and pass   */
2948         /* through SHA to produce final key                  */
2949         /* May want to ensure that engineLength <= 32,       */
2950         /* otherwise need to use a buffer larger than 72     */
2951         /*****************************************************/
2952         memcpy(password_buf, key, 20);
2953         memcpy(password_buf+20, engineID, engineLength);
2954         memcpy(password_buf+20+engineLength, key, 20);
2955
2956         sha1_starts(&SH);
2957         sha1_update(&SH, password_buf, 40+engineLength);
2958         sha1_finish(&SH, key);
2959         return;
2960  }
2961
2962
2963 static void process_prefs(void) {}
2964
2965 static void* snmp_users_copy_cb(void* dest, const void* orig, unsigned len _U_) {
2966         const snmp_ue_assoc_t* o = orig;
2967         snmp_ue_assoc_t* d = dest;
2968
2969         d->auth_model = o->auth_model;
2970         d->user.authModel = auth_models[o->auth_model];
2971
2972         d->priv_proto = o->priv_proto;
2973         d->user.privProtocol = priv_protos[o->priv_proto];
2974
2975         d->user.userName.data = g_memdup(o->user.userName.data,o->user.userName.len);
2976         d->user.userName.len = o->user.userName.len;
2977
2978         d->user.authPassword.data = o->user.authPassword.data ? g_memdup(o->user.authPassword.data,o->user.authPassword.len) : NULL;
2979         d->user.authPassword.len = o->user.authPassword.len;
2980
2981         d->user.privPassword.data = o->user.privPassword.data ? g_memdup(o->user.privPassword.data,o->user.privPassword.len) : NULL;
2982         d->user.privPassword.len = o->user.privPassword.len;
2983
2984         d->engine.len = o->engine.len;
2985         if (o->engine.data) {
2986                 d->engine.data = g_memdup(o->engine.data,o->engine.len);
2987         }
2988
2989         d->user.authKey.data = o->user.authKey.data ? g_memdup(o->user.authKey.data,o->user.authKey.len) : NULL;
2990         d->user.authKey.len = o->user.authKey.len;
2991
2992         d->user.privKey.data = o->user.privKey.data ? g_memdup(o->user.privKey.data,o->user.privKey.len) : NULL;
2993         d->user.privKey.len = o->user.privKey.len;
2994
2995         return d;
2996 }
2997
2998 static void snmp_users_free_cb(void* p) {
2999         snmp_ue_assoc_t* ue = p;
3000         if (ue->user.userName.data) g_free(ue->user.userName.data);
3001         if (ue->user.authPassword.data) g_free(ue->user.authPassword.data);
3002         if (ue->user.privPassword.data) g_free(ue->user.privPassword.data);
3003         if (ue->user.authKey.data) g_free(ue->user.authKey.data);
3004         if (ue->user.privKey.data) g_free(ue->user.privKey.data);
3005         if (ue->engine.data) g_free(ue->engine.data);
3006 }
3007
3008 static void snmp_users_update_cb(void* p _U_, const char** err) {
3009         snmp_ue_assoc_t* ue = p;
3010         GString* es = g_string_new("");
3011
3012         *err = NULL;
3013
3014         if (! ue->user.userName.len) g_string_append(es,"no userName, ");
3015         if (ue->user.authPassword.len < 8) g_string_sprintfa(es,"short authPassword (%d), ", ue->user.authPassword.len);
3016         if (ue->user.privPassword.len < 8) g_string_sprintfa(es,"short privPassword (%d), ", ue->user.privPassword.len);
3017
3018         if (es->len) {
3019                 g_string_truncate(es,es->len-2);
3020                 *err = ep_strdup(es->str);
3021         }
3022
3023         g_string_free(es,TRUE);
3024
3025         return;
3026 }
3027
3028 UAT_LSTRING_CB_DEF(snmp_users,userName,snmp_ue_assoc_t,user.userName.data,user.userName.len)
3029 UAT_LSTRING_CB_DEF(snmp_users,authPassword,snmp_ue_assoc_t,user.authPassword.data,user.authPassword.len)
3030 UAT_LSTRING_CB_DEF(snmp_users,privPassword,snmp_ue_assoc_t,user.privPassword.data,user.privPassword.len)
3031 UAT_BUFFER_CB_DEF(snmp_users,engine_id,snmp_ue_assoc_t,engine.data,engine.len)
3032 UAT_VS_DEF(snmp_users,auth_model,snmp_ue_assoc_t,0,"MD5")
3033 UAT_VS_DEF(snmp_users,priv_proto,snmp_ue_assoc_t,0,"DES")
3034
3035         /*--- proto_register_snmp -------------------------------------------*/
3036 void proto_register_snmp(void) {
3037   /* List of fields */
3038   static hf_register_info hf[] = {
3039                 { &hf_snmp_v3_flags_auth,
3040                 { "Authenticated", "snmp.v3.flags.auth", FT_BOOLEAN, 8,
3041                     TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
3042                 { &hf_snmp_v3_flags_crypt,
3043                 { "Encrypted", "snmp.v3.flags.crypt", FT_BOOLEAN, 8,
3044                     TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
3045                 { &hf_snmp_v3_flags_report,
3046                 { "Reportable", "snmp.v3.flags.report", FT_BOOLEAN, 8,
3047                     TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
3048                 { &hf_snmp_engineid_conform, {
3049                     "Engine ID Conformance", "snmp.engineid.conform", FT_BOOLEAN, 8,
3050                     TFS(&tfs_snmp_engineid_conform), F_SNMP_ENGINEID_CONFORM, "Engine ID RFC3411 Conformance", HFILL }},
3051                 { &hf_snmp_engineid_enterprise, {
3052                     "Engine Enterprise ID", "snmp.engineid.enterprise", FT_UINT32, BASE_DEC,
3053                     VALS(sminmpec_values), 0, "Engine Enterprise ID", HFILL }},
3054                 { &hf_snmp_engineid_format, {
3055                     "Engine ID Format", "snmp.engineid.format", FT_UINT8, BASE_DEC,
3056                     VALS(snmp_engineid_format_vals), 0, "Engine ID Format", HFILL }},
3057                 { &hf_snmp_engineid_ipv4, {
3058                     "Engine ID Data: IPv4 address", "snmp.engineid.ipv4", FT_IPv4, BASE_NONE,
3059                     NULL, 0, "Engine ID Data: IPv4 address", HFILL }},
3060                 { &hf_snmp_engineid_ipv6, {
3061                     "Engine ID Data: IPv6 address", "snmp.engineid.ipv6", FT_IPv6, BASE_NONE,
3062                     NULL, 0, "Engine ID Data: IPv6 address", HFILL }},
3063                 { &hf_snmp_engineid_mac, {
3064                     "Engine ID Data: MAC address", "snmp.engineid.mac", FT_ETHER, BASE_NONE,
3065                     NULL, 0, "Engine ID Data: MAC address", HFILL }},
3066                 { &hf_snmp_engineid_text, {
3067                     "Engine ID Data: Text", "snmp.engineid.text", FT_STRING, BASE_NONE,
3068                     NULL, 0, "Engine ID Data: Text", HFILL }},
3069                 { &hf_snmp_engineid_time, {
3070                     "Engine ID Data: Time", "snmp.engineid.time", FT_ABSOLUTE_TIME, BASE_NONE,
3071                     NULL, 0, "Engine ID Data: Time", HFILL }},
3072                 { &hf_snmp_engineid_data, {
3073                     "Engine ID Data", "snmp.engineid.data", FT_BYTES, BASE_HEX,
3074                     NULL, 0, "Engine ID Data", HFILL }},
3075                   { &hf_snmp_msgAuthentication,
3076                                 { "Authentication", "snmp.v3.auth", FT_BOOLEAN, 8,
3077                                         TFS(&auth_flags), 0, "", HFILL }},
3078                   { &hf_snmp_decryptedPDU, {
3079                                         "Decrypted ScopedPDU", "snmp.decrypted_pdu", FT_BYTES, BASE_HEX,
3080                                         NULL, 0, "Decrypted PDU", HFILL }},
3081   { &hf_snmp_noSuchObject, { "noSuchObject", "snmp.noSuchObject", FT_NONE, BASE_NONE,  NULL, 0, "", HFILL }},
3082   { &hf_snmp_noSuchInstance, { "noSuchInstance", "snmp.noSuchInstance", FT_NONE, BASE_DEC,  NULL, 0, "", HFILL }},
3083   { &hf_snmp_endOfMibView, { "endOfMibView", "snmp.endOfMibView", FT_NONE, BASE_DEC,  NULL, 0, "", HFILL }},
3084   { &hf_snmp_unSpecified, { "unSpecified", "snmp.unSpecified", FT_NONE, BASE_DEC,  NULL, 0, "", HFILL }},
3085
3086   { &hf_snmp_integer32_value, { "Value (Integer32)", "snmp.value.int", FT_INT64, BASE_DEC,  NULL, 0, "", HFILL }},
3087   { &hf_snmp_octetstring_value, { "Value (OctetString)", "snmp.value.octets", FT_BYTES, BASE_NONE,  NULL, 0, "", HFILL }},
3088   { &hf_snmp_oid_value, { "Value (OID)", "snmp.value.oid", FT_OID, BASE_NONE,  NULL, 0, "", HFILL }},
3089   { &hf_snmp_null_value, { "Value (Null)", "snmp.value.null", FT_NONE, BASE_NONE,  NULL, 0, "", HFILL }},
3090   { &hf_snmp_ipv4_value, { "Value (IpAddress)", "snmp.value.ipv4", FT_IPv4, BASE_NONE,  NULL, 0, "", HFILL }},
3091   { &hf_snmp_ipv6_value, { "Value (IpAddress)", "snmp.value.ipv6", FT_IPv6, BASE_NONE,  NULL, 0, "", HFILL }},
3092   { &hf_snmp_anyaddress_value, { "Value (IpAddress)", "snmp.value.addr", FT_BYTES, BASE_DEC,  NULL, 0, "", HFILL }},
3093   { &hf_snmp_unsigned32_value, { "Value (Unsigned32)", "snmp.value.u32", FT_INT64, BASE_DEC,  NULL, 0, "", HFILL }},
3094   { &hf_snmp_gauge32_value, { "Value (Gauge32)", "snmp.value.g32", FT_INT64, BASE_DEC,  NULL, 0, "", HFILL }},
3095   { &hf_snmp_unknown_value, { "Value (Unknown)", "snmp.value.unk", FT_BYTES, BASE_NONE,  NULL, 0, "", HFILL }},
3096   { &hf_snmp_counter_value, { "Value (Counter32)", "snmp.value.counter", FT_UINT64, BASE_DEC,  NULL, 0, "", HFILL }},
3097   { &hf_snmp_big_counter_value, { "Value (Counter64)", "snmp.value.counter", FT_UINT64, BASE_DEC,  NULL, 0, "", HFILL }},
3098   { &hf_snmp_nsap_value, { "Value (NSAP)", "snmp.value.nsap", FT_UINT64, BASE_DEC,  NULL, 0, "", HFILL }},
3099   { &hf_snmp_timeticks_value, { "Value (Timeticks)", "snmp.value.timeticks", FT_UINT64, BASE_DEC,  NULL, 0, "", HFILL }},
3100   { &hf_snmp_opaque_value, { "Value (Opaque)", "snmp.value.opaque", FT_BYTES, BASE_NONE,  NULL, 0, "", HFILL }},
3101   { &hf_snmp_objectname, { "Object Name", "snmp.name", FT_OID, BASE_NONE,  NULL, 0, "", HFILL }},
3102   { &hf_snmp_scalar_instance_index, { "Scalar Instance Index", "snmp.name.index", FT_UINT64, BASE_DEC,  NULL, 0, "", HFILL }},
3103
3104
3105
3106 /*--- Included file: packet-snmp-hfarr.c ---*/
3107 #line 1 "packet-snmp-hfarr.c"
3108     { &hf_snmp_SMUX_PDUs_PDU,
3109       { "SMUX-PDUs", "snmp.SMUX_PDUs",
3110         FT_UINT32, BASE_DEC, VALS(snmp_SMUX_PDUs_vals), 0,
3111         "snmp.SMUX_PDUs", HFILL }},
3112     { &hf_snmp_version,
3113       { "version", "snmp.version",
3114         FT_INT32, BASE_DEC, VALS(snmp_Version_vals), 0,
3115         "snmp.Version", HFILL }},
3116     { &hf_snmp_community,
3117       { "community", "snmp.community",
3118         FT_STRING, BASE_HEX, NULL, 0,
3119         "snmp.OCTET_STRING", HFILL }},
3120     { &hf_snmp_data,
3121       { "data", "snmp.data",
3122         FT_UINT32, BASE_DEC, VALS(snmp_PDUs_vals), 0,
3123         "snmp.PDUs", HFILL }},
3124     { &hf_snmp_parameters,
3125       { "parameters", "snmp.parameters",
3126         FT_BYTES, BASE_HEX, NULL, 0,
3127         "snmp.OCTET_STRING", HFILL }},
3128     { &hf_snmp_datav2u,
3129       { "datav2u", "snmp.datav2u",
3130         FT_UINT32, BASE_DEC, VALS(snmp_T_datav2u_vals), 0,
3131         "snmp.T_datav2u", HFILL }},
3132     { &hf_snmp_v2u_plaintext,
3133       { "plaintext", "snmp.plaintext",
3134         FT_UINT32, BASE_DEC, VALS(snmp_PDUs_vals), 0,
3135         "snmp.PDUs", HFILL }},
3136     { &hf_snmp_encrypted,
3137       { "encrypted", "snmp.encrypted",
3138         FT_BYTES, BASE_HEX, NULL, 0,
3139         "snmp.OCTET_STRING", HFILL }},
3140     { &hf_snmp_msgAuthoritativeEngineID,
3141       { "msgAuthoritativeEngineID", "snmp.msgAuthoritativeEngineID",
3142         FT_BYTES, BASE_HEX, NULL, 0,
3143         "snmp.T_msgAuthoritativeEngineID", HFILL }},
3144     { &hf_snmp_msgAuthoritativeEngineBoots,
3145       { "msgAuthoritativeEngineBoots", "snmp.msgAuthoritativeEngineBoots",
3146         FT_UINT32, BASE_DEC, NULL, 0,
3147         "snmp.T_msgAuthoritativeEngineBoots", HFILL }},
3148     { &hf_snmp_msgAuthoritativeEngineTime,
3149       { "msgAuthoritativeEngineTime", "snmp.msgAuthoritativeEngineTime",
3150         FT_UINT32, BASE_DEC, NULL, 0,
3151         "snmp.T_msgAuthoritativeEngineTime", HFILL }},
3152     { &hf_snmp_msgUserName,
3153       { "msgUserName", "snmp.msgUserName",
3154         FT_STRING, BASE_HEX, NULL, 0,
3155         "snmp.T_msgUserName", HFILL }},
3156     { &hf_snmp_msgAuthenticationParameters,
3157       { "msgAuthenticationParameters", "snmp.msgAuthenticationParameters",
3158         FT_BYTES, BASE_HEX, NULL, 0,
3159         "snmp.T_msgAuthenticationParameters", HFILL }},
3160     { &hf_snmp_msgPrivacyParameters,
3161       { "msgPrivacyParameters", "snmp.msgPrivacyParameters",
3162         FT_BYTES, BASE_HEX, NULL, 0,
3163         "snmp.T_msgPrivacyParameters", HFILL }},
3164     { &hf_snmp_msgVersion,
3165       { "msgVersion", "snmp.msgVersion",
3166         FT_INT32, BASE_DEC, VALS(snmp_Version_vals), 0,
3167         "snmp.Version", HFILL }},
3168     { &hf_snmp_msgGlobalData,
3169       { "msgGlobalData", "snmp.msgGlobalData",
3170         FT_NONE, BASE_NONE, NULL, 0,
3171         "snmp.HeaderData", HFILL }},
3172     { &hf_snmp_msgSecurityParameters,
3173       { "msgSecurityParameters", "snmp.msgSecurityParameters",
3174         FT_BYTES, BASE_HEX, NULL, 0,
3175         "snmp.T_msgSecurityParameters", HFILL }},
3176     { &hf_snmp_msgData,
3177       { "msgData", "snmp.msgData",
3178         FT_UINT32, BASE_DEC, VALS(snmp_ScopedPduData_vals), 0,
3179         "snmp.ScopedPduData", HFILL }},
3180     { &hf_snmp_msgID,
3181       { "msgID", "snmp.msgID",
3182         FT_UINT32, BASE_DEC, NULL, 0,
3183         "snmp.INTEGER_0_2147483647", HFILL }},
3184     { &hf_snmp_msgMaxSize,
3185       { "msgMaxSize", "snmp.msgMaxSize",
3186         FT_UINT32, BASE_DEC, NULL, 0,
3187         "snmp.INTEGER_484_2147483647", HFILL }},
3188     { &hf_snmp_msgFlags,
3189       { "msgFlags", "snmp.msgFlags",
3190         FT_BYTES, BASE_HEX, NULL, 0,
3191         "snmp.T_msgFlags", HFILL }},
3192     { &hf_snmp_msgSecurityModel,
3193       { "msgSecurityModel", "snmp.msgSecurityModel",
3194         FT_UINT32, BASE_DEC, VALS(sec_models), 0,
3195         "snmp.T_msgSecurityModel", HFILL }},
3196     { &hf_snmp_plaintext,
3197       { "plaintext", "snmp.plaintext",
3198         FT_NONE, BASE_NONE, NULL, 0,
3199         "snmp.ScopedPDU", HFILL }},
3200     { &hf_snmp_encryptedPDU,
3201       { "encryptedPDU", "snmp.encryptedPDU",
3202         FT_BYTES, BASE_HEX, NULL, 0,
3203         "snmp.T_encryptedPDU", HFILL }},
3204     { &hf_snmp_contextEngineID,
3205       { "contextEngineID", "snmp.contextEngineID",
3206         FT_BYTES, BASE_HEX, NULL, 0,
3207         "snmp.SnmpEngineID", HFILL }},
3208     { &hf_snmp_contextName,
3209       { "contextName", "snmp.contextName",
3210         FT_BYTES, BASE_HEX, NULL, 0,
3211         "snmp.OCTET_STRING", HFILL }},
3212     { &hf_snmp_get_request,
3213       { "get-request", "snmp.get_request",
3214         FT_NONE, BASE_NONE, NULL, 0,
3215         "snmp.GetRequest_PDU", HFILL }},
3216     { &hf_snmp_get_next_request,
3217       { "get-next-request", "snmp.get_next_request",
3218         FT_NONE, BASE_NONE, NULL, 0,
3219         "snmp.GetNextRequest_PDU", HFILL }},
3220     { &hf_snmp_get_response,
3221       { "get-response", "snmp.get_response",
3222         FT_NONE, BASE_NONE, NULL, 0,
3223         "snmp.GetResponse_PDU", HFILL }},
3224     { &hf_snmp_set_request,
3225       { "set-request", "snmp.set_request",
3226         FT_NONE, BASE_NONE, NULL, 0,
3227         "snmp.SetRequest_PDU", HFILL }},
3228     { &hf_snmp_trap,
3229       { "trap", "snmp.trap",
3230         FT_NONE, BASE_NONE, NULL, 0,
3231         "snmp.Trap_PDU", HFILL }},
3232     { &hf_snmp_getBulkRequest,
3233       { "getBulkRequest", "snmp.getBulkRequest",
3234         FT_NONE, BASE_NONE, NULL, 0,
3235         "snmp.GetBulkRequest_PDU", HFILL }},
3236     { &hf_snmp_informRequest,
3237       { "informRequest", "snmp.informRequest",
3238         FT_NONE, BASE_NONE, NULL, 0,
3239         "snmp.InformRequest_PDU", HFILL }},
3240     { &hf_snmp_sNMPv2_Trap,
3241       { "sNMPv2-Trap", "snmp.sNMPv2_Trap",
3242         FT_NONE, BASE_NONE, NULL, 0,
3243         "snmp.SNMPv2_Trap_PDU", HFILL }},
3244     { &hf_snmp_report,
3245       { "report", "snmp.report",
3246         FT_NONE, BASE_NONE, NULL, 0,
3247         "snmp.Report_PDU", HFILL }},
3248     { &hf_snmp_request_id,
3249       { "request-id", "snmp.request_id",
3250         FT_INT32, BASE_DEC, NULL, 0,
3251         "snmp.INTEGER", HFILL }},
3252     { &hf_snmp_error_status,
3253       { "error-status", "snmp.error_status",
3254         FT_INT32, BASE_DEC, VALS(snmp_T_error_status_vals), 0,
3255         "snmp.T_error_status", HFILL }},
3256     { &hf_snmp_error_index,
3257       { "error-index", "snmp.error_index",
3258         FT_INT32, BASE_DEC, NULL, 0,
3259         "snmp.INTEGER", HFILL }},
3260     { &hf_snmp_variable_bindings,
3261       { "variable-bindings", "snmp.variable_bindings",
3262         FT_UINT32, BASE_DEC, NULL, 0,
3263         "snmp.VarBindList", HFILL }},
3264     { &hf_snmp_bulkPDU_request_id,
3265       { "request-id", "snmp.request_id",
3266         FT_INT32, BASE_DEC, NULL, 0,
3267         "snmp.Integer32", HFILL }},
3268     { &hf_snmp_non_repeaters,
3269       { "non-repeaters", "snmp.non_repeaters",
3270         FT_UINT32, BASE_DEC, NULL, 0,
3271         "snmp.INTEGER_0_2147483647", HFILL }},
3272     { &hf_snmp_max_repetitions,
3273       { "max-repetitions", "snmp.max_repetitions",
3274         FT_UINT32, BASE_DEC, NULL, 0,
3275         "snmp.INTEGER_0_2147483647", HFILL }},
3276     { &hf_snmp_enterprise,
3277       { "enterprise", "snmp.enterprise",
3278         FT_OID, BASE_NONE, NULL, 0,
3279         "snmp.EnterpriseOID", HFILL }},
3280     { &hf_snmp_agent_addr,
3281       { "agent-addr", "snmp.agent_addr",
3282         FT_IPv4, BASE_NONE, NULL, 0,
3283         "snmp.NetworkAddress", HFILL }},
3284     { &hf_snmp_generic_trap,
3285       { "generic-trap", "snmp.generic_trap",
3286         FT_INT32, BASE_DEC, VALS(snmp_T_generic_trap_vals), 0,
3287         "snmp.T_generic_trap", HFILL }},
3288     { &hf_snmp_specific_trap,
3289       { "specific-trap", "snmp.specific_trap",
3290         FT_INT32, BASE_DEC, NULL, 0,
3291         "snmp.INTEGER", HFILL }},
3292     { &hf_snmp_time_stamp,
3293       { "time-stamp", "snmp.time_stamp",
3294         FT_UINT32, BASE_DEC, NULL, 0,
3295         "snmp.TimeTicks", HFILL }},
3296     { &hf_snmp_name,
3297       { "name", "snmp.name",
3298         FT_OID, BASE_NONE, NULL, 0,
3299         "snmp.ObjectName", HFILL }},
3300     { &hf_snmp_valueType,
3301       { "valueType", "snmp.valueType",
3302         FT_NONE, BASE_NONE, NULL, 0,
3303         "snmp.NULL", HFILL }},
3304     { &hf_snmp_VarBindList_item,
3305       { "Item", "snmp.VarBindList_item",
3306         FT_NONE, BASE_NONE, NULL, 0,
3307         "snmp.VarBind", HFILL }},
3308     { &hf_snmp_open,
3309       { "open", "snmp.open",
3310         FT_UINT32, BASE_DEC, VALS(snmp_OpenPDU_vals), 0,
3311         "snmp.OpenPDU", HFILL }},
3312     { &hf_snmp_close,
3313       { "close", "snmp.close",
3314         FT_INT32, BASE_DEC, VALS(snmp_ClosePDU_U_vals), 0,
3315         "snmp.ClosePDU", HFILL }},
3316     { &hf_snmp_registerRequest,
3317       { "registerRequest", "snmp.registerRequest",
3318         FT_NONE, BASE_NONE, NULL, 0,
3319         "snmp.RReqPDU", HFILL }},
3320     { &hf_snmp_registerResponse,
3321       { "registerResponse", "snmp.registerResponse",
3322         FT_UINT32, BASE_DEC, VALS(snmp_RegisterResponse_vals), 0,
3323         "snmp.RegisterResponse", HFILL }},
3324     { &hf_snmp_commitOrRollback,
3325       { "commitOrRollback", "snmp.commitOrRollback",
3326         FT_INT32, BASE_DEC, VALS(snmp_SOutPDU_U_vals), 0,
3327         "snmp.SOutPDU", HFILL }},
3328     { &hf_snmp_rRspPDU,
3329       { "rRspPDU", "snmp.rRspPDU",
3330         FT_INT32, BASE_DEC, VALS(snmp_RRspPDU_U_vals), 0,
3331         "snmp.RRspPDU", HFILL }},
3332     { &hf_snmp_pDUs,
3333       { "pDUs", "snmp.pDUs",
3334         FT_UINT32, BASE_DEC, VALS(snmp_PDUs_vals), 0,
3335         "snmp.PDUs", HFILL }},
3336     { &hf_snmp_smux_simple,
3337       { "smux-simple", "snmp.smux_simple",
3338         FT_NONE, BASE_NONE, NULL, 0,
3339         "snmp.SimpleOpen", HFILL }},
3340     { &hf_snmp_smux_version,
3341       { "smux-version", "snmp.smux_version",
3342         FT_INT32, BASE_DEC, VALS(snmp_T_smux_version_vals), 0,
3343         "snmp.T_smux_version", HFILL }},
3344     { &hf_snmp_identity,
3345       { "identity", "snmp.identity",
3346         FT_OID, BASE_NONE, NULL, 0,
3347         "snmp.OBJECT_IDENTIFIER", HFILL }},
3348     { &hf_snmp_description,
3349       { "description", "snmp.description",
3350         FT_BYTES, BASE_HEX, NULL, 0,
3351         "snmp.DisplayString", HFILL }},
3352     { &hf_snmp_password,
3353       { "password", "snmp.password",
3354         FT_BYTES, BASE_HEX, NULL, 0,
3355         "snmp.OCTET_STRING", HFILL }},
3356     { &hf_snmp_subtree,
3357       { "subtree", "snmp.subtree",
3358         FT_OID, BASE_NONE, NULL, 0,
3359         "snmp.ObjectName", HFILL }},
3360     { &hf_snmp_priority,
3361       { "priority", "snmp.priority",
3362         FT_INT32, BASE_DEC, NULL, 0,
3363         "snmp.INTEGER_M1_2147483647", HFILL }},
3364     { &hf_snmp_operation,
3365       { "operation", "snmp.operation",
3366         FT_INT32, BASE_DEC, VALS(snmp_T_operation_vals), 0,
3367         "snmp.T_operation", HFILL }},
3368
3369 /*--- End of included file: packet-snmp-hfarr.c ---*/
3370 #line 1913 "packet-snmp-template.c"
3371   };
3372
3373   /* List of subtrees */
3374   static gint *ett[] = {
3375           &ett_snmp,
3376           &ett_engineid,
3377           &ett_msgFlags,
3378           &ett_encryptedPDU,
3379           &ett_decrypted,
3380           &ett_authParameters,
3381           &ett_internet,
3382           &ett_varbind,
3383           &ett_name,
3384           &ett_value,
3385           &ett_decoding_error,
3386
3387 /*--- Included file: packet-snmp-ettarr.c ---*/
3388 #line 1 "packet-snmp-ettarr.c"
3389     &ett_snmp_Message,
3390     &ett_snmp_Messagev2u,
3391     &ett_snmp_T_datav2u,
3392     &ett_snmp_UsmSecurityParameters,
3393     &ett_snmp_SNMPv3Message,
3394     &ett_snmp_HeaderData,
3395     &ett_snmp_ScopedPduData,
3396     &ett_snmp_ScopedPDU,
3397     &ett_snmp_PDUs,
3398     &ett_snmp_PDU,
3399     &ett_snmp_BulkPDU,
3400     &ett_snmp_Trap_PDU_U,
3401     &ett_snmp_VarBind,
3402     &ett_snmp_VarBindList,
3403     &ett_snmp_SMUX_PDUs,
3404     &ett_snmp_RegisterResponse,
3405     &ett_snmp_OpenPDU,
3406     &ett_snmp_SimpleOpen_U,
3407     &ett_snmp_RReqPDU_U,
3408
3409 /*--- End of included file: packet-snmp-ettarr.c ---*/
3410 #line 1929 "packet-snmp-template.c"
3411   };
3412   module_t *snmp_module;
3413   static uat_field_t users_fields[] = {
3414           UAT_FLD_BUFFER(snmp_users,engine_id,"Engine-id for this entry (empty = any)"),
3415           UAT_FLD_LSTRING(snmp_users,userName,"The username"),
3416           UAT_FLD_VS(snmp_users,auth_model,auth_types,"Algorithm to be used for authentication."),
3417           UAT_FLD_LSTRING(snmp_users,authPassword,"The password used for authenticating packets for this entry"),
3418           UAT_FLD_VS(snmp_users,priv_proto,priv_types,"Algorithm to be used for privacy."),
3419           UAT_FLD_LSTRING(snmp_users,privPassword,"The password used for encrypting packets for this entry"),
3420           UAT_END_FIELDS
3421   };
3422
3423   assocs_uat = uat_new("SNMP Users",
3424                                            sizeof(snmp_ue_assoc_t),
3425                                            "snmp_users",
3426                                            TRUE,
3427                                            (void**)&ueas,
3428                                            &num_ueas,
3429                                            UAT_CAT_CRYPTO,
3430                                            "ChSNMPUsersSection",
3431                                            snmp_users_copy_cb,
3432                                            snmp_users_update_cb,
3433                                            snmp_users_free_cb,
3434                                            users_fields);
3435
3436   /* Register protocol */
3437   proto_snmp = proto_register_protocol(PNAME, PSNAME, PFNAME);
3438   new_register_dissector("snmp", dissect_snmp, proto_snmp);
3439
3440   /* Register fields and subtrees */
3441   proto_register_field_array(proto_snmp, hf, array_length(hf));
3442   proto_register_subtree_array(ett, array_length(ett));
3443
3444
3445         /* Register configuration preferences */
3446         snmp_module = prefs_register_protocol(proto_snmp, process_prefs);
3447         prefs_register_bool_preference(snmp_module, "display_oid",
3448                 "Show SNMP OID in info column",
3449                 "Whether the SNMP OID should be shown in the info column",
3450                 &display_oid);
3451
3452         prefs_register_obsolete_preference(snmp_module, "mib_modules");
3453         prefs_register_obsolete_preference(snmp_module, "users_file");
3454
3455         prefs_register_bool_preference(snmp_module, "desegment",
3456             "Reassemble SNMP-over-TCP messages\nspanning multiple TCP segments",
3457             "Whether the SNMP dissector should reassemble messages spanning multiple TCP segments."
3458             " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3459             &snmp_desegment);
3460
3461   prefs_register_bool_preference(snmp_module, "var_in_tree",
3462                 "Display dissected variables inside SNMP tree",
3463                 "ON - display dissected variables inside SNMP tree, OFF - display dissected variables in root tree after SNMP",
3464                 &snmp_var_in_tree);
3465
3466   prefs_register_uat_preference(snmp_module, "users_table",
3467                                                                 "Users Table",
3468                                                                 "Table of engine-user associations used for authentication and decryption",
3469                                                                 assocs_uat);
3470
3471
3472         value_sub_dissectors_table = register_dissector_table("snmp.variable_oid","SNMP Variable OID", FT_STRING, BASE_NONE);
3473
3474         register_init_routine(renew_ue_cache);
3475 }
3476
3477
3478 /*--- proto_reg_handoff_snmp ---------------------------------------*/
3479 void proto_reg_handoff_snmp(void) {
3480         dissector_handle_t snmp_tcp_handle;
3481
3482         snmp_handle = find_dissector("snmp");
3483
3484         dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
3485         dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
3486         dissector_add("udp.port", UDP_PORT_SNMP_PATROL, snmp_handle);
3487         dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
3488         dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
3489         dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
3490         dissector_add("hpext.dxsap", HPEXT_SNMP, snmp_handle);
3491
3492         snmp_tcp_handle = create_dissector_handle(dissect_snmp_tcp, proto_snmp);
3493         dissector_add("tcp.port", TCP_PORT_SNMP, snmp_tcp_handle);
3494         dissector_add("tcp.port", TCP_PORT_SNMP_TRAP, snmp_tcp_handle);
3495
3496         data_handle = find_dissector("data");
3497
3498         /*
3499          * Process preference settings.
3500          *
3501          * We can't do this in the register routine, as preferences aren't
3502          * read until all dissector register routines have been called (so
3503          * that all dissector preferences have been registered).
3504          */
3505         process_prefs();
3506
3507 }
3508
3509 void
3510 proto_register_smux(void)
3511 {
3512         static hf_register_info hf[] = {
3513                 { &hf_smux_version,
3514                 { "Version", "smux.version", FT_UINT8, BASE_DEC, NULL,
3515                     0x0, "", HFILL }},
3516                 { &hf_smux_pdutype,
3517                 { "PDU type", "smux.pdutype", FT_UINT8, BASE_DEC, VALS(smux_types),
3518                     0x0, "", HFILL }},
3519         };
3520         static gint *ett[] = {
3521                 &ett_smux,
3522         };
3523
3524         proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
3525             "SMUX", "smux");
3526         proto_register_field_array(proto_smux, hf, array_length(hf));
3527         proto_register_subtree_array(ett, array_length(ett));
3528
3529 }
3530
3531 void
3532 proto_reg_handoff_smux(void)
3533 {
3534         dissector_handle_t smux_handle;
3535
3536         smux_handle = create_dissector_handle(dissect_smux, proto_smux);
3537         dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);
3538 }
3539
3540