1 /* Do not modify this file. Changes will be overwritten. */
2 /* Generated automatically by the ASN.1 to Wireshark dissector compiler */
4 /* asn2wrs.py -b -q -L -p snmp -c ./snmp.cnf -s ./packet-snmp-template -D . -O ../.. snmp.asn */
7 * Routines for SNMP (simple network management protocol)
8 * Copyright (C) 1998 Didier Jorand
10 * See RFC 1157 for SNMPv1.
12 * See RFCs 1901, 1905, and 1906 for SNMPv2c.
14 * See RFCs 1905, 1906, 1909, and 1910 for SNMPv2u [historic].
16 * See RFCs 2570-2576 for SNMPv3
17 * Updated to use the asn2wrs compiler made by Tomas Kukosa
18 * Copyright (C) 2005 - 2006 Anders Broman [AT] ericsson.com
20 * See RFC 3414 for User-based Security Model for SNMPv3
21 * See RFC 3826 for (AES) Cipher Algorithm in the SNMP USM
22 * See RFC 2578 for Structure of Management Information Version 2 (SMIv2)
23 * Copyright (C) 2007 Luis E. Garcia Ontanon <luis@ontanon.org>
25 * Wireshark - Network traffic analyzer
26 * By Gerald Combs <gerald@wireshark.org>
27 * Copyright 1998 Gerald Combs
31 * GXSNMP -- An snmp mangament application
32 * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
33 * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
35 * SPDX-License-Identifier: GPL-2.0-or-later
40 #define D(args) do {printf args; fflush(stdout); } while(0)
45 #include <epan/packet.h>
46 #include <epan/strutil.h>
47 #include <epan/conversation.h>
48 #include <epan/etypes.h>
49 #include <epan/prefs.h>
50 #include <epan/addr_resolv.h>
51 #include <epan/next_tvb.h>
53 #include <epan/asn1.h>
54 #include <epan/expert.h>
55 #include <epan/oids.h>
56 #include <epan/srt_table.h>
59 #include <wsutil/array.h>
60 #include "packet-ipx.h"
61 #include "packet-hpext.h"
62 #include "packet-ber.h"
63 #include "packet-snmp.h"
64 #include <wsutil/wsgcrypt.h>
66 #define PNAME "Simple Network Management Protocol"
70 #define UDP_PORT_SNMP 161
71 #define UDP_PORT_SNMP_TRAP 162
72 #define TCP_PORT_SNMP 161
73 #define TCP_PORT_SNMP_TRAP 162
74 #define TCP_PORT_SMUX 199
75 #define UDP_PORT_SNMP_PATROL 8161
76 #define SNMP_NUM_PROCEDURES 8
78 /* Initialize the protocol and registered fields */
80 static int proto_snmp
;
81 static int proto_smux
;
83 static bool display_oid
= true;
84 static bool snmp_var_in_tree
= true;
86 void proto_register_snmp(void);
87 void proto_reg_handoff_snmp(void);
88 void proto_register_smux(void);
89 void proto_reg_handoff_smux(void);
91 static void snmp_usm_password_to_key(const snmp_usm_auth_model_t model
, const uint8_t *password
, unsigned passwordlen
,
92 const uint8_t *engineID
, unsigned engineLength
, uint8_t *key
);
94 static tvbuff_t
* snmp_usm_priv_des(snmp_usm_params_t
*, tvbuff_t
*, packet_info
*pinfo
, char const**);
95 static tvbuff_t
* snmp_usm_priv_aes128(snmp_usm_params_t
*, tvbuff_t
*, packet_info
*pinfo
, char const**);
96 static tvbuff_t
* snmp_usm_priv_aes192(snmp_usm_params_t
*, tvbuff_t
*, packet_info
*pinfo
, char const**);
97 static tvbuff_t
* snmp_usm_priv_aes256(snmp_usm_params_t
*, tvbuff_t
*, packet_info
*pinfo
, char const**);
99 static bool snmp_usm_auth(const packet_info
*pinfo
, const snmp_usm_auth_model_t model
, snmp_usm_params_t
* p
, uint8_t**, unsigned*, char const**);
101 static const value_string auth_types
[] = {
102 {SNMP_USM_AUTH_MD5
,"MD5"},
103 {SNMP_USM_AUTH_SHA1
,"SHA1"},
104 {SNMP_USM_AUTH_SHA2_224
,"SHA2-224"},
105 {SNMP_USM_AUTH_SHA2_256
,"SHA2-256"},
106 {SNMP_USM_AUTH_SHA2_384
,"SHA2-384"},
107 {SNMP_USM_AUTH_SHA2_512
,"SHA2-512"},
111 static const unsigned auth_hash_len
[] = {
114 HASH_SHA2_224_LENGTH
,
115 HASH_SHA2_256_LENGTH
,
116 HASH_SHA2_384_LENGTH
,
120 static const unsigned auth_tag_len
[] = {
129 static const enum gcry_md_algos auth_hash_algo
[] = {
139 #define PRIV_AES128 1
140 #define PRIV_AES192 2
141 #define PRIV_AES256 3
143 static const value_string priv_types
[] = {
145 { PRIV_AES128
, "AES" },
146 { PRIV_AES192
, "AES192" },
147 { PRIV_AES256
, "AES256" },
150 static snmp_usm_decoder_t priv_protos
[] = {
152 snmp_usm_priv_aes128
,
153 snmp_usm_priv_aes192
,
157 #define PRIVKEYEXP_USM_3DESDESEDE_00 0
158 #define PRIVKEYEXP_AGENTPP 1
160 static const value_string priv_key_exp_types
[] = {
161 { PRIVKEYEXP_USM_3DESDESEDE_00
, "draft-reeder-snmpv3-usm-3desede-00" },
162 { PRIVKEYEXP_AGENTPP
, "AGENT++" },
166 static snmp_ue_assoc_t
* ueas
;
167 static unsigned num_ueas
;
168 static snmp_ue_assoc_t
* localized_ues
;
169 static snmp_ue_assoc_t
* unlocalized_ues
;
172 /* Variables used for handling enterprise specific trap types */
173 typedef struct _snmp_st_assoc_t
{
178 static unsigned num_specific_traps
;
179 static snmp_st_assoc_t
*specific_traps
;
180 static const char *enterprise_oid
;
181 static unsigned generic_trap
;
182 static uint32_t snmp_version
;
183 static uint32_t RequestID
= -1;
185 static snmp_usm_params_t usm_p
;
188 #define TH_CRYPT 0x02
189 #define TH_REPORT 0x04
191 /* desegmentation of SNMP-over-TCP */
192 static bool snmp_desegment
= true;
194 /* Global variables */
196 uint32_t MsgSecurityModel
;
197 tvbuff_t
*oid_tvb
=NULL
;
198 tvbuff_t
*value_tvb
=NULL
;
200 static dissector_handle_t snmp_handle
;
201 static dissector_handle_t snmp_tcp_handle
;
202 static dissector_handle_t data_handle
;
203 static dissector_handle_t smux_handle
;
205 static next_tvb_list_t
*var_list
;
207 static int hf_snmp_response_in
;
208 static int hf_snmp_response_to
;
209 static int hf_snmp_time
;
211 static int hf_snmp_v3_flags_auth
;
212 static int hf_snmp_v3_flags_crypt
;
213 static int hf_snmp_v3_flags_report
;
215 static int hf_snmp_engineid_conform
;
216 static int hf_snmp_engineid_enterprise
;
217 static int hf_snmp_engineid_format
;
218 static int hf_snmp_engineid_ipv4
;
219 static int hf_snmp_engineid_ipv6
;
220 static int hf_snmp_engineid_cisco_type
;
221 static int hf_snmp_engineid_mac
;
222 static int hf_snmp_engineid_text
;
223 static int hf_snmp_engineid_time
;
224 static int hf_snmp_engineid_data
;
225 static int hf_snmp_decryptedPDU
;
226 static int hf_snmp_msgAuthentication
;
228 static int hf_snmp_noSuchObject
;
229 static int hf_snmp_noSuchInstance
;
230 static int hf_snmp_endOfMibView
;
231 static int hf_snmp_unSpecified
;
233 static int hf_snmp_integer32_value
;
234 static int hf_snmp_octetstring_value
;
235 static int hf_snmp_oid_value
;
236 static int hf_snmp_null_value
;
237 static int hf_snmp_ipv4_value
;
238 static int hf_snmp_ipv6_value
;
239 static int hf_snmp_anyaddress_value
;
240 static int hf_snmp_unsigned32_value
;
241 static int hf_snmp_unknown_value
;
242 static int hf_snmp_opaque_value
;
243 static int hf_snmp_nsap_value
;
244 static int hf_snmp_counter_value
;
245 static int hf_snmp_timeticks_value
;
246 static int hf_snmp_big_counter_value
;
247 static int hf_snmp_gauge32_value
;
249 static int hf_snmp_objectname
;
250 static int hf_snmp_scalar_instance_index
;
252 static int hf_snmp_var_bind_str
;
253 static int hf_snmp_agentid_trailer
;
255 static int hf_snmp_SMUX_PDUs_PDU
; /* SMUX_PDUs */
256 static int hf_snmp_version
; /* Version */
257 static int hf_snmp_community
; /* Community */
258 static int hf_snmp_data
; /* PDUs */
259 static int hf_snmp_parameters
; /* OCTET_STRING */
260 static int hf_snmp_datav2u
; /* T_datav2u */
261 static int hf_snmp_v2u_plaintext
; /* PDUs */
262 static int hf_snmp_encrypted
; /* OCTET_STRING */
263 static int hf_snmp_msgAuthoritativeEngineID
; /* T_msgAuthoritativeEngineID */
264 static int hf_snmp_msgAuthoritativeEngineBoots
; /* T_msgAuthoritativeEngineBoots */
265 static int hf_snmp_msgAuthoritativeEngineTime
; /* T_msgAuthoritativeEngineTime */
266 static int hf_snmp_msgUserName
; /* T_msgUserName */
267 static int hf_snmp_msgAuthenticationParameters
; /* T_msgAuthenticationParameters */
268 static int hf_snmp_msgPrivacyParameters
; /* T_msgPrivacyParameters */
269 static int hf_snmp_msgVersion
; /* Version */
270 static int hf_snmp_msgGlobalData
; /* HeaderData */
271 static int hf_snmp_msgSecurityParameters
; /* T_msgSecurityParameters */
272 static int hf_snmp_msgData
; /* ScopedPduData */
273 static int hf_snmp_msgID
; /* INTEGER_0_2147483647 */
274 static int hf_snmp_msgMaxSize
; /* INTEGER_484_2147483647 */
275 static int hf_snmp_msgFlags
; /* T_msgFlags */
276 static int hf_snmp_msgSecurityModel
; /* T_msgSecurityModel */
277 static int hf_snmp_plaintext
; /* ScopedPDU */
278 static int hf_snmp_encryptedPDU
; /* T_encryptedPDU */
279 static int hf_snmp_contextEngineID
; /* SnmpEngineID */
280 static int hf_snmp_contextName
; /* OCTET_STRING */
281 static int hf_snmp_get_request
; /* GetRequest_PDU */
282 static int hf_snmp_get_next_request
; /* GetNextRequest_PDU */
283 static int hf_snmp_get_response
; /* GetResponse_PDU */
284 static int hf_snmp_set_request
; /* SetRequest_PDU */
285 static int hf_snmp_trap
; /* Trap_PDU */
286 static int hf_snmp_getBulkRequest
; /* GetBulkRequest_PDU */
287 static int hf_snmp_informRequest
; /* InformRequest_PDU */
288 static int hf_snmp_snmpV2_trap
; /* SNMPv2_Trap_PDU */
289 static int hf_snmp_report
; /* Report_PDU */
290 static int hf_snmp_request_id
; /* T_request_id */
291 static int hf_snmp_error_status
; /* T_error_status */
292 static int hf_snmp_error_index
; /* INTEGER */
293 static int hf_snmp_variable_bindings
; /* VarBindList */
294 static int hf_snmp_bulkPDU_request_id
; /* Integer32 */
295 static int hf_snmp_non_repeaters
; /* INTEGER_0_2147483647 */
296 static int hf_snmp_max_repetitions
; /* INTEGER_0_2147483647 */
297 static int hf_snmp_enterprise
; /* EnterpriseOID */
298 static int hf_snmp_agent_addr
; /* NetworkAddress */
299 static int hf_snmp_generic_trap
; /* GenericTrap */
300 static int hf_snmp_specific_trap
; /* SpecificTrap */
301 static int hf_snmp_time_stamp
; /* TimeTicks */
302 static int hf_snmp_name
; /* ObjectName */
303 static int hf_snmp_valueType
; /* ValueType */
304 static int hf_snmp_VarBindList_item
; /* VarBind */
305 static int hf_snmp_open
; /* OpenPDU */
306 static int hf_snmp_close
; /* ClosePDU */
307 static int hf_snmp_registerRequest
; /* RReqPDU */
308 static int hf_snmp_registerResponse
; /* RegisterResponse */
309 static int hf_snmp_commitOrRollback
; /* SOutPDU */
310 static int hf_snmp_rRspPDU
; /* RRspPDU */
311 static int hf_snmp_pDUs
; /* PDUs */
312 static int hf_snmp_smux_simple
; /* SimpleOpen */
313 static int hf_snmp_smux_version
; /* T_smux_version */
314 static int hf_snmp_identity
; /* OBJECT_IDENTIFIER */
315 static int hf_snmp_description
; /* DisplayString */
316 static int hf_snmp_password
; /* OCTET_STRING */
317 static int hf_snmp_subtree
; /* ObjectName */
318 static int hf_snmp_priority
; /* INTEGER_M1_2147483647 */
319 static int hf_snmp_operation
; /* T_operation */
321 /* Initialize the subtree pointers */
324 static int ett_engineid
;
325 static int ett_msgFlags
;
326 static int ett_encryptedPDU
;
327 static int ett_decrypted
;
328 static int ett_authParameters
;
329 static int ett_internet
;
330 static int ett_varbind
;
332 static int ett_value
;
333 static int ett_decoding_error
;
335 static int ett_snmp_Message
;
336 static int ett_snmp_Messagev2u
;
337 static int ett_snmp_T_datav2u
;
338 static int ett_snmp_UsmSecurityParameters
;
339 static int ett_snmp_SNMPv3Message
;
340 static int ett_snmp_HeaderData
;
341 static int ett_snmp_ScopedPduData
;
342 static int ett_snmp_ScopedPDU
;
343 static int ett_snmp_PDUs
;
344 static int ett_snmp_PDU
;
345 static int ett_snmp_BulkPDU
;
346 static int ett_snmp_Trap_PDU_U
;
347 static int ett_snmp_VarBind
;
348 static int ett_snmp_VarBindList
;
349 static int ett_snmp_SMUX_PDUs
;
350 static int ett_snmp_RegisterResponse
;
351 static int ett_snmp_OpenPDU
;
352 static int ett_snmp_SimpleOpen_U
;
353 static int ett_snmp_RReqPDU_U
;
355 static expert_field ei_snmp_failed_decrypted_data_pdu
;
356 static expert_field ei_snmp_decrypted_data_bad_formatted
;
357 static expert_field ei_snmp_verify_authentication_error
;
358 static expert_field ei_snmp_authentication_ok
;
359 static expert_field ei_snmp_authentication_error
;
360 static expert_field ei_snmp_varbind_not_uni_class_seq
;
361 static expert_field ei_snmp_varbind_has_indicator
;
362 static expert_field ei_snmp_objectname_not_oid
;
363 static expert_field ei_snmp_objectname_has_indicator
;
364 static expert_field ei_snmp_value_not_primitive_encoding
;
365 static expert_field ei_snmp_invalid_oid
;
366 static expert_field ei_snmp_varbind_wrong_tag
;
367 static expert_field ei_snmp_varbind_response
;
368 static expert_field ei_snmp_no_instance_subid
;
369 static expert_field ei_snmp_wrong_num_of_subids
;
370 static expert_field ei_snmp_index_suboid_too_short
;
371 static expert_field ei_snmp_unimplemented_instance_index
;
372 static expert_field ei_snmp_index_suboid_len0
;
373 static expert_field ei_snmp_index_suboid_too_long
;
374 static expert_field ei_snmp_index_string_too_long
;
375 static expert_field ei_snmp_column_parent_not_row
;
376 static expert_field ei_snmp_uint_too_large
;
377 static expert_field ei_snmp_int_too_large
;
378 static expert_field ei_snmp_integral_value0
;
379 static expert_field ei_snmp_missing_mib
;
380 static expert_field ei_snmp_varbind_wrong_length_value
;
381 static expert_field ei_snmp_varbind_wrong_class_tag
;
382 static expert_field ei_snmp_rfc1910_non_conformant
;
383 static expert_field ei_snmp_rfc3411_non_conformant
;
384 static expert_field ei_snmp_version_unknown
;
385 static expert_field ei_snmp_trap_pdu_obsolete
;
387 static const true_false_string auth_flags
= {
392 /* Security Models */
394 #define SNMP_SEC_ANY 0
395 #define SNMP_SEC_V1 1
396 #define SNMP_SEC_V2C 2
397 #define SNMP_SEC_USM 3
399 static const value_string sec_models
[] = {
400 { SNMP_SEC_ANY
, "Any" },
401 { SNMP_SEC_V1
, "V1" },
402 { SNMP_SEC_V2C
, "V2C" },
403 { SNMP_SEC_USM
, "USM" },
409 #define SMUX_MSG_OPEN 0
410 #define SMUX_MSG_CLOSE 1
411 #define SMUX_MSG_RREQ 2
412 #define SMUX_MSG_RRSP 3
413 #define SMUX_MSG_SOUT 4
415 static const value_string smux_types
[] = {
416 { SMUX_MSG_OPEN
, "Open" },
417 { SMUX_MSG_CLOSE
, "Close" },
418 { SMUX_MSG_RREQ
, "Registration Request" },
419 { SMUX_MSG_RRSP
, "Registration Response" },
420 { SMUX_MSG_SOUT
, "Commit Or Rollback" },
425 /* Procedure names (used in Service Response Time) */
426 static const value_string snmp_procedure_names
[] = {
436 #define SNMP_IPA 0 /* IP Address */
437 #define SNMP_CNT 1 /* Counter (Counter32) */
438 #define SNMP_GGE 2 /* Gauge (Gauge32) */
439 #define SNMP_TIT 3 /* TimeTicks */
440 #define SNMP_OPQ 4 /* Opaque */
441 #define SNMP_NSP 5 /* NsapAddress */
442 #define SNMP_C64 6 /* Counter64 */
443 #define SNMP_U32 7 /* Uinteger32 */
450 dissector_table_t value_sub_dissectors_table
;
453 * Data structure attached to a conversation, request/response information
455 typedef struct snmp_conv_info_t
{
456 wmem_map_t
*request_response
;
459 static snmp_conv_info_t
*
460 snmp_find_conversation_and_get_conv_data(packet_info
*pinfo
);
462 static snmp_request_response_t
*
463 snmp_get_request_response_pointer(wmem_map_t
*map
, uint32_t requestId
)
465 snmp_request_response_t
*srrp
=(snmp_request_response_t
*)wmem_map_lookup(map
, &requestId
);
467 srrp
=wmem_new0(wmem_file_scope(), snmp_request_response_t
);
468 srrp
->requestId
=requestId
;
469 wmem_map_insert(map
, &(srrp
->requestId
), (void *)srrp
);
475 static snmp_request_response_t
*
476 snmp_match_request_response(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned requestId
, unsigned procedure_id
, snmp_conv_info_t
*snmp_info
)
478 snmp_request_response_t
*srrp
=NULL
;
480 DISSECTOR_ASSERT_HINT(snmp_info
, "No SNMP info from ASN1 context");
482 /* get or create request/response pointer based on request id */
483 srrp
=(snmp_request_response_t
*)snmp_get_request_response_pointer(snmp_info
->request_response
, requestId
);
485 // if not visited fill the request/response data
486 if (!PINFO_FD_VISITED(pinfo
)) {
490 case SNMP_REQ_GETNEXT
:
492 case SNMP_REQ_GETBULK
:
493 case SNMP_REQ_INFORM
:
494 srrp
->request_frame_id
=pinfo
->fd
->num
;
495 srrp
->response_frame_id
=0;
496 srrp
->request_time
=pinfo
->abs_ts
;
497 srrp
->request_procedure_id
=procedure_id
;
500 srrp
->response_frame_id
=pinfo
->fd
->num
;
507 /* if request and response was matched */
508 if (srrp
->request_frame_id
!=0 && srrp
->response_frame_id
!=0)
512 // if it is the response
513 if (srrp
->response_frame_id
== pinfo
->fd
->num
)
516 it
=proto_tree_add_uint(tree
, hf_snmp_response_to
, tvb
, 0, 0, srrp
->request_frame_id
);
517 proto_item_set_generated(it
);
518 nstime_delta(&ns
, &pinfo
->abs_ts
, &srrp
->request_time
);
519 it
=proto_tree_add_time(tree
, hf_snmp_time
, tvb
, 0, 0, &ns
);
520 proto_item_set_generated(it
);
524 it
=proto_tree_add_uint(tree
, hf_snmp_response_in
, tvb
, 0, 0, srrp
->response_frame_id
);
525 proto_item_set_generated(it
);
533 snmpstat_init(struct register_srt
* srt _U_
, GArray
* srt_array
)
535 srt_stat_table
*snmp_srt_table
;
538 snmp_srt_table
= init_srt_table("SNMP Commands", NULL
, srt_array
, SNMP_NUM_PROCEDURES
, NULL
, "snmp.data", NULL
);
539 for (i
= 0; i
< SNMP_NUM_PROCEDURES
; i
++)
541 init_srt_table_row(snmp_srt_table
, i
, val_to_str_const(i
, snmp_procedure_names
, "<unknown>"));
545 /* This is called only if request and response was matched -> no need to return anything than TAP_PACKET_REDRAW */
546 static tap_packet_status
547 snmpstat_packet(void *psnmp
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *psi
, tap_flags_t flags _U_
)
550 srt_stat_table
*snmp_srt_table
;
551 const snmp_request_response_t
*snmp
=(const snmp_request_response_t
*)psi
;
552 srt_data_t
*data
= (srt_data_t
*)psnmp
;
554 snmp_srt_table
= g_array_index(data
->srt_array
, srt_stat_table
*, i
);
556 add_srt_table_data(snmp_srt_table
, snmp
->request_procedure_id
, &snmp
->request_time
, pinfo
);
557 return TAP_PACKET_REDRAW
;
561 snmp_lookup_specific_trap (unsigned specific_trap
)
565 for (i
= 0; i
< num_specific_traps
; i
++) {
566 snmp_st_assoc_t
*u
= &(specific_traps
[i
]);
568 if ((u
->trap
== specific_trap
) &&
569 (strcmp (u
->enterprise
, enterprise_oid
) == 0))
579 dissect_snmp_variable_string(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void *data _U_
)
582 proto_tree_add_item(tree
, hf_snmp_var_bind_str
, tvb
, 0, -1, ENC_ASCII
);
584 return tvb_captured_length(tvb
);
588 DateAndTime ::= TEXTUAL-CONVENTION
589 DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d"
592 "A date-time specification.
594 field octets contents range
595 ----- ------ -------- -----
602 (use 60 for leap-second)
603 7 8 deci-seconds 0..9
604 8 9 direction from UTC '+' / '-'
605 9 10 hours from UTC* 0..13
606 10 11 minutes from UTC 0..59
609 - the value of year is in network-byte order
610 - daylight saving time in New Zealand is +13
612 For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be
615 1992-5-26,13:30:15.0,-4:0
617 Note that if only local time is known, then timezone
618 information (fields 8-10) is not present."
619 SYNTAX OCTET STRING (SIZE (8 | 11))
622 dissect_snmp_variable_date_and_time(proto_tree
*tree
, packet_info
*pinfo
, int hfid
, tvbuff_t
*tvb
, int offset
, int length
)
630 uint8_t deci_seconds
;
631 uint8_t hour_from_utc
;
632 uint8_t min_from_utc
;
635 year
= tvb_get_ntohs(tvb
,offset
);
636 month
= tvb_get_uint8(tvb
,offset
+2);
637 day
= tvb_get_uint8(tvb
,offset
+3);
638 hour
= tvb_get_uint8(tvb
,offset
+4);
639 minutes
= tvb_get_uint8(tvb
,offset
+5);
640 seconds
= tvb_get_uint8(tvb
,offset
+6);
641 deci_seconds
= tvb_get_uint8(tvb
,offset
+7);
643 hour_from_utc
= tvb_get_uint8(tvb
,offset
+9);
644 min_from_utc
= tvb_get_uint8(tvb
,offset
+10);
646 str
= wmem_strdup_printf(pinfo
->pool
,
647 "%u-%u-%u, %u:%u:%u.%u UTC %s%u:%u",
655 tvb_get_string_enc(pinfo
->pool
,tvb
,offset
+8,1,ENC_ASCII
|ENC_NA
),
659 str
= wmem_strdup_printf(pinfo
->pool
,
660 "%u-%u-%u, %u:%u:%u.%u",
670 return proto_tree_add_string(tree
, hfid
, tvb
, offset
, length
, str
);
675 * dissect_snmp_VarBind
676 * this routine dissects variable bindings, looking for the oid information in our oid reporsitory
677 * to format and add the value adequatelly.
679 * The choice to handwrite this code instead of using the asn compiler is to avoid having tons
680 * of uses of global variables distributed in very different parts of the code.
681 * Other than that there's a cosmetic thing: the tree from ASN generated code would be so
682 * convoluted due to the nesting of CHOICEs in the definition of VarBind/value.
684 * XXX: the length of this function (~400 lines) is an aberration!
685 * oid_key_t:key_type could become a series of callbacks instead of an enum
686 * the (! oid_info_is_ok) switch could be made into an array (would be slower)
689 NetworkAddress ::= CHOICE { internet IpAddress }
690 IpAddress ::= [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4))
691 TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
692 Integer32 ::= INTEGER (-2147483648..2147483647)
693 ObjectName ::= OBJECT IDENTIFIER
694 Counter32 ::= [APPLICATION 1] IMPLICIT INTEGER (0..4294967295)
695 Gauge32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
696 Unsigned32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
697 Integer-value ::= INTEGER (-2147483648..2147483647)
698 Integer32 ::= INTEGER (-2147483648..2147483647)
699 ObjectID-value ::= OBJECT IDENTIFIER
701 TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
702 Opaque ::= [APPLICATION 4] IMPLICIT OCTET STRING
703 Counter64 ::= [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615)
705 ObjectSyntax ::= CHOICE {
707 application-wide ApplicationSyntax
710 SimpleSyntax ::= CHOICE {
711 integer-value Integer-value,
712 string-value String-value,
713 objectID-value ObjectID-value,
717 ApplicationSyntax ::= CHOICE {
718 ipAddress-value IpAddress,
719 counter-value Counter32,
720 timeticks-value TimeTicks,
721 arbitrary-value Opaque,
722 big-counter-value Counter64,
723 unsigned-integer-value Unsigned32
726 ValueType ::= CHOICE {
729 noSuchObject[0] IMPLICIT NULL,
730 noSuchInstance[1] IMPLICIT NULL,
731 endOfMibView[2] IMPLICIT NULL
734 VarBind ::= SEQUENCE {
742 dissect_snmp_VarBind(bool implicit_tag _U_
, tvbuff_t
*tvb
, int offset
,
743 asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index _U_
)
745 int seq_offset
, name_offset
, value_offset
, value_start
;
746 uint32_t seq_len
, name_len
, value_len
;
753 oid_info_t
* oid_info
= NULL
;
754 unsigned oid_matched
, oid_left
;
755 proto_item
*pi_name
, *pi_varbind
, *pi_value
= NULL
;
756 proto_tree
*pt
, *pt_varbind
, *pt_name
, *pt_value
;
757 char label
[ITEM_LABEL_LENGTH
];
758 const char* repr
= NULL
;
759 const char* info_oid
= NULL
;
762 int min_len
= 0, max_len
= 0;
764 const char* oid_string
= NULL
;
765 enum {BER_NO_ERROR
, BER_WRONG_LENGTH
, BER_WRONG_TAG
} format_error
= BER_NO_ERROR
;
769 /* first have the VarBind's sequence header */
770 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
771 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &seq_len
, &ind
);
773 if (!pc
&& ber_class
==BER_CLASS_UNI
&& tag
==BER_UNI_TAG_SEQUENCE
) {
775 pt
= proto_tree_add_subtree(tree
, tvb
, seq_offset
, seq_len
+ (offset
- seq_offset
),
776 ett_decoding_error
, &pi
, "VarBind must be an universal class sequence");
777 expert_add_info(actx
->pinfo
, pi
, &ei_snmp_varbind_not_uni_class_seq
);
778 return dissect_unknown_ber(actx
->pinfo
, tvb
, seq_offset
, pt
);
783 pt
= proto_tree_add_subtree(tree
, tvb
, seq_offset
, seq_len
+ (offset
- seq_offset
),
784 ett_decoding_error
, &pi
, "Indicator must be clear in VarBind");
785 expert_add_info(actx
->pinfo
, pi
, &ei_snmp_varbind_has_indicator
);
786 return dissect_unknown_ber(actx
->pinfo
, tvb
, seq_offset
, pt
);
789 /* we add the varbind tree root with a dummy label we'll fill later on */
790 pt_varbind
= proto_tree_add_subtree(tree
,tvb
,offset
,seq_len
,ett_varbind
,&pi_varbind
,"VarBind");
793 seq_len
+= offset
- seq_offset
;
795 /* then we have the ObjectName's header */
797 offset
= dissect_ber_identifier(actx
->pinfo
, pt_varbind
, tvb
, offset
, &ber_class
, &pc
, &tag
);
798 name_offset
= offset
= dissect_ber_length(actx
->pinfo
, pt_varbind
, tvb
, offset
, &name_len
, &ind
);
800 if (! ( !pc
&& ber_class
==BER_CLASS_UNI
&& tag
==BER_UNI_TAG_OID
) ) {
802 pt
= proto_tree_add_subtree(tree
, tvb
, seq_offset
, seq_len
,
803 ett_decoding_error
, &pi
, "ObjectName must be an OID in primitive encoding");
804 expert_add_info(actx
->pinfo
, pi
, &ei_snmp_objectname_not_oid
);
805 return dissect_unknown_ber(actx
->pinfo
, tvb
, seq_offset
, pt
);
810 pt
= proto_tree_add_subtree(tree
, tvb
, seq_offset
, seq_len
,
811 ett_decoding_error
, &pi
, "Indicator must be clear in ObjectName");
812 expert_add_info(actx
->pinfo
, pi
, &ei_snmp_objectname_has_indicator
);
813 return dissect_unknown_ber(actx
->pinfo
, tvb
, seq_offset
, pt
);
816 pi_name
= proto_tree_add_item(pt_varbind
,hf_snmp_objectname
,tvb
,name_offset
,name_len
,ENC_NA
);
817 pt_name
= proto_item_add_subtree(pi_name
,ett_name
);
820 value_start
= offset
;
821 /* then we have the value's header */
822 offset
= dissect_ber_identifier(actx
->pinfo
, pt_varbind
, tvb
, offset
, &ber_class
, &pc
, &tag
);
823 value_offset
= dissect_ber_length(actx
->pinfo
, pt_varbind
, tvb
, offset
, &value_len
, &ind
);
827 pt
= proto_tree_add_subtree(pt_varbind
, tvb
, value_start
, value_len
,
828 ett_decoding_error
, &pi
, "the value must be in primitive encoding");
829 expert_add_info(actx
->pinfo
, pi
, &ei_snmp_value_not_primitive_encoding
);
830 return dissect_unknown_ber(actx
->pinfo
, tvb
, value_start
, pt
);
833 /* Now, we know where everything is */
835 /* fetch ObjectName and its relative oid_info */
836 oid_bytes
= (uint8_t*)tvb_memdup(actx
->pinfo
->pool
, tvb
, name_offset
, name_len
);
837 oid_info
= oid_get_from_encoded(actx
->pinfo
->pool
, oid_bytes
, name_len
, &subids
, &oid_matched
, &oid_left
);
839 add_oid_debug_subtree(oid_info
,pt_name
);
844 repr
= oid_encoded2string(actx
->pinfo
->pool
, oid_bytes
, name_len
);
845 pt
= proto_tree_add_subtree_format(pt_name
,tvb
, 0, 0, ett_decoding_error
, &pi
, "invalid oid: %s", repr
);
846 expert_add_info_format(actx
->pinfo
, pi
, &ei_snmp_invalid_oid
, "invalid oid: %s", repr
);
847 return dissect_unknown_ber(actx
->pinfo
, tvb
, name_offset
, pt
);
850 if (oid_matched
+oid_left
) {
851 oid_string
= oid_subid2string(actx
->pinfo
->pool
, subids
,oid_matched
+oid_left
);
854 if (ber_class
== BER_CLASS_CON
) {
855 /* if we have an error value just add it and get out the way ASAP */
859 if (value_len
!= 0) {
860 min_len
= max_len
= 0;
861 format_error
= BER_WRONG_LENGTH
;
866 hfid
= hf_snmp_noSuchObject
;
867 note
= "noSuchObject";
870 hfid
= hf_snmp_noSuchInstance
;
871 note
= "noSuchInstance";
874 hfid
= hf_snmp_endOfMibView
;
875 note
= "endOfMibView";
878 pt
= proto_tree_add_subtree_format(pt_varbind
,tvb
,0,0,ett_decoding_error
,&pi
,
879 "Wrong tag for Error Value: expected 0, 1, or 2 but got: %d",tag
);
880 expert_add_info(actx
->pinfo
, pi
, &ei_snmp_varbind_wrong_tag
);
881 return dissect_unknown_ber(actx
->pinfo
, tvb
, value_start
, pt
);
885 pi
= proto_tree_add_item(pt_varbind
,hfid
,tvb
,value_offset
,value_len
,ENC_BIG_ENDIAN
);
886 expert_add_info_format(actx
->pinfo
, pi
, &ei_snmp_varbind_response
, "%s",note
);
887 (void) g_strlcpy (label
, note
, ITEM_LABEL_LENGTH
);
891 /* 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 */
892 switch (oid_info
->kind
) {
893 case OID_KIND_SCALAR
:
895 /* OK: we got the instance sub-id */
896 proto_tree_add_uint64(pt_name
,hf_snmp_scalar_instance_index
,tvb
,name_offset
,name_len
,subids
[oid_matched
]);
897 oid_info_is_ok
= true;
899 } else if (oid_left
== 0) {
900 if (ber_class
== BER_CLASS_UNI
&& tag
== BER_UNI_TAG_NULL
) {
901 /* unSpecified does not require an instance sub-id add the new value and get off the way! */
902 pi_value
= proto_tree_add_item(pt_varbind
,hf_snmp_unSpecified
,tvb
,value_offset
,value_len
,ENC_NA
);
905 proto_tree_add_expert(pt_name
,actx
->pinfo
,&ei_snmp_no_instance_subid
,tvb
,0,0);
906 oid_info_is_ok
= false;
910 proto_tree_add_expert_format(pt_name
,actx
->pinfo
,&ei_snmp_wrong_num_of_subids
,tvb
,0,0,"A scalar should have only one instance sub-id this has: %d",oid_left
);
911 oid_info_is_ok
= false;
915 case OID_KIND_COLUMN
:
916 if ( oid_info
->parent
->kind
== OID_KIND_ROW
) {
917 oid_key_t
* k
= oid_info
->parent
->key
;
918 unsigned key_start
= oid_matched
;
919 unsigned key_len
= oid_left
;
920 oid_info_is_ok
= true;
922 if ( key_len
== 0 && ber_class
== BER_CLASS_UNI
&& tag
== BER_UNI_TAG_NULL
) {
923 /* unSpecified does not require an instance sub-id add the new value and get off the way! */
924 pi_value
= proto_tree_add_item(pt_varbind
,hf_snmp_unSpecified
,tvb
,value_offset
,value_len
,ENC_NA
);
929 for (;k
;k
= k
->next
) {
932 if (key_start
>= oid_matched
+oid_left
) {
933 proto_tree_add_expert(pt_name
,actx
->pinfo
,&ei_snmp_index_suboid_too_short
,tvb
,0,0);
934 oid_info_is_ok
= false;
938 switch(k
->key_type
) {
939 case OID_KEY_TYPE_WRONG
: {
940 proto_tree_add_expert(pt_name
,actx
->pinfo
,&ei_snmp_unimplemented_instance_index
,tvb
,0,0);
941 oid_info_is_ok
= false;
944 case OID_KEY_TYPE_INTEGER
: {
945 if (FT_IS_INT(k
->ft_type
)) {
946 proto_tree_add_int(pt_name
,k
->hfid
,tvb
,name_offset
,name_len
,(unsigned)subids
[key_start
]);
947 } else { /* if it's not an unsigned int let proto_tree_add_uint throw a warning */
948 proto_tree_add_uint64(pt_name
,k
->hfid
,tvb
,name_offset
,name_len
,(unsigned)subids
[key_start
]);
952 continue; /* k->next */
954 case OID_KEY_TYPE_IMPLIED_OID
:
955 suboid_len
= key_len
;
959 case OID_KEY_TYPE_OID
: {
961 unsigned suboid_buf_len
;
964 suboid_len
= subids
[key_start
++];
968 suboid
= &(subids
[key_start
]);
970 if( suboid_len
== 0 ) {
971 proto_tree_add_expert(pt_name
,actx
->pinfo
,&ei_snmp_index_suboid_len0
,tvb
,0,0);
972 oid_info_is_ok
= false;
976 if( key_len
< suboid_len
) {
977 proto_tree_add_expert(pt_name
,actx
->pinfo
,&ei_snmp_index_suboid_too_long
,tvb
,0,0);
978 oid_info_is_ok
= false;
982 suboid_buf_len
= oid_subid2encoded(actx
->pinfo
->pool
, suboid_len
, suboid
, &suboid_buf
);
984 DISSECTOR_ASSERT(suboid_buf_len
);
986 proto_tree_add_oid(pt_name
,k
->hfid
,tvb
,name_offset
, suboid_buf_len
, suboid_buf
);
988 key_start
+= suboid_len
;
989 key_len
-= suboid_len
+ 1;
990 continue; /* k->next */
999 switch (k
->key_type
) {
1000 case OID_KEY_TYPE_IPADDR
:
1001 suboid
= &(subids
[key_start
]);
1004 case OID_KEY_TYPE_IMPLIED_STRING
:
1005 case OID_KEY_TYPE_IMPLIED_BYTES
:
1006 case OID_KEY_TYPE_ETHER
:
1007 suboid
= &(subids
[key_start
]);
1011 buf_len
= k
->num_subids
;
1012 suboid
= &(subids
[key_start
]);
1015 buf_len
= *suboid
++;
1022 if( key_len
< buf_len
) {
1023 proto_tree_add_expert(pt_name
,actx
->pinfo
,&ei_snmp_index_string_too_long
,tvb
,0,0);
1024 oid_info_is_ok
= false;
1028 buf
= (uint8_t*)wmem_alloc(actx
->pinfo
->pool
, buf_len
+1);
1029 for (i
= 0; i
< buf_len
; i
++)
1030 buf
[i
] = (uint8_t)suboid
[i
];
1033 switch(k
->key_type
) {
1034 case OID_KEY_TYPE_STRING
:
1035 case OID_KEY_TYPE_IMPLIED_STRING
:
1036 proto_tree_add_string(pt_name
,k
->hfid
,tvb
,name_offset
,buf_len
, buf
);
1038 case OID_KEY_TYPE_BYTES
:
1039 case OID_KEY_TYPE_NSAP
:
1040 case OID_KEY_TYPE_IMPLIED_BYTES
:
1041 proto_tree_add_bytes(pt_name
,k
->hfid
,tvb
,name_offset
,buf_len
, buf
);
1043 case OID_KEY_TYPE_ETHER
:
1044 proto_tree_add_ether(pt_name
,k
->hfid
,tvb
,name_offset
,buf_len
, buf
);
1046 case OID_KEY_TYPE_IPADDR
: {
1047 uint32_t* ipv4_p
= (uint32_t*)buf
;
1048 proto_tree_add_ipv4(pt_name
,k
->hfid
,tvb
,name_offset
,buf_len
, *ipv4_p
);
1052 DISSECTOR_ASSERT_NOT_REACHED();
1056 key_start
+= buf_len
;
1058 continue; /* k->next*/
1064 proto_tree_add_expert(pt_name
,actx
->pinfo
,&ei_snmp_unimplemented_instance_index
,tvb
,0,0);
1065 oid_info_is_ok
= false;
1069 proto_tree_add_expert(pt_name
,actx
->pinfo
,&ei_snmp_column_parent_not_row
,tvb
,0,0);
1070 oid_info_is_ok
= false;
1074 /* proto_tree_add_expert (pt_name,actx->pinfo,PI_MALFORMED, PI_WARN,tvb,0,0,"This kind OID should have no value"); */
1075 oid_info_is_ok
= false;
1081 if (oid_info_is_ok
&& oid_info
->value_type
) {
1082 if (ber_class
== BER_CLASS_UNI
&& tag
== BER_UNI_TAG_NULL
) {
1083 pi_value
= proto_tree_add_item(pt_varbind
,hf_snmp_unSpecified
,tvb
,value_offset
,value_len
,ENC_NA
);
1085 /* Provide a tree_item to attach errors to, if needed. */
1088 if ((oid_info
->value_type
->ber_class
!= BER_CLASS_ANY
) &&
1089 (ber_class
!= oid_info
->value_type
->ber_class
))
1090 format_error
= BER_WRONG_TAG
;
1091 else if ((oid_info
->value_type
->ber_tag
!= BER_TAG_ANY
) &&
1092 (tag
!= oid_info
->value_type
->ber_tag
))
1093 format_error
= BER_WRONG_TAG
;
1095 max_len
= oid_info
->value_type
->max_len
== -1 ? 0xffffff : oid_info
->value_type
->max_len
;
1096 min_len
= oid_info
->value_type
->min_len
;
1098 if ((int)value_len
< min_len
|| (int)value_len
> max_len
)
1099 format_error
= BER_WRONG_LENGTH
;
1102 if (format_error
== BER_NO_ERROR
) {
1103 /* Special case DATE AND TIME */
1104 if((oid_info
->value_type
)&&(oid_info
->value_type
->keytype
== OID_KEY_TYPE_DATE_AND_TIME
)&&(value_len
> 7)){
1105 pi_value
= dissect_snmp_variable_date_and_time(pt_varbind
, actx
->pinfo
, oid_info
->value_hfid
, tvb
, value_offset
, value_len
);
1107 pi_value
= proto_tree_add_item(pt_varbind
,oid_info
->value_hfid
,tvb
,value_offset
,value_len
,ENC_BIG_ENDIAN
);
1112 switch(ber_class
|(tag
<<4)) {
1113 case BER_CLASS_UNI
|(BER_UNI_TAG_INTEGER
<<4):
1116 unsigned int int_val_offset
= value_offset
;
1119 max_len
= 4; min_len
= 1;
1120 if (value_len
> (unsigned)max_len
|| value_len
< (unsigned)min_len
) {
1121 hfid
= hf_snmp_integer32_value
;
1122 format_error
= BER_WRONG_LENGTH
;
1127 /* extend sign bit */
1128 if(tvb_get_uint8(tvb
, int_val_offset
)&0x80) {
1131 for(i
=0;i
<value_len
;i
++) {
1132 val
=(val
<<8)|tvb_get_uint8(tvb
, int_val_offset
);
1136 pi_value
= proto_tree_add_int64(pt_varbind
, hf_snmp_integer32_value
, tvb
,value_offset
,value_len
, val
);
1140 case BER_CLASS_UNI
|(BER_UNI_TAG_OCTETSTRING
<<4):
1141 if(oid_info
->value_hfid
> -1){
1142 hfid
= oid_info
->value_hfid
;
1144 hfid
= hf_snmp_octetstring_value
;
1147 case BER_CLASS_UNI
|(BER_UNI_TAG_OID
<<4):
1148 max_len
= -1; min_len
= 1;
1149 if (value_len
< (unsigned)min_len
) format_error
= BER_WRONG_LENGTH
;
1150 hfid
= hf_snmp_oid_value
;
1152 case BER_CLASS_UNI
|(BER_UNI_TAG_NULL
<<4):
1153 max_len
= 0; min_len
= 0;
1154 if (value_len
!= 0) format_error
= BER_WRONG_LENGTH
;
1155 hfid
= hf_snmp_null_value
;
1157 case BER_CLASS_APP
: /* | (SNMP_IPA<<4)*/
1159 case 4: hfid
= hf_snmp_ipv4_value
; break;
1160 case 16: hfid
= hf_snmp_ipv6_value
; break;
1161 default: hfid
= hf_snmp_anyaddress_value
; break;
1164 case BER_CLASS_APP
|(SNMP_U32
<<4):
1165 hfid
= hf_snmp_unsigned32_value
;
1167 case BER_CLASS_APP
|(SNMP_GGE
<<4):
1168 hfid
= hf_snmp_gauge32_value
;
1170 case BER_CLASS_APP
|(SNMP_CNT
<<4):
1171 hfid
= hf_snmp_counter_value
;
1173 case BER_CLASS_APP
|(SNMP_TIT
<<4):
1174 hfid
= hf_snmp_timeticks_value
;
1176 case BER_CLASS_APP
|(SNMP_OPQ
<<4):
1177 hfid
= hf_snmp_opaque_value
;
1179 case BER_CLASS_APP
|(SNMP_NSP
<<4):
1180 hfid
= hf_snmp_nsap_value
;
1182 case BER_CLASS_APP
|(SNMP_C64
<<4):
1183 hfid
= hf_snmp_big_counter_value
;
1186 hfid
= hf_snmp_unknown_value
;
1189 if (value_len
> 8) {
1191 * Too long for an FT_UINT64 or an FT_INT64.
1193 header_field_info
*hfinfo
= proto_registrar_get_nth(hfid
);
1194 if (hfinfo
->type
== FT_UINT64
) {
1196 * Check if this is an unsigned int64 with
1199 if (value_len
> 9 || tvb_get_uint8(tvb
, value_offset
) != 0) {
1201 proto_tree_add_expert_format(pt_varbind
,actx
->pinfo
,&ei_snmp_uint_too_large
,tvb
,value_offset
,value_len
,"Integral value too large");
1204 /* Cheat and skip the leading 0 byte */
1207 } else if (hfinfo
->type
== FT_INT64
) {
1209 * For now, just reject these.
1211 proto_tree_add_expert_format(pt_varbind
,actx
->pinfo
,&ei_snmp_int_too_large
,tvb
,value_offset
,value_len
,"Integral value too large or too small");
1214 } else if (value_len
== 0) {
1216 * X.690 section 8.3.1 "Encoding of an integer value":
1217 * "The encoding of an integer value shall be
1218 * primitive. The contents octets shall consist of
1219 * one or more octets."
1221 * Zero is not "one or more".
1223 header_field_info
*hfinfo
= proto_registrar_get_nth(hfid
);
1224 if (hfinfo
->type
== FT_UINT64
|| hfinfo
->type
== FT_INT64
) {
1225 proto_tree_add_expert_format(pt_varbind
,actx
->pinfo
,&ei_snmp_integral_value0
,tvb
,value_offset
,value_len
,"Integral value is zero-length");
1229 /* Special case DATE AND TIME */
1230 if((oid_info
->value_type
)&&(oid_info
->value_type
->keytype
== OID_KEY_TYPE_DATE_AND_TIME
)&&(value_len
> 7)){
1231 pi_value
= dissect_snmp_variable_date_and_time(pt_varbind
, actx
->pinfo
, hfid
, tvb
, value_offset
, value_len
);
1233 pi_value
= proto_tree_add_item(pt_varbind
,hfid
,tvb
,value_offset
,value_len
,ENC_BIG_ENDIAN
);
1235 if (format_error
!= BER_NO_ERROR
) {
1236 expert_add_info(actx
->pinfo
, pi_value
, &ei_snmp_missing_mib
);
1241 pt_value
= proto_item_add_subtree(pi_value
,ett_value
);
1243 if (value_len
> 0 && oid_string
) {
1244 tvbuff_t
* sub_tvb
= tvb_new_subset_length(tvb
, value_offset
, value_len
);
1246 next_tvb_add_string(var_list
, sub_tvb
, (snmp_var_in_tree
) ? pt_value
: NULL
, value_sub_dissectors_table
, oid_string
);
1251 if (pi_value
) proto_item_fill_label(PITEM_FINFO(pi_value
), label
, NULL
);
1253 if (oid_info
&& oid_info
->name
) {
1254 if (oid_left
>= 1) {
1255 repr
= wmem_strdup_printf(actx
->pinfo
->pool
, "%s.%s (%s)", oid_info
->name
,
1256 oid_subid2string(actx
->pinfo
->pool
, &(subids
[oid_matched
]),oid_left
),
1257 oid_subid2string(actx
->pinfo
->pool
, subids
,oid_matched
+oid_left
));
1258 info_oid
= wmem_strdup_printf(actx
->pinfo
->pool
, "%s.%s", oid_info
->name
,
1259 oid_subid2string(actx
->pinfo
->pool
, &(subids
[oid_matched
]),oid_left
));
1261 repr
= wmem_strdup_printf(actx
->pinfo
->pool
, "%s (%s)", oid_info
->name
,
1262 oid_subid2string(actx
->pinfo
->pool
, subids
,oid_matched
));
1263 info_oid
= oid_info
->name
;
1265 } else if (oid_string
) {
1266 repr
= wmem_strdup(actx
->pinfo
->pool
, oid_string
);
1267 info_oid
= oid_string
;
1269 repr
= wmem_strdup(actx
->pinfo
->pool
, "[Bad OID]");
1272 valstr
= strstr(label
,": ");
1273 valstr
= valstr
? valstr
+2 : label
;
1275 proto_item_set_text(pi_varbind
,"%s: %s",repr
,valstr
);
1277 if (display_oid
&& info_oid
) {
1278 col_append_fstr (actx
->pinfo
->cinfo
, COL_INFO
, " %s", info_oid
);
1281 switch (format_error
) {
1282 case BER_WRONG_LENGTH
: {
1284 proto_tree
* p_tree
= proto_item_add_subtree(pi_value
,ett_decoding_error
);
1285 pt
= proto_tree_add_subtree_format(p_tree
,tvb
,0,0,ett_decoding_error
,&pi
,
1286 "Wrong value length: %u expecting: %u <= len <= %u",
1287 value_len
, min_len
, max_len
== -1 ? 0xFFFFFF : max_len
);
1288 expert_add_info(actx
->pinfo
, pi
, &ei_snmp_varbind_wrong_length_value
);
1289 return dissect_unknown_ber(actx
->pinfo
, tvb
, value_start
, pt
);
1291 case BER_WRONG_TAG
: {
1293 proto_tree
* p_tree
= proto_item_add_subtree(pi_value
,ett_decoding_error
);
1294 pt
= proto_tree_add_subtree_format(p_tree
,tvb
,0,0,ett_decoding_error
,&pi
,
1295 "Wrong class/tag for Value expected: %d,%d got: %d,%d",
1296 oid_info
->value_type
->ber_class
, oid_info
->value_type
->ber_tag
,
1298 expert_add_info(actx
->pinfo
, pi
, &ei_snmp_varbind_wrong_class_tag
);
1299 return dissect_unknown_ber(actx
->pinfo
, tvb
, value_start
, pt
);
1305 return seq_offset
+ seq_len
;
1309 #define F_SNMP_ENGINEID_CONFORM 0x80
1310 #define SNMP_ENGINEID_RFC1910 0x00
1311 #define SNMP_ENGINEID_RFC3411 0x01
1313 static const true_false_string tfs_snmp_engineid_conform
= {
1315 "RFC1910 (Non-SNMPv3)"
1318 #define SNMP_ENGINEID_FORMAT_IPV4 0x01
1319 #define SNMP_ENGINEID_FORMAT_IPV6 0x02
1320 #define SNMP_ENGINEID_FORMAT_MACADDRESS 0x03
1321 #define SNMP_ENGINEID_FORMAT_TEXT 0x04
1322 #define SNMP_ENGINEID_FORMAT_OCTETS 0x05
1323 #define SNMP_ENGINEID_FORMAT_LOCAL 0x06
1325 static const value_string snmp_engineid_format_vals
[] = {
1326 { SNMP_ENGINEID_FORMAT_IPV4
, "IPv4 address" },
1327 { SNMP_ENGINEID_FORMAT_IPV6
, "IPv6 address" },
1328 { SNMP_ENGINEID_FORMAT_MACADDRESS
, "MAC address" },
1329 { SNMP_ENGINEID_FORMAT_TEXT
, "Text, administratively assigned" },
1330 { SNMP_ENGINEID_FORMAT_OCTETS
, "Octets, administratively assigned" },
1331 { SNMP_ENGINEID_FORMAT_LOCAL
, "Local engine" },
1335 #define SNMP_ENGINEID_CISCO_AGENT 0x00
1336 #define SNMP_ENGINEID_CISCO_MANAGER 0x01
1338 static const value_string snmp_engineid_cisco_type_vals
[] = {
1339 { SNMP_ENGINEID_CISCO_AGENT
, "Agent" },
1340 { SNMP_ENGINEID_CISCO_MANAGER
, "Manager" },
1345 * SNMP Engine ID dissection according to RFC 3411 (SnmpEngineID TC)
1346 * or historic RFC 1910 (AgentID)
1349 dissect_snmp_engineid(proto_tree
*tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, int len
)
1351 proto_item
*item
= NULL
;
1352 uint8_t conformance
, format
;
1353 uint32_t enterpriseid
;
1356 int len_remain
= len
;
1358 /* first bit: engine id conformance */
1359 if (len_remain
<1) return offset
;
1360 conformance
= ((tvb_get_uint8(tvb
, offset
)>>7) & 0x01);
1361 proto_tree_add_item(tree
, hf_snmp_engineid_conform
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1363 /* 4-byte enterprise number/name */
1364 if (len_remain
<4) return offset
;
1365 enterpriseid
= tvb_get_ntohl(tvb
, offset
);
1367 enterpriseid
-= 0x80000000; /* ignore first bit */
1368 proto_tree_add_uint(tree
, hf_snmp_engineid_enterprise
, tvb
, offset
, 4, enterpriseid
);
1372 switch(conformance
) {
1374 case SNMP_ENGINEID_RFC1910
:
1375 /* 12-byte AgentID w/ 8-byte trailer */
1376 if (len_remain
==8) {
1377 proto_tree_add_item(tree
, hf_snmp_agentid_trailer
, tvb
, offset
, 8, ENC_NA
);
1381 proto_tree_add_expert(tree
, pinfo
, &ei_snmp_rfc1910_non_conformant
, tvb
, offset
, len_remain
);
1386 case SNMP_ENGINEID_RFC3411
: /* variable length: 5..32 */
1388 /* 1-byte format specifier */
1389 if (len_remain
<1) return offset
;
1390 format
= tvb_get_uint8(tvb
, offset
);
1391 item
= proto_tree_add_uint_format(tree
, hf_snmp_engineid_format
, tvb
, offset
, 1, format
, "Engine ID Format: %s (%d)",
1392 val_to_str_const(format
, snmp_engineid_format_vals
, "Reserved/Enterprise-specific"),
1398 case SNMP_ENGINEID_FORMAT_IPV4
:
1399 /* 4-byte IPv4 address */
1400 if (len_remain
==4) {
1401 proto_tree_add_item(tree
, hf_snmp_engineid_ipv4
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1406 case SNMP_ENGINEID_FORMAT_IPV6
:
1407 /* 16-byte IPv6 address */
1408 if (len_remain
==16) {
1409 proto_tree_add_item(tree
, hf_snmp_engineid_ipv6
, tvb
, offset
, 16, ENC_NA
);
1414 case SNMP_ENGINEID_FORMAT_MACADDRESS
:
1415 /* See: https://supportforums.cisco.com/message/3010617#3010617 for details. */
1416 if ((enterpriseid
==9)&&(len_remain
==7)) {
1417 proto_tree_add_item(tree
, hf_snmp_engineid_cisco_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1421 /* 6-byte MAC address */
1422 if (len_remain
==6) {
1423 proto_tree_add_item(tree
, hf_snmp_engineid_mac
, tvb
, offset
, 6, ENC_NA
);
1428 case SNMP_ENGINEID_FORMAT_TEXT
:
1429 /* max. 27-byte string, administratively assigned */
1430 if (len_remain
<=27) {
1431 proto_tree_add_item(tree
, hf_snmp_engineid_text
, tvb
, offset
, len_remain
, ENC_ASCII
);
1436 case SNMP_ENGINEID_FORMAT_LOCAL
:
1439 /* most common enterprise-specific format: (ucd|net)-snmp random */
1440 if ((enterpriseid
==2021)||(enterpriseid
==8072)) {
1441 proto_item_append_text(item
, (enterpriseid
==2021) ? ": UCD-SNMP Random" : ": Net-SNMP Random");
1442 /* demystify: 4B random, 4B/8B epoch seconds */
1443 if ((len_remain
==8) || (len_remain
==12)) {
1444 proto_tree_add_item(tree
, hf_snmp_engineid_data
, tvb
, offset
, 4, ENC_NA
);
1445 if (len_remain
==8) {
1446 seconds
= (time_t)tvb_get_letohl(tvb
, offset
+ 4);
1448 seconds
= (time_t)tvb_get_letohi64(tvb
, offset
+ 4);
1452 proto_tree_add_time_format_value(tree
, hf_snmp_engineid_time
, tvb
, offset
+ 4, len_remain
- 4,
1454 abs_time_secs_to_str(pinfo
->pool
, seconds
, ABSOLUTE_TIME_LOCAL
, true));
1461 case SNMP_ENGINEID_FORMAT_OCTETS
:
1463 /* max. 27 bytes, administratively assigned or unknown format */
1464 if (len_remain
>0 && len_remain
<=27) {
1465 proto_tree_add_item(tree
, hf_snmp_engineid_data
, tvb
, offset
, len_remain
, ENC_NA
);
1474 proto_tree_add_expert(tree
, pinfo
, &ei_snmp_rfc3411_non_conformant
, tvb
, offset
, len_remain
);
1481 static void set_ue_keys(snmp_ue_assoc_t
* n
) {
1482 unsigned const key_size
= auth_hash_len
[n
->user
.authModel
];
1484 n
->user
.authKey
.data
= (uint8_t *)g_malloc(key_size
);
1485 n
->user
.authKey
.len
= key_size
;
1486 snmp_usm_password_to_key(n
->user
.authModel
,
1487 n
->user
.authPassword
.data
,
1488 n
->user
.authPassword
.len
,
1491 n
->user
.authKey
.data
);
1493 if (n
->priv_proto
== PRIV_AES128
|| n
->priv_proto
== PRIV_AES192
|| n
->priv_proto
== PRIV_AES256
) {
1494 unsigned need_key_len
=
1495 (n
->priv_proto
== PRIV_AES128
) ? 16 :
1496 (n
->priv_proto
== PRIV_AES192
) ? 24 :
1497 (n
->priv_proto
== PRIV_AES256
) ? 32 :
1500 unsigned key_len
= key_size
;
1502 while (key_len
< need_key_len
)
1503 key_len
+= key_size
;
1505 n
->user
.privKey
.data
= (uint8_t *)g_malloc(key_len
);
1506 n
->user
.privKey
.len
= need_key_len
;
1508 snmp_usm_password_to_key(n
->user
.authModel
,
1509 n
->user
.privPassword
.data
,
1510 n
->user
.privPassword
.len
,
1513 n
->user
.privKey
.data
);
1517 /* extend key if needed */
1518 while (key_len
< need_key_len
) {
1519 switch (n
->priv_key_exp
) {
1520 /* Baed on draft-reeder-snmpv3-usm-3desede-00, section 2.1 */
1521 case PRIVKEYEXP_USM_3DESDESEDE_00
:
1523 snmp_usm_password_to_key(n
->user
.authModel
,
1524 n
->user
.privKey
.data
+ (key_len
- key_size
),
1528 n
->user
.privKey
.data
+ key_len
);
1531 /* Based on snmp++ method PrivAES::extend_short_key in Agent++ */
1532 case PRIVKEYEXP_AGENTPP
:
1534 /* Key expansion in Agent++
1537 * K3 = hash(K1 | K2)
1538 * localized_key = K1 | K2 | K3
1540 gcry_md_hd_t hash_handle
;
1542 if (gcry_md_open(&hash_handle
, auth_hash_algo
[n
->user
.authModel
], 0)) {
1546 gcry_md_write(hash_handle
, n
->user
.privKey
.data
, key_len
);
1547 memcpy(n
->user
.privKey
.data
+ key_len
, gcry_md_read(hash_handle
, 0), key_size
);
1548 gcry_md_close(hash_handle
);
1557 key_len
+= key_size
;
1561 n
->user
.privKey
.data
= (uint8_t *)g_malloc(key_size
);
1562 n
->user
.privKey
.len
= key_size
;
1563 snmp_usm_password_to_key(n
->user
.authModel
,
1564 n
->user
.privPassword
.data
,
1565 n
->user
.privPassword
.len
,
1568 n
->user
.privKey
.data
);
1572 static snmp_ue_assoc_t
*
1573 ue_dup(snmp_ue_assoc_t
* o
)
1575 snmp_ue_assoc_t
* d
= (snmp_ue_assoc_t
*)g_memdup2(o
,sizeof(snmp_ue_assoc_t
));
1577 d
->user
.authModel
= o
->user
.authModel
;
1579 d
->user
.privProtocol
= o
->user
.privProtocol
;
1581 d
->user
.userName
.data
= (uint8_t *)g_memdup2(o
->user
.userName
.data
,o
->user
.userName
.len
);
1582 d
->user
.userName
.len
= o
->user
.userName
.len
;
1584 d
->user
.authPassword
.data
= o
->user
.authPassword
.data
? (uint8_t *)g_memdup2(o
->user
.authPassword
.data
,o
->user
.authPassword
.len
) : NULL
;
1585 d
->user
.authPassword
.len
= o
->user
.authPassword
.len
;
1587 d
->user
.privPassword
.data
= o
->user
.privPassword
.data
? (uint8_t *)g_memdup2(o
->user
.privPassword
.data
,o
->user
.privPassword
.len
) : NULL
;
1588 d
->user
.privPassword
.len
= o
->user
.privPassword
.len
;
1590 d
->engine
.len
= o
->engine
.len
;
1592 if (d
->engine
.len
) {
1593 d
->engine
.data
= (uint8_t *)g_memdup2(o
->engine
.data
,o
->engine
.len
);
1602 snmp_users_copy_cb(void* dest
, const void* orig
, size_t len _U_
)
1604 const snmp_ue_assoc_t
* o
= (const snmp_ue_assoc_t
*)orig
;
1605 snmp_ue_assoc_t
* d
= (snmp_ue_assoc_t
*)dest
;
1607 d
->auth_model
= o
->auth_model
;
1608 d
->user
.authModel
= (snmp_usm_auth_model_t
) o
->auth_model
;
1610 d
->priv_proto
= o
->priv_proto
;
1611 d
->user
.privProtocol
= priv_protos
[o
->priv_proto
];
1613 d
->user
.userName
.data
= (uint8_t*)g_memdup2(o
->user
.userName
.data
,o
->user
.userName
.len
);
1614 d
->user
.userName
.len
= o
->user
.userName
.len
;
1616 d
->user
.authPassword
.data
= o
->user
.authPassword
.data
? (uint8_t*)g_memdup2(o
->user
.authPassword
.data
,o
->user
.authPassword
.len
) : NULL
;
1617 d
->user
.authPassword
.len
= o
->user
.authPassword
.len
;
1619 d
->user
.privPassword
.data
= o
->user
.privPassword
.data
? (uint8_t*)g_memdup2(o
->user
.privPassword
.data
,o
->user
.privPassword
.len
) : NULL
;
1620 d
->user
.privPassword
.len
= o
->user
.privPassword
.len
;
1622 d
->engine
.len
= o
->engine
.len
;
1623 if (o
->engine
.data
) {
1624 d
->engine
.data
= (uint8_t*)g_memdup2(o
->engine
.data
,o
->engine
.len
);
1627 d
->user
.authKey
.data
= o
->user
.authKey
.data
? (uint8_t*)g_memdup2(o
->user
.authKey
.data
,o
->user
.authKey
.len
) : NULL
;
1628 d
->user
.authKey
.len
= o
->user
.authKey
.len
;
1630 d
->user
.privKey
.data
= o
->user
.privKey
.data
? (uint8_t*)g_memdup2(o
->user
.privKey
.data
,o
->user
.privKey
.len
) : NULL
;
1631 d
->user
.privKey
.len
= o
->user
.privKey
.len
;
1637 snmp_users_free_cb(void* p
)
1639 snmp_ue_assoc_t
* ue
= (snmp_ue_assoc_t
*)p
;
1640 g_free(ue
->user
.userName
.data
);
1641 g_free(ue
->user
.authPassword
.data
);
1642 g_free(ue
->user
.privPassword
.data
);
1643 g_free(ue
->user
.authKey
.data
);
1644 g_free(ue
->user
.privKey
.data
);
1645 g_free(ue
->engine
.data
);
1649 snmp_users_update_cb(void* p _U_
, char** err
)
1651 snmp_ue_assoc_t
* ue
= (snmp_ue_assoc_t
*)p
;
1652 GString
* es
= g_string_new("");
1657 if (! ue
->user
.userName
.len
) {
1658 g_string_append_printf(es
,"no userName\n");
1659 } else if ((ue
->engine
.len
> 0) && (ue
->engine
.len
< 5 || ue
->engine
.len
> 32)) {
1660 /* RFC 3411 section 5 */
1661 g_string_append_printf(es
, "Invalid engineId length (%u). Must be between 5 and 32 (10 and 64 hex digits)\n", ue
->engine
.len
);
1662 } else if (num_ueas
) {
1663 for (i
=0; i
<num_ueas
-1; i
++) {
1664 snmp_ue_assoc_t
* u
= &(ueas
[i
]);
1666 if ( u
->user
.userName
.len
== ue
->user
.userName
.len
1667 && u
->engine
.len
== ue
->engine
.len
&& (u
!= ue
)) {
1669 if (u
->engine
.len
> 0 && memcmp( u
->engine
.data
, ue
->engine
.data
, u
->engine
.len
) == 0) {
1670 if ( memcmp( u
->user
.userName
.data
, ue
->user
.userName
.data
, ue
->user
.userName
.len
) == 0 ) {
1671 /* XXX: make a string for the engineId */
1672 g_string_append_printf(es
,"Duplicate key (userName='%s')\n",ue
->user
.userName
.data
);
1677 if (u
->engine
.len
== 0) {
1678 if ( memcmp( u
->user
.userName
.data
, ue
->user
.userName
.data
, ue
->user
.userName
.len
) == 0 ) {
1679 g_string_append_printf(es
,"Duplicate key (userName='%s' engineId=NONE)\n",ue
->user
.userName
.data
);
1688 es
= g_string_truncate(es
,es
->len
-1);
1689 *err
= g_string_free(es
, FALSE
);
1693 g_string_free(es
, TRUE
);
1698 free_ue_cache(snmp_ue_assoc_t
**cache
)
1700 static snmp_ue_assoc_t
*a
, *nxt
;
1702 for (a
= *cache
; a
; a
= nxt
) {
1704 snmp_users_free_cb(a
);
1711 #define CACHE_INSERT(c,a) if (c) { snmp_ue_assoc_t* t = c; c = a; c->next = t; } else { c = a; a->next = NULL; }
1718 for (i
= 0; i
< num_ueas
; i
++) {
1719 snmp_ue_assoc_t
* a
= ue_dup(&(ueas
[i
]));
1721 if (a
->engine
.len
) {
1722 CACHE_INSERT(localized_ues
,a
);
1725 CACHE_INSERT(unlocalized_ues
,a
);
1732 cleanup_ue_cache(void)
1734 free_ue_cache(&localized_ues
);
1735 free_ue_cache(&unlocalized_ues
);
1738 /* Called when the user applies changes to UAT preferences. */
1740 renew_ue_cache(void)
1747 static snmp_ue_assoc_t
*
1748 localize_ue( snmp_ue_assoc_t
* o
, const uint8_t* engine
, unsigned engine_len
)
1750 snmp_ue_assoc_t
* n
= (snmp_ue_assoc_t
*)g_memdup2(o
,sizeof(snmp_ue_assoc_t
));
1752 n
->user
.userName
.data
= (uint8_t*)g_memdup2(o
->user
.userName
.data
,o
->user
.userName
.len
);
1753 n
->user
.authModel
= o
->user
.authModel
;
1754 n
->user
.authPassword
.data
= (uint8_t*)g_memdup2(o
->user
.authPassword
.data
,o
->user
.authPassword
.len
);
1755 n
->user
.authPassword
.len
= o
->user
.authPassword
.len
;
1756 n
->user
.privPassword
.data
= (uint8_t*)g_memdup2(o
->user
.privPassword
.data
,o
->user
.privPassword
.len
);
1757 n
->user
.privPassword
.len
= o
->user
.privPassword
.len
;
1758 n
->user
.authKey
.data
= (uint8_t*)g_memdup2(o
->user
.authKey
.data
,o
->user
.authKey
.len
);
1759 n
->user
.privKey
.data
= (uint8_t*)g_memdup2(o
->user
.privKey
.data
,o
->user
.privKey
.len
);
1760 n
->engine
.data
= (uint8_t*)g_memdup2(engine
,engine_len
);
1761 n
->engine
.len
= engine_len
;
1762 n
->priv_proto
= o
->priv_proto
;
1770 #define localized_match(a,u,ul,e,el) \
1771 ( a->user.userName.len == ul \
1772 && a->engine.len == el \
1773 && memcmp( a->user.userName.data, u, ul ) == 0 \
1774 && memcmp( a->engine.data, e, el ) == 0 )
1776 #define unlocalized_match(a,u,l) \
1777 ( a->user.userName.len == l && memcmp( a->user.userName.data, u, l) == 0 )
1779 static snmp_ue_assoc_t
*
1780 get_user_assoc(tvbuff_t
* engine_tvb
, tvbuff_t
* user_tvb
, packet_info
*pinfo
)
1782 static snmp_ue_assoc_t
* a
;
1783 unsigned given_username_len
;
1784 uint8_t* given_username
;
1785 unsigned given_engine_len
= 0;
1786 uint8_t* given_engine
= NULL
;
1788 if ( ! (localized_ues
|| unlocalized_ues
) ) return NULL
;
1790 if (! ( user_tvb
&& engine_tvb
) ) return NULL
;
1792 given_username_len
= tvb_captured_length(user_tvb
);
1793 given_engine_len
= tvb_captured_length(engine_tvb
);
1794 if (! ( given_engine_len
&& given_username_len
) ) return NULL
;
1795 given_username
= (uint8_t*)tvb_memdup(pinfo
->pool
,user_tvb
,0,-1);
1796 given_engine
= (uint8_t*)tvb_memdup(pinfo
->pool
,engine_tvb
,0,-1);
1798 for (a
= localized_ues
; a
; a
= a
->next
) {
1799 if ( localized_match(a
, given_username
, given_username_len
, given_engine
, given_engine_len
) ) {
1804 for (a
= unlocalized_ues
; a
; a
= a
->next
) {
1805 if ( unlocalized_match(a
, given_username
, given_username_len
) ) {
1806 snmp_ue_assoc_t
* n
= localize_ue( a
, given_engine
, given_engine_len
);
1807 CACHE_INSERT(localized_ues
,n
);
1816 snmp_usm_auth(const packet_info
*pinfo
, const snmp_usm_auth_model_t model
, snmp_usm_params_t
* p
, uint8_t** calc_auth_p
,
1817 unsigned* calc_auth_len_p
, char const** error
)
1831 *error
= "No Authenticator";
1835 key
= p
->user_assoc
->user
.authKey
.data
;
1836 key_len
= p
->user_assoc
->user
.authKey
.len
;
1839 *error
= "User has no authKey";
1843 auth_len
= tvb_captured_length(p
->auth_tvb
);
1845 if (auth_len
!= auth_tag_len
[model
]) {
1846 *error
= "Authenticator length wrong";
1850 msg_len
= tvb_captured_length(p
->msg_tvb
);
1852 *error
= "Not enough data remaining";
1855 msg
= (uint8_t*)tvb_memdup(pinfo
->pool
,p
->msg_tvb
,0,msg_len
);
1857 auth
= (uint8_t*)tvb_memdup(pinfo
->pool
,p
->auth_tvb
,0,auth_len
);
1859 start
= p
->auth_offset
- p
->start_offset
;
1860 end
= start
+ auth_len
;
1862 /* fill the authenticator with zeros */
1863 for ( i
= start
; i
< end
; i
++ ) {
1867 calc_auth
= (uint8_t*)wmem_alloc(pinfo
->pool
, auth_hash_len
[model
]);
1869 if (ws_hmac_buffer(auth_hash_algo
[model
], calc_auth
, msg
, msg_len
, key
, key_len
)) {
1873 if (calc_auth_p
) *calc_auth_p
= calc_auth
;
1874 if (calc_auth_len_p
) *calc_auth_len_p
= auth_len
;
1876 return ( memcmp(auth
,calc_auth
,auth_len
) != 0 ) ? false : true;
1880 snmp_usm_priv_des(snmp_usm_params_t
* p
, tvbuff_t
* encryptedData
, packet_info
*pinfo
, char const** error
)
1883 gcry_cipher_hd_t hd
= NULL
;
1886 uint8_t* des_key
= p
->user_assoc
->user
.privKey
.data
; /* first 8 bytes */
1887 uint8_t* pre_iv
= &(p
->user_assoc
->user
.privKey
.data
[8]); /* last 8 bytes */
1892 tvbuff_t
* clear_tvb
;
1897 salt_len
= tvb_captured_length(p
->priv_tvb
);
1899 if (salt_len
!= 8) {
1900 *error
= "decryptionError: msgPrivacyParameters length != 8";
1904 salt
= (uint8_t*)tvb_memdup(pinfo
->pool
,p
->priv_tvb
,0,salt_len
);
1907 The resulting "salt" is XOR-ed with the pre-IV to obtain the IV.
1909 for (i
=0; i
<8; i
++) {
1910 iv
[i
] = pre_iv
[i
] ^ salt
[i
];
1913 cryptgrm_len
= tvb_captured_length(encryptedData
);
1915 if ((cryptgrm_len
<= 0) || (cryptgrm_len
% 8)) {
1916 *error
= "decryptionError: the length of the encrypted data is not a multiple of 8 octets";
1920 cryptgrm
= (uint8_t*)tvb_memdup(pinfo
->pool
,encryptedData
,0,-1);
1922 cleartext
= (uint8_t*)wmem_alloc(pinfo
->pool
, cryptgrm_len
);
1924 err
= gcry_cipher_open(&hd
, GCRY_CIPHER_DES
, GCRY_CIPHER_MODE_CBC
, 0);
1925 if (err
!= GPG_ERR_NO_ERROR
) goto on_gcry_error
;
1927 err
= gcry_cipher_setiv(hd
, iv
, 8);
1928 if (err
!= GPG_ERR_NO_ERROR
) goto on_gcry_error
;
1930 err
= gcry_cipher_setkey(hd
,des_key
,8);
1931 if (err
!= GPG_ERR_NO_ERROR
) goto on_gcry_error
;
1933 err
= gcry_cipher_decrypt(hd
, cleartext
, cryptgrm_len
, cryptgrm
, cryptgrm_len
);
1934 if (err
!= GPG_ERR_NO_ERROR
) goto on_gcry_error
;
1936 gcry_cipher_close(hd
);
1938 clear_tvb
= tvb_new_child_real_data(encryptedData
, cleartext
, cryptgrm_len
, cryptgrm_len
);
1943 *error
= (const char *)gcry_strerror(err
);
1944 if (hd
) gcry_cipher_close(hd
);
1949 snmp_usm_priv_aes_common(snmp_usm_params_t
* p
, tvbuff_t
* encryptedData
, packet_info
*pinfo
, char const** error
, int algo
)
1952 gcry_cipher_hd_t hd
= NULL
;
1955 uint8_t* aes_key
= p
->user_assoc
->user
.privKey
.data
;
1956 int aes_key_len
= p
->user_assoc
->user
.privKey
.len
;
1961 tvbuff_t
* clear_tvb
;
1963 priv_len
= tvb_captured_length(p
->priv_tvb
);
1965 if (priv_len
!= 8) {
1966 *error
= "decryptionError: msgPrivacyParameters length != 8";
1970 iv
[0] = (p
->boots
& 0xff000000) >> 24;
1971 iv
[1] = (p
->boots
& 0x00ff0000) >> 16;
1972 iv
[2] = (p
->boots
& 0x0000ff00) >> 8;
1973 iv
[3] = (p
->boots
& 0x000000ff);
1974 iv
[4] = (p
->snmp_time
& 0xff000000) >> 24;
1975 iv
[5] = (p
->snmp_time
& 0x00ff0000) >> 16;
1976 iv
[6] = (p
->snmp_time
& 0x0000ff00) >> 8;
1977 iv
[7] = (p
->snmp_time
& 0x000000ff);
1978 tvb_memcpy(p
->priv_tvb
,&(iv
[8]),0,8);
1980 cryptgrm_len
= tvb_captured_length(encryptedData
);
1981 if (cryptgrm_len
<= 0) {
1982 *error
= "Not enough data remaining";
1985 cryptgrm
= (uint8_t*)tvb_memdup(pinfo
->pool
,encryptedData
,0,-1);
1987 cleartext
= (uint8_t*)wmem_alloc(pinfo
->pool
, cryptgrm_len
);
1989 err
= gcry_cipher_open(&hd
, algo
, GCRY_CIPHER_MODE_CFB
, 0);
1990 if (err
!= GPG_ERR_NO_ERROR
) goto on_gcry_error
;
1992 err
= gcry_cipher_setiv(hd
, iv
, 16);
1993 if (err
!= GPG_ERR_NO_ERROR
) goto on_gcry_error
;
1995 err
= gcry_cipher_setkey(hd
,aes_key
,aes_key_len
);
1996 if (err
!= GPG_ERR_NO_ERROR
) goto on_gcry_error
;
1998 err
= gcry_cipher_decrypt(hd
, cleartext
, cryptgrm_len
, cryptgrm
, cryptgrm_len
);
1999 if (err
!= GPG_ERR_NO_ERROR
) goto on_gcry_error
;
2001 gcry_cipher_close(hd
);
2003 clear_tvb
= tvb_new_child_real_data(encryptedData
, cleartext
, cryptgrm_len
, cryptgrm_len
);
2008 *error
= (const char *)gcry_strerror(err
);
2009 if (hd
) gcry_cipher_close(hd
);
2014 snmp_usm_priv_aes128(snmp_usm_params_t
* p
, tvbuff_t
* encryptedData
, packet_info
*pinfo
, char const** error
)
2016 return snmp_usm_priv_aes_common(p
, encryptedData
, pinfo
, error
, GCRY_CIPHER_AES
);
2020 snmp_usm_priv_aes192(snmp_usm_params_t
* p
, tvbuff_t
* encryptedData
, packet_info
*pinfo
, char const** error
)
2022 return snmp_usm_priv_aes_common(p
, encryptedData
, pinfo
, error
, GCRY_CIPHER_AES192
);
2026 snmp_usm_priv_aes256(snmp_usm_params_t
* p
, tvbuff_t
* encryptedData
, packet_info
*pinfo
, char const** error
)
2028 return snmp_usm_priv_aes_common(p
, encryptedData
, pinfo
, error
, GCRY_CIPHER_AES256
);
2032 check_ScopedPdu(tvbuff_t
* tvb
)
2038 int hoffset
, eoffset
;
2041 offset
= get_ber_identifier(tvb
, 0, &ber_class
, &pc
, &tag
);
2042 offset
= get_ber_length(tvb
, offset
, NULL
, NULL
);
2044 if ( ! (((ber_class
!=BER_CLASS_APP
) && (ber_class
!=BER_CLASS_PRI
) )
2045 && ( (!pc
) || (ber_class
!=BER_CLASS_UNI
) || (tag
!=BER_UNI_TAG_ENUMERATED
) )
2048 if((tvb_get_uint8(tvb
, offset
)==0)&&(tvb_get_uint8(tvb
, offset
+1)==0))
2053 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
2054 offset
= get_ber_length(tvb
, offset
, &len
, NULL
);
2055 eoffset
= offset
+ len
;
2057 if (eoffset
<= hoffset
) return false;
2059 if ((ber_class
!=BER_CLASS_APP
)&&(ber_class
!=BER_CLASS_PRI
))
2060 if( (ber_class
!=BER_CLASS_UNI
)
2061 ||((tag
<BER_UNI_TAG_NumericString
)&&(tag
!=BER_UNI_TAG_OCTETSTRING
)&&(tag
!=BER_UNI_TAG_UTF8String
)) )
2072 dissect_snmp_EnterpriseOID(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2075 offset
= dissect_ber_object_identifier_str(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, &enterprise_oid
);
2078 if (display_oid
&& enterprise_oid
) {
2079 name
= oid_resolved_from_string(actx
->pinfo
->pool
, enterprise_oid
);
2081 col_append_fstr (actx
->pinfo
->cinfo
, COL_INFO
, " %s", name
);
2092 dissect_snmp_OCTET_STRING_SIZE_4(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2093 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2102 dissect_snmp_NetworkAddress(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2103 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2104 hf_index
, BER_CLASS_APP
, 0, true, dissect_snmp_OCTET_STRING_SIZE_4
);
2112 dissect_snmp_INTEGER_0_4294967295(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2113 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2122 dissect_snmp_TimeTicks(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2123 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2124 hf_index
, BER_CLASS_APP
, 3, true, dissect_snmp_INTEGER_0_4294967295
);
2132 dissect_snmp_Integer32(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2134 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2145 dissect_snmp_ObjectName(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2146 offset
= dissect_ber_object_identifier(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, NULL
);
2152 static const value_string snmp_Version_vals
[] = {
2162 dissect_snmp_Version(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2163 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2172 dissect_snmp_Community(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2173 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2182 dissect_snmp_T_request_id(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2184 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2193 static const value_string snmp_T_error_status_vals
[] = {
2196 { 2, "noSuchName" },
2202 { 8, "wrongLength" },
2203 { 9, "wrongEncoding" },
2204 { 10, "wrongValue" },
2205 { 11, "noCreation" },
2206 { 12, "inconsistentValue" },
2207 { 13, "resourceUnavailable" },
2208 { 14, "commitFailed" },
2209 { 15, "undoFailed" },
2210 { 16, "authorizationError" },
2211 { 17, "notWritable" },
2212 { 18, "inconsistentName" },
2218 dissect_snmp_T_error_status(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2219 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2228 dissect_snmp_INTEGER(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2229 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2237 static const ber_sequence_t VarBindList_sequence_of
[1] = {
2238 { &hf_snmp_VarBindList_item
, BER_CLASS_UNI
, BER_UNI_TAG_SEQUENCE
, BER_FLAGS_NOOWNTAG
, dissect_snmp_VarBind
},
2242 dissect_snmp_VarBindList(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2243 offset
= dissect_ber_sequence_of(implicit_tag
, actx
, tree
, tvb
, offset
,
2244 VarBindList_sequence_of
, hf_index
, ett_snmp_VarBindList
);
2250 static const ber_sequence_t PDU_sequence
[] = {
2251 { &hf_snmp_request_id
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_request_id
},
2252 { &hf_snmp_error_status
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_error_status
},
2253 { &hf_snmp_error_index
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_INTEGER
},
2254 { &hf_snmp_variable_bindings
, BER_CLASS_UNI
, BER_UNI_TAG_SEQUENCE
, BER_FLAGS_NOOWNTAG
, dissect_snmp_VarBindList
},
2255 { NULL
, 0, 0, 0, NULL
}
2259 dissect_snmp_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2260 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2261 PDU_sequence
, hf_index
, ett_snmp_PDU
);
2269 dissect_snmp_GetRequest_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2270 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2271 hf_index
, BER_CLASS_CON
, 0, true, dissect_snmp_PDU
);
2279 dissect_snmp_GetNextRequest_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2280 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2281 hf_index
, BER_CLASS_CON
, 1, true, dissect_snmp_PDU
);
2289 dissect_snmp_GetResponse_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2290 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2291 hf_index
, BER_CLASS_CON
, 2, true, dissect_snmp_PDU
);
2299 dissect_snmp_SetRequest_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2300 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2301 hf_index
, BER_CLASS_CON
, 3, true, dissect_snmp_PDU
);
2307 static const value_string snmp_GenericTrap_vals
[] = {
2312 { 4, "authenticationFailure" },
2313 { 5, "egpNeighborLoss" },
2314 { 6, "enterpriseSpecific" },
2320 dissect_snmp_GenericTrap(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2321 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2330 dissect_snmp_SpecificTrap(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2331 unsigned specific_trap
;
2333 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2337 if (generic_trap
== 6) { /* enterprise specific */
2338 const char *specific_str
= snmp_lookup_specific_trap (specific_trap
);
2340 proto_item_append_text(actx
->created_item
, " (%s)", specific_str
);
2348 static const ber_sequence_t Trap_PDU_U_sequence
[] = {
2349 { &hf_snmp_enterprise
, BER_CLASS_UNI
, BER_UNI_TAG_OID
, BER_FLAGS_NOOWNTAG
, dissect_snmp_EnterpriseOID
},
2350 { &hf_snmp_agent_addr
, BER_CLASS_APP
, 0, BER_FLAGS_NOOWNTAG
, dissect_snmp_NetworkAddress
},
2351 { &hf_snmp_generic_trap
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_GenericTrap
},
2352 { &hf_snmp_specific_trap
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_SpecificTrap
},
2353 { &hf_snmp_time_stamp
, BER_CLASS_APP
, 3, BER_FLAGS_NOOWNTAG
, dissect_snmp_TimeTicks
},
2354 { &hf_snmp_variable_bindings
, BER_CLASS_UNI
, BER_UNI_TAG_SEQUENCE
, BER_FLAGS_NOOWNTAG
, dissect_snmp_VarBindList
},
2355 { NULL
, 0, 0, 0, NULL
}
2359 dissect_snmp_Trap_PDU_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2361 enterprise_oid
= NULL
;
2363 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2364 Trap_PDU_U_sequence
, hf_index
, ett_snmp_Trap_PDU_U
);
2367 if (snmp_version
!= 0) {
2368 expert_add_info(actx
->pinfo
, tree
, &ei_snmp_trap_pdu_obsolete
);
2378 dissect_snmp_Trap_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2379 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2380 hf_index
, BER_CLASS_CON
, 4, true, dissect_snmp_Trap_PDU_U
);
2388 dissect_snmp_INTEGER_0_2147483647(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2389 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2396 static const ber_sequence_t BulkPDU_sequence
[] = {
2397 { &hf_snmp_bulkPDU_request_id
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_Integer32
},
2398 { &hf_snmp_non_repeaters
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_INTEGER_0_2147483647
},
2399 { &hf_snmp_max_repetitions
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_INTEGER_0_2147483647
},
2400 { &hf_snmp_variable_bindings
, BER_CLASS_UNI
, BER_UNI_TAG_SEQUENCE
, BER_FLAGS_NOOWNTAG
, dissect_snmp_VarBindList
},
2401 { NULL
, 0, 0, 0, NULL
}
2405 dissect_snmp_BulkPDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2406 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2407 BulkPDU_sequence
, hf_index
, ett_snmp_BulkPDU
);
2415 dissect_snmp_GetBulkRequest_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2416 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2417 hf_index
, BER_CLASS_CON
, 5, true, dissect_snmp_BulkPDU
);
2425 dissect_snmp_InformRequest_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2426 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2427 hf_index
, BER_CLASS_CON
, 6, true, dissect_snmp_PDU
);
2435 dissect_snmp_SNMPv2_Trap_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2436 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2437 hf_index
, BER_CLASS_CON
, 7, true, dissect_snmp_PDU
);
2445 dissect_snmp_Report_PDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2446 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2447 hf_index
, BER_CLASS_CON
, 8, true, dissect_snmp_PDU
);
2453 static const value_string snmp_PDUs_vals
[] = {
2454 { 0, "get-request" },
2455 { 1, "get-next-request" },
2456 { 2, "get-response" },
2457 { 3, "set-request" },
2459 { 5, "getBulkRequest" },
2460 { 6, "informRequest" },
2461 { 7, "snmpV2-trap" },
2466 static const ber_choice_t PDUs_choice
[] = {
2467 { 0, &hf_snmp_get_request
, BER_CLASS_CON
, 0, BER_FLAGS_NOOWNTAG
, dissect_snmp_GetRequest_PDU
},
2468 { 1, &hf_snmp_get_next_request
, BER_CLASS_CON
, 1, BER_FLAGS_NOOWNTAG
, dissect_snmp_GetNextRequest_PDU
},
2469 { 2, &hf_snmp_get_response
, BER_CLASS_CON
, 2, BER_FLAGS_NOOWNTAG
, dissect_snmp_GetResponse_PDU
},
2470 { 3, &hf_snmp_set_request
, BER_CLASS_CON
, 3, BER_FLAGS_NOOWNTAG
, dissect_snmp_SetRequest_PDU
},
2471 { 4, &hf_snmp_trap
, BER_CLASS_CON
, 4, BER_FLAGS_NOOWNTAG
, dissect_snmp_Trap_PDU
},
2472 { 5, &hf_snmp_getBulkRequest
, BER_CLASS_CON
, 5, BER_FLAGS_NOOWNTAG
, dissect_snmp_GetBulkRequest_PDU
},
2473 { 6, &hf_snmp_informRequest
, BER_CLASS_CON
, 6, BER_FLAGS_NOOWNTAG
, dissect_snmp_InformRequest_PDU
},
2474 { 7, &hf_snmp_snmpV2_trap
, BER_CLASS_CON
, 7, BER_FLAGS_NOOWNTAG
, dissect_snmp_SNMPv2_Trap_PDU
},
2475 { 8, &hf_snmp_report
, BER_CLASS_CON
, 8, BER_FLAGS_NOOWNTAG
, dissect_snmp_Report_PDU
},
2476 { 0, NULL
, 0, 0, 0, NULL
}
2480 dissect_snmp_PDUs(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2483 snmp_request_response_t
*srrp
;
2484 snmp_conv_info_t
*snmp_info
= (snmp_conv_info_t
*)actx
->private_data
;
2486 col_clear(actx
->pinfo
->cinfo
, COL_INFO
);
2488 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
2489 PDUs_choice
, hf_index
, ett_snmp_PDUs
,
2492 if( (pdu_type
!=-1) && snmp_PDUs_vals
[pdu_type
].strptr
){
2493 col_prepend_fstr(actx
->pinfo
->cinfo
, COL_INFO
, "%s", snmp_PDUs_vals
[pdu_type
].strptr
);
2495 /* pdu_type is the index, not the tag so convert it to the tag value */
2496 pdu_type
= snmp_PDUs_vals
[pdu_type
].value
;
2498 srrp
=snmp_match_request_response(tvb
, actx
->pinfo
, tree
, RequestID
, pdu_type
, snmp_info
);
2500 tap_queue_packet(snmp_tap
, actx
->pinfo
, srrp
);
2510 static const ber_sequence_t Message_sequence
[] = {
2511 { &hf_snmp_version
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_Version
},
2512 { &hf_snmp_community
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_Community
},
2513 { &hf_snmp_data
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
|BER_FLAGS_NOTCHKTAG
, dissect_snmp_PDUs
},
2514 { NULL
, 0, 0, 0, NULL
}
2518 dissect_snmp_Message(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2519 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2520 Message_sequence
, hf_index
, ett_snmp_Message
);
2528 dissect_snmp_OCTET_STRING(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2529 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2536 static const value_string snmp_T_datav2u_vals
[] = {
2542 static const ber_choice_t T_datav2u_choice
[] = {
2543 { 0, &hf_snmp_v2u_plaintext
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
, dissect_snmp_PDUs
},
2544 { 1, &hf_snmp_encrypted
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_OCTET_STRING
},
2545 { 0, NULL
, 0, 0, 0, NULL
}
2549 dissect_snmp_T_datav2u(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2550 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
2551 T_datav2u_choice
, hf_index
, ett_snmp_T_datav2u
,
2558 static const ber_sequence_t Messagev2u_sequence
[] = {
2559 { &hf_snmp_version
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_Version
},
2560 { &hf_snmp_parameters
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_OCTET_STRING
},
2561 { &hf_snmp_datav2u
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
|BER_FLAGS_NOTCHKTAG
, dissect_snmp_T_datav2u
},
2562 { NULL
, 0, 0, 0, NULL
}
2566 dissect_snmp_Messagev2u(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2567 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2568 Messagev2u_sequence
, hf_index
, ett_snmp_Messagev2u
);
2576 dissect_snmp_SnmpEngineID(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2577 tvbuff_t
* param_tvb
= NULL
;
2579 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, ¶m_tvb
);
2581 proto_tree
* engine_tree
= proto_item_add_subtree(actx
->created_item
,ett_engineid
);
2582 dissect_snmp_engineid(engine_tree
, actx
->pinfo
, param_tvb
, 0, tvb_reported_length_remaining(param_tvb
,0));
2592 dissect_snmp_T_msgAuthoritativeEngineID(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2594 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, &usm_p
.engine_tvb
);
2595 if (usm_p
.engine_tvb
) {
2596 proto_tree
* engine_tree
= proto_item_add_subtree(actx
->created_item
,ett_engineid
);
2597 dissect_snmp_engineid(engine_tree
, actx
->pinfo
, usm_p
.engine_tvb
, 0, tvb_reported_length_remaining(usm_p
.engine_tvb
,0));
2607 dissect_snmp_T_msgAuthoritativeEngineBoots(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2608 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2617 dissect_snmp_T_msgAuthoritativeEngineTime(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2618 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2627 dissect_snmp_T_msgUserName(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2628 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2637 dissect_snmp_T_msgAuthenticationParameters(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2638 offset
= dissect_ber_octet_string(false, actx
, tree
, tvb
, offset
, hf_index
, &usm_p
.auth_tvb
);
2639 if (usm_p
.auth_tvb
) {
2640 usm_p
.auth_item
= actx
->created_item
;
2641 usm_p
.auth_offset
= tvb_offset_from_real_beginning(usm_p
.auth_tvb
);
2650 dissect_snmp_T_msgPrivacyParameters(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2651 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2658 static const ber_sequence_t UsmSecurityParameters_sequence
[] = {
2659 { &hf_snmp_msgAuthoritativeEngineID
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_msgAuthoritativeEngineID
},
2660 { &hf_snmp_msgAuthoritativeEngineBoots
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_msgAuthoritativeEngineBoots
},
2661 { &hf_snmp_msgAuthoritativeEngineTime
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_msgAuthoritativeEngineTime
},
2662 { &hf_snmp_msgUserName
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_msgUserName
},
2663 { &hf_snmp_msgAuthenticationParameters
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_msgAuthenticationParameters
},
2664 { &hf_snmp_msgPrivacyParameters
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_msgPrivacyParameters
},
2665 { NULL
, 0, 0, 0, NULL
}
2669 dissect_snmp_UsmSecurityParameters(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2670 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2671 UsmSecurityParameters_sequence
, hf_index
, ett_snmp_UsmSecurityParameters
);
2679 dissect_snmp_INTEGER_484_2147483647(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2680 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2689 dissect_snmp_T_msgFlags(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2690 tvbuff_t
*parameter_tvb
= NULL
;
2692 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2696 uint8_t v3_flags
= tvb_get_uint8(parameter_tvb
, 0);
2697 proto_tree
* flags_tree
= proto_item_add_subtree(actx
->created_item
,ett_msgFlags
);
2699 proto_tree_add_item(flags_tree
, hf_snmp_v3_flags_report
, parameter_tvb
, 0, 1, ENC_BIG_ENDIAN
);
2700 proto_tree_add_item(flags_tree
, hf_snmp_v3_flags_crypt
, parameter_tvb
, 0, 1, ENC_BIG_ENDIAN
);
2701 proto_tree_add_item(flags_tree
, hf_snmp_v3_flags_auth
, parameter_tvb
, 0, 1, ENC_BIG_ENDIAN
);
2703 usm_p
.encrypted
= v3_flags
& TH_CRYPT
? true : false;
2704 usm_p
.authenticated
= v3_flags
& TH_AUTH
? true : false;
2715 dissect_snmp_T_msgSecurityModel(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2716 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2723 static const ber_sequence_t HeaderData_sequence
[] = {
2724 { &hf_snmp_msgID
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_INTEGER_0_2147483647
},
2725 { &hf_snmp_msgMaxSize
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_INTEGER_484_2147483647
},
2726 { &hf_snmp_msgFlags
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_msgFlags
},
2727 { &hf_snmp_msgSecurityModel
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_msgSecurityModel
},
2728 { NULL
, 0, 0, 0, NULL
}
2732 dissect_snmp_HeaderData(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2733 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2734 HeaderData_sequence
, hf_index
, ett_snmp_HeaderData
);
2742 dissect_snmp_T_msgSecurityParameters(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2744 switch(MsgSecurityModel
){
2745 case SNMP_SEC_USM
: /* 3 */
2746 offset
= get_ber_identifier(tvb
, offset
, NULL
, NULL
, NULL
);
2747 offset
= get_ber_length(tvb
, offset
, NULL
, NULL
);
2748 offset
= dissect_snmp_UsmSecurityParameters(false, tvb
, offset
, actx
, tree
, -1);
2749 usm_p
.user_assoc
= get_user_assoc(usm_p
.engine_tvb
, usm_p
.user_tvb
, actx
->pinfo
);
2751 case SNMP_SEC_ANY
: /* 0 */
2752 case SNMP_SEC_V1
: /* 1 */
2753 case SNMP_SEC_V2C
: /* 2 */
2755 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2766 static const ber_sequence_t ScopedPDU_sequence
[] = {
2767 { &hf_snmp_contextEngineID
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_SnmpEngineID
},
2768 { &hf_snmp_contextName
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_OCTET_STRING
},
2769 { &hf_snmp_data
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
|BER_FLAGS_NOTCHKTAG
, dissect_snmp_PDUs
},
2770 { NULL
, 0, 0, 0, NULL
}
2774 dissect_snmp_ScopedPDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2775 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2776 ScopedPDU_sequence
, hf_index
, ett_snmp_ScopedPDU
);
2784 dissect_snmp_T_encryptedPDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2785 tvbuff_t
* crypt_tvb
;
2786 offset
= dissect_ber_octet_string(false, actx
, tree
, tvb
, offset
, hf_snmp_encryptedPDU
, &crypt_tvb
);
2788 if( usm_p
.encrypted
&& crypt_tvb
2790 && usm_p
.user_assoc
->user
.privProtocol
) {
2792 const char* error
= NULL
;
2793 proto_tree
* encryptedpdu_tree
= proto_item_add_subtree(actx
->created_item
,ett_encryptedPDU
);
2794 tvbuff_t
* cleartext_tvb
= usm_p
.user_assoc
->user
.privProtocol(&usm_p
, crypt_tvb
, actx
->pinfo
, &error
);
2796 if (! cleartext_tvb
) {
2797 proto_tree_add_expert_format(encryptedpdu_tree
, actx
->pinfo
, &ei_snmp_failed_decrypted_data_pdu
,
2798 crypt_tvb
, 0, -1, "Failed to decrypt encryptedPDU: %s", error
);
2800 col_set_str(actx
->pinfo
->cinfo
, COL_INFO
, "encryptedPDU: Failed to decrypt");
2804 proto_item
* decrypted_item
;
2805 proto_tree
* decrypted_tree
;
2807 if (! check_ScopedPdu(cleartext_tvb
)) {
2808 proto_tree_add_expert(encryptedpdu_tree
, actx
->pinfo
, &ei_snmp_decrypted_data_bad_formatted
, cleartext_tvb
, 0, -1);
2810 col_set_str(actx
->pinfo
->cinfo
, COL_INFO
, "encryptedPDU: Decrypted data not formatted as expected");
2816 add_new_data_source(actx
->pinfo
, cleartext_tvb
, "Decrypted ScopedPDU");
2818 decrypted_item
= proto_tree_add_item(encryptedpdu_tree
, hf_snmp_decryptedPDU
,cleartext_tvb
,0,-1,ENC_NA
);
2819 decrypted_tree
= proto_item_add_subtree(decrypted_item
,ett_decrypted
);
2820 dissect_snmp_ScopedPDU(false, cleartext_tvb
, 0, actx
, decrypted_tree
, -1);
2823 col_set_str(actx
->pinfo
->cinfo
, COL_INFO
, "encryptedPDU: privKey Unknown");
2831 static const value_string snmp_ScopedPduData_vals
[] = {
2833 { 1, "encryptedPDU" },
2837 static const ber_choice_t ScopedPduData_choice
[] = {
2838 { 0, &hf_snmp_plaintext
, BER_CLASS_UNI
, BER_UNI_TAG_SEQUENCE
, BER_FLAGS_NOOWNTAG
, dissect_snmp_ScopedPDU
},
2839 { 1, &hf_snmp_encryptedPDU
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_encryptedPDU
},
2840 { 0, NULL
, 0, 0, 0, NULL
}
2844 dissect_snmp_ScopedPduData(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2845 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
2846 ScopedPduData_choice
, hf_index
, ett_snmp_ScopedPduData
,
2853 static const ber_sequence_t SNMPv3Message_sequence
[] = {
2854 { &hf_snmp_msgVersion
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_Version
},
2855 { &hf_snmp_msgGlobalData
, BER_CLASS_UNI
, BER_UNI_TAG_SEQUENCE
, BER_FLAGS_NOOWNTAG
, dissect_snmp_HeaderData
},
2856 { &hf_snmp_msgSecurityParameters
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_msgSecurityParameters
},
2857 { &hf_snmp_msgData
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
|BER_FLAGS_NOTCHKTAG
, dissect_snmp_ScopedPduData
},
2858 { NULL
, 0, 0, 0, NULL
}
2862 dissect_snmp_SNMPv3Message(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2863 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2864 SNMPv3Message_sequence
, hf_index
, ett_snmp_SNMPv3Message
);
2867 if( usm_p
.authenticated
2868 && usm_p
.user_assoc
) {
2869 const char* error
= NULL
;
2870 proto_item
* authen_item
;
2871 proto_tree
* authen_tree
= proto_item_add_subtree(usm_p
.auth_item
,ett_authParameters
);
2872 uint8_t* calc_auth
= NULL
;
2873 unsigned calc_auth_len
= 0;
2875 usm_p
.authOK
= snmp_usm_auth(actx
->pinfo
, usm_p
.user_assoc
->user
.authModel
, &usm_p
, &calc_auth
, &calc_auth_len
, &error
);
2878 expert_add_info_format( actx
->pinfo
, usm_p
.auth_item
, &ei_snmp_verify_authentication_error
, "Error while verifying Message authenticity: %s", error
);
2880 expert_field
* expert
;
2882 authen_item
= proto_tree_add_boolean(authen_tree
, hf_snmp_msgAuthentication
, tvb
, 0, 0, usm_p
.authOK
);
2883 proto_item_set_generated(authen_item
);
2886 expert
= &ei_snmp_authentication_ok
;
2888 const char* calc_auth_str
= bytes_to_str_punct(actx
->pinfo
->pool
, calc_auth
,calc_auth_len
,' ');
2889 proto_item_append_text(authen_item
, " calculated = %s", calc_auth_str
);
2890 expert
= &ei_snmp_authentication_error
;
2893 expert_add_info( actx
->pinfo
, authen_item
, expert
);
2901 static const value_string snmp_T_smux_version_vals
[] = {
2908 dissect_snmp_T_smux_version(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2909 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2918 dissect_snmp_OBJECT_IDENTIFIER(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2919 offset
= dissect_ber_object_identifier(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, NULL
);
2927 dissect_snmp_DisplayString(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2928 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
2935 static const ber_sequence_t SimpleOpen_U_sequence
[] = {
2936 { &hf_snmp_smux_version
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_smux_version
},
2937 { &hf_snmp_identity
, BER_CLASS_UNI
, BER_UNI_TAG_OID
, BER_FLAGS_NOOWNTAG
, dissect_snmp_OBJECT_IDENTIFIER
},
2938 { &hf_snmp_description
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_DisplayString
},
2939 { &hf_snmp_password
, BER_CLASS_UNI
, BER_UNI_TAG_OCTETSTRING
, BER_FLAGS_NOOWNTAG
, dissect_snmp_OCTET_STRING
},
2940 { NULL
, 0, 0, 0, NULL
}
2944 dissect_snmp_SimpleOpen_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2945 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
2946 SimpleOpen_U_sequence
, hf_index
, ett_snmp_SimpleOpen_U
);
2954 dissect_snmp_SimpleOpen(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2955 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
2956 hf_index
, BER_CLASS_APP
, 0, true, dissect_snmp_SimpleOpen_U
);
2962 static const value_string snmp_OpenPDU_vals
[] = {
2963 { 0, "smux-simple" },
2967 static const ber_choice_t OpenPDU_choice
[] = {
2968 { 0, &hf_snmp_smux_simple
, BER_CLASS_APP
, 0, BER_FLAGS_NOOWNTAG
, dissect_snmp_SimpleOpen
},
2969 { 0, NULL
, 0, 0, 0, NULL
}
2973 dissect_snmp_OpenPDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2974 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
2975 OpenPDU_choice
, hf_index
, ett_snmp_OpenPDU
,
2982 static const value_string snmp_ClosePDU_U_vals
[] = {
2984 { 1, "unsupportedVersion" },
2985 { 2, "packetFormat" },
2986 { 3, "protocolError" },
2987 { 4, "internalError" },
2988 { 5, "authenticationFailure" },
2994 dissect_snmp_ClosePDU_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
2995 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
3004 dissect_snmp_ClosePDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3005 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
3006 hf_index
, BER_CLASS_APP
, 1, true, dissect_snmp_ClosePDU_U
);
3014 dissect_snmp_INTEGER_M1_2147483647(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3015 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
3022 static const value_string snmp_T_operation_vals
[] = {
3031 dissect_snmp_T_operation(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3032 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
3039 static const ber_sequence_t RReqPDU_U_sequence
[] = {
3040 { &hf_snmp_subtree
, BER_CLASS_UNI
, BER_UNI_TAG_OID
, BER_FLAGS_NOOWNTAG
, dissect_snmp_ObjectName
},
3041 { &hf_snmp_priority
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_INTEGER_M1_2147483647
},
3042 { &hf_snmp_operation
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_NOOWNTAG
, dissect_snmp_T_operation
},
3043 { NULL
, 0, 0, 0, NULL
}
3047 dissect_snmp_RReqPDU_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3048 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
3049 RReqPDU_U_sequence
, hf_index
, ett_snmp_RReqPDU_U
);
3057 dissect_snmp_RReqPDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3058 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
3059 hf_index
, BER_CLASS_APP
, 2, true, dissect_snmp_RReqPDU_U
);
3065 static const value_string snmp_RRspPDU_U_vals
[] = {
3072 dissect_snmp_RRspPDU_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3073 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
3082 dissect_snmp_RRspPDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3083 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
3084 hf_index
, BER_CLASS_APP
, 3, true, dissect_snmp_RRspPDU_U
);
3090 static const value_string snmp_RegisterResponse_vals
[] = {
3096 static const ber_choice_t RegisterResponse_choice
[] = {
3097 { 0, &hf_snmp_rRspPDU
, BER_CLASS_APP
, 3, BER_FLAGS_NOOWNTAG
, dissect_snmp_RRspPDU
},
3098 { 1, &hf_snmp_pDUs
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
, dissect_snmp_PDUs
},
3099 { 0, NULL
, 0, 0, 0, NULL
}
3103 dissect_snmp_RegisterResponse(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3104 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
3105 RegisterResponse_choice
, hf_index
, ett_snmp_RegisterResponse
,
3112 static const value_string snmp_SOutPDU_U_vals
[] = {
3120 dissect_snmp_SOutPDU_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3121 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
3130 dissect_snmp_SOutPDU(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3131 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
3132 hf_index
, BER_CLASS_APP
, 4, true, dissect_snmp_SOutPDU_U
);
3138 static const value_string snmp_SMUX_PDUs_vals
[] = {
3141 { 2, "registerRequest" },
3142 { 3, "registerResponse" },
3143 { 4, "commitOrRollback" },
3147 static const ber_choice_t SMUX_PDUs_choice
[] = {
3148 { 0, &hf_snmp_open
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
, dissect_snmp_OpenPDU
},
3149 { 1, &hf_snmp_close
, BER_CLASS_APP
, 1, BER_FLAGS_NOOWNTAG
, dissect_snmp_ClosePDU
},
3150 { 2, &hf_snmp_registerRequest
, BER_CLASS_APP
, 2, BER_FLAGS_NOOWNTAG
, dissect_snmp_RReqPDU
},
3151 { 3, &hf_snmp_registerResponse
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
, dissect_snmp_RegisterResponse
},
3152 { 4, &hf_snmp_commitOrRollback
, BER_CLASS_APP
, 4, BER_FLAGS_NOOWNTAG
, dissect_snmp_SOutPDU
},
3153 { 0, NULL
, 0, 0, 0, NULL
}
3157 dissect_snmp_SMUX_PDUs(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
3159 snmp_conv_info_t
*snmp_info
= snmp_find_conversation_and_get_conv_data(actx
->pinfo
);
3161 actx
->private_data
= snmp_info
;
3163 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
3164 SMUX_PDUs_choice
, hf_index
, ett_snmp_SMUX_PDUs
,
3172 static int dissect_SMUX_PDUs_PDU(tvbuff_t
*tvb _U_
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
, void *data _U_
) {
3174 asn1_ctx_t asn1_ctx
;
3175 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_BER
, true, pinfo
);
3176 offset
= dissect_snmp_SMUX_PDUs(false, tvb
, offset
, &asn1_ctx
, tree
, hf_snmp_SMUX_PDUs_PDU
);
3181 static snmp_conv_info_t
*
3182 snmp_find_conversation_and_get_conv_data(packet_info
*pinfo
) {
3184 conversation_t
*conversation
= NULL
;
3185 snmp_conv_info_t
*snmp_info
= NULL
;
3187 /* Get the conversation with the wildcarded port, if it exists
3188 * and is associated with SNMP, so that requests and responses
3189 * can be matched even if the response comes from a different,
3190 * ephemeral, source port, as originally done in OS/400.
3191 * On UDP, we do not automatically call conversation_set_port2()
3192 * and we do not want to do so. Possibly this should eventually
3193 * use find_conversation_full and separate the "SNMP conversation"
3194 * from "the transport layer conversation that carries SNMP."
3196 if (pinfo
->destport
== UDP_PORT_SNMP
) {
3197 conversation
= find_conversation(pinfo
->fd
->num
, &pinfo
->src
, &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
),
3198 pinfo
->srcport
, 0, NO_PORT_B
);
3199 } else if (pinfo
->srcport
== UDP_PORT_SNMP
) {
3200 conversation
= find_conversation(pinfo
->fd
->num
, &pinfo
->dst
, &pinfo
->src
, conversation_pt_to_conversation_type(pinfo
->ptype
),
3201 pinfo
->destport
, 0, NO_PORT_B
);
3203 if ((conversation
== NULL
) || (conversation_get_dissector(conversation
, pinfo
->num
) != snmp_handle
)) {
3204 conversation
= find_or_create_conversation(pinfo
);
3207 snmp_info
= (snmp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_snmp
);
3208 if (snmp_info
== NULL
) {
3209 snmp_info
= wmem_new0(wmem_file_scope(), snmp_conv_info_t
);
3210 snmp_info
->request_response
=wmem_map_new(wmem_file_scope(), g_int_hash
, g_int_equal
);
3212 conversation_add_proto_data(conversation
, proto_snmp
, snmp_info
);
3218 dissect_snmp_pdu(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
3219 proto_tree
*tree
, int proto
, int ett
, bool is_tcp
)
3222 unsigned length_remaining
;
3227 unsigned message_length
;
3228 int start_offset
= offset
;
3229 uint32_t version
= 0;
3232 proto_tree
*snmp_tree
= NULL
;
3233 proto_item
*item
= NULL
;
3235 snmp_conv_info_t
*snmp_info
= snmp_find_conversation_and_get_conv_data(pinfo
);
3237 asn1_ctx_t asn1_ctx
;
3238 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_BER
, true, pinfo
);
3240 asn1_ctx
.private_data
= snmp_info
;
3242 usm_p
.msg_tvb
= tvb
;
3243 usm_p
.start_offset
= tvb_offset_from_real_beginning(tvb
);
3244 usm_p
.engine_tvb
= NULL
;
3245 usm_p
.user_tvb
= NULL
;
3246 usm_p
.auth_item
= NULL
;
3247 usm_p
.auth_tvb
= NULL
;
3248 usm_p
.auth_offset
= 0;
3249 usm_p
.priv_tvb
= NULL
;
3250 usm_p
.user_assoc
= NULL
;
3251 usm_p
.authenticated
= false;
3252 usm_p
.encrypted
= false;
3254 usm_p
.snmp_time
= 0;
3255 usm_p
.authOK
= false;
3258 * This will throw an exception if we don't have any data left.
3259 * That's what we want. (See "tcp_dissect_pdus()", which is
3260 * similar, but doesn't have to deal with ASN.1.
3261 * XXX - can we make "tcp_dissect_pdus()" provide enough
3262 * information to the "get_pdu_len" routine so that we could
3263 * have that routine deal with ASN.1, and just use
3264 * "tcp_dissect_pdus()"?)
3266 length_remaining
= tvb_ensure_captured_length_remaining(tvb
, offset
);
3268 /* NOTE: we have to parse the message piece by piece, since the
3269 * capture length may be less than the message length: a 'global'
3270 * parsing is likely to fail.
3274 * If this is SNMP-over-TCP, we might have to do reassembly
3275 * in order to read the "Sequence Of" header.
3277 if (is_tcp
&& snmp_desegment
&& pinfo
->can_desegment
) {
3279 * This is TCP, and we should, and can, do reassembly.
3281 * Is the "Sequence Of" header split across segment
3282 * boundaries? We require at least 6 bytes for the
3283 * header, which allows for a 4-byte length (ASN.1
3286 if (length_remaining
< 6) {
3288 * Yes. Tell the TCP dissector where the data
3289 * for this message starts in the data it handed
3290 * us and that we need "some more data." Don't tell
3291 * it exactly how many bytes we need because if/when
3292 * we ask for even more (after the header) that will
3295 pinfo
->desegment_offset
= offset
;
3296 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
3302 * OK, try to read the "Sequence Of" header; this gets the total
3303 * length of the SNMP message.
3305 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
3306 /*Get the total octet length of the SNMP data*/
3307 offset
= get_ber_length(tvb
, offset
, &len
, &ind
);
3308 message_length
= len
+ offset
;
3310 /*Get the SNMP version data*/
3311 /*offset =*/ dissect_ber_integer(false, &asn1_ctx
, 0, tvb
, offset
, -1, &version
);
3315 * If this is SNMP-over-TCP, we might have to do reassembly
3316 * to get all of this message.
3318 if (is_tcp
&& snmp_desegment
&& pinfo
->can_desegment
) {
3320 * Yes - is the message split across segment boundaries?
3322 if (length_remaining
< message_length
) {
3324 * Yes. Tell the TCP dissector where the data
3325 * for this message starts in the data it handed
3326 * us, and how many more bytes we need, and
3329 pinfo
->desegment_offset
= start_offset
;
3330 pinfo
->desegment_len
=
3331 message_length
- length_remaining
;
3334 * Return 0, which means "I didn't dissect anything
3335 * because I don't have enough data - we need
3342 var_list
= next_tvb_list_new(pinfo
->pool
);
3344 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, proto_get_protocol_short_name(find_protocol_by_id(proto
)));
3346 item
= proto_tree_add_item(tree
, proto
, tvb
, start_offset
, message_length
, ENC_BIG_ENDIAN
);
3347 snmp_tree
= proto_item_add_subtree(item
, ett
);
3352 offset
= dissect_snmp_Message(false , tvb
, start_offset
, &asn1_ctx
, snmp_tree
, -1);
3355 offset
= dissect_snmp_Messagev2u(false , tvb
, start_offset
, &asn1_ctx
, snmp_tree
, -1);
3359 offset
= dissect_snmp_SNMPv3Message(false , tvb
, start_offset
, &asn1_ctx
, snmp_tree
, -1);
3363 * Return the length remaining in the tvbuff, so
3364 * if this is SNMP-over-TCP, our caller thinks there's
3365 * nothing left to dissect.
3367 expert_add_info(pinfo
, item
, &ei_snmp_version_unknown
);
3368 return length_remaining
;
3371 /* There may be appended data after the SNMP data, so treat as raw
3372 * data which needs to be dissected in case of UDP as UDP is PDU oriented.
3374 if((!is_tcp
) && (length_remaining
> (unsigned)offset
)) {
3375 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
3376 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
3378 next_tvb_call(var_list
, pinfo
, tree
, NULL
, data_handle
);
3385 dissect_snmp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
3391 uint32_t tmp_length
;
3395 * See if this looks like SNMP or not. if not, return 0 so
3396 * wireshark can try some other dissector instead.
3398 /* All SNMP packets are BER encoded and consist of a SEQUENCE
3399 * that spans the entire PDU. The first item is an INTEGER that
3400 * has the values 0-2 (version 1-3).
3401 * if not it is not snmp.
3403 /* SNMP starts with a SEQUENCE */
3404 offset
= get_ber_identifier(tvb
, 0, &tmp_class
, &tmp_pc
, &tmp_tag
);
3405 if((tmp_class
!=BER_CLASS_UNI
)||(tmp_tag
!=BER_UNI_TAG_SEQUENCE
)) {
3408 /* then comes a length which spans the rest of the tvb */
3409 offset
= get_ber_length(tvb
, offset
, &tmp_length
, &tmp_ind
);
3410 /* Loosen the heuristic a bit to handle the case where data has intentionally
3411 * been added after the snmp PDU ( UDP case) (#3684)
3412 * If this is fragmented or carried in ICMP, we don't expect the tvb to
3413 * have the full legnth, so don't check.
3415 if (!pinfo
->fragmented
&& !pinfo
->flags
.in_error_pkt
) {
3416 if ( pinfo
->ptype
== PT_UDP
) {
3417 if(tmp_length
>(uint32_t)tvb_reported_length_remaining(tvb
, offset
)) {
3421 if(tmp_length
!=(uint32_t)tvb_reported_length_remaining(tvb
, offset
)) {
3426 /* then comes an INTEGER (version)*/
3427 get_ber_identifier(tvb
, offset
, &tmp_class
, &tmp_pc
, &tmp_tag
);
3428 if((tmp_class
!=BER_CLASS_UNI
)||(tmp_tag
!=BER_UNI_TAG_INTEGER
)) {
3431 /* do we need to test that version is 0 - 2 (version1-3) ? */
3435 * The IBM i (OS/400) SNMP agent, at least originally, would
3436 * send responses back from some *other* UDP port, an ephemeral
3437 * port above 5000, going back to the same IP address and port
3438 * from which the request came, similar to TFTP. This only happens
3439 * with the agent port, 161, not with the trap port, etc. As of
3440 * 2015 with the latest fixes applied, it no longer does this:
3441 * https://www.ibm.com/support/pages/ptf/SI55487
3442 * https://www.ibm.com/support/pages/ptf/SI55537
3444 * The SNMP RFCs are silent on this (cf. L2TP RFC 2661, which
3445 * supports using either the well-known port or an ephemeral
3446 * port as the source port for responses, while noting that
3447 * the latter can cause issues with firewalls and NATs.) so
3448 * possibly some other implementations could do this.
3450 * If this packet went to the SNMP port, we check to see if
3451 * there's already a conversation with one address/port pair
3452 * matching the source IP address and port of this packet,
3453 * the other address matching the destination IP address of this
3454 * packet, and any destination port.
3456 * If not, we create one, with its address 1/port 1 pair being
3457 * the source address/port of this packet, its address 2 being
3458 * the destination address of this packet, and its port 2 being
3459 * wildcarded, and give it the SNMP dissector as a dissector.
3462 if (pinfo
->destport
== UDP_PORT_SNMP
) {
3463 conversation_t
*conversation
= find_conversation(pinfo
->fd
->num
, &pinfo
->src
, &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
),
3464 pinfo
->srcport
, 0, NO_PORT_B
);
3466 if( (conversation
== NULL
) || (conversation_get_dissector(conversation
, pinfo
->num
)!=snmp_handle
) ) {
3467 conversation
= conversation_new(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
),
3468 pinfo
->srcport
, 0, NO_PORT2
);
3469 conversation_set_dissector(conversation
, snmp_handle
);
3473 return dissect_snmp_pdu(tvb
, 0, pinfo
, tree
, proto_snmp
, ett_snmp
, false);
3477 dissect_snmp_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
3480 unsigned message_len
;
3482 while (tvb_reported_length_remaining(tvb
, offset
) > 0) {
3483 message_len
= dissect_snmp_pdu(tvb
, offset
, pinfo
, tree
, proto_snmp
, ett_snmp
, true);
3484 if (message_len
== 0) {
3486 * We don't have all the data for that message,
3487 * so we need to do desegmentation;
3488 * "dissect_snmp_pdu()" has set that up.
3492 offset
+= message_len
;
3494 return tvb_captured_length(tvb
);
3498 dissect_smux(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
3500 proto_tree
*smux_tree
= NULL
;
3501 proto_item
*item
= NULL
;
3503 var_list
= next_tvb_list_new(pinfo
->pool
);
3505 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SMUX");
3507 item
= proto_tree_add_item(tree
, proto_smux
, tvb
, 0, -1, ENC_NA
);
3508 smux_tree
= proto_item_add_subtree(item
, ett_smux
);
3510 return dissect_SMUX_PDUs_PDU(tvb
, pinfo
, smux_tree
, data
);
3514 MD5 Password to Key Algorithm from RFC 3414 A.2.1
3515 SHA1 Password to Key Algorithm from RFC 3414 A.2.2
3516 SHA2 Password to Key Algorithm from RFC 7860 9.3
3519 snmp_usm_password_to_key(const snmp_usm_auth_model_t model
, const uint8_t *password
,
3520 unsigned passwordlen
, const uint8_t *engineID
, unsigned engineLength
, uint8_t *key
)
3522 gcry_md_hd_t hash_handle
;
3523 uint8_t *cp
, password_buf
[64];
3524 uint32_t password_index
= 0;
3525 uint32_t count
= 0, i
;
3528 if (gcry_md_open(&hash_handle
, auth_hash_algo
[model
], 0)) {
3532 hash_len
= auth_hash_len
[model
];
3534 /**********************************************/
3535 /* Use while loop until we've done 1 Megabyte */
3536 /**********************************************/
3537 while (count
< 1048576) {
3539 if (passwordlen
!= 0) {
3540 for (i
= 0; i
< 64; i
++) {
3541 /*************************************************/
3542 /* Take the next octet of the password, wrapping */
3543 /* to the beginning of the password as necessary.*/
3544 /*************************************************/
3545 *cp
++ = password
[password_index
++ % passwordlen
];
3550 gcry_md_write(hash_handle
, password_buf
, 64);
3553 memcpy(key
, gcry_md_read(hash_handle
, 0), hash_len
);
3554 gcry_md_close(hash_handle
);
3556 /*****************************************************/
3557 /* Now localise the key with the engineID and pass */
3558 /* through hash function to produce final key */
3559 /* We ignore invalid engineLengths here. More strict */
3560 /* checking is done in snmp_users_update_cb. */
3561 /*****************************************************/
3562 if (gcry_md_open(&hash_handle
, auth_hash_algo
[model
], 0)) {
3565 gcry_md_write(hash_handle
, key
, hash_len
);
3566 gcry_md_write(hash_handle
, engineID
, engineLength
);
3567 gcry_md_write(hash_handle
, key
, hash_len
);
3568 memcpy(key
, gcry_md_read(hash_handle
, 0), hash_len
);
3569 gcry_md_close(hash_handle
);
3578 UAT_LSTRING_CB_DEF(snmp_users
,userName
,snmp_ue_assoc_t
,user
.userName
.data
,user
.userName
.len
)
3579 UAT_LSTRING_CB_DEF(snmp_users
,authPassword
,snmp_ue_assoc_t
,user
.authPassword
.data
,user
.authPassword
.len
)
3580 UAT_LSTRING_CB_DEF(snmp_users
,privPassword
,snmp_ue_assoc_t
,user
.privPassword
.data
,user
.privPassword
.len
)
3581 UAT_BUFFER_CB_DEF(snmp_users
,engine_id
,snmp_ue_assoc_t
,engine
.data
,engine
.len
)
3582 UAT_VS_DEF(snmp_users
,auth_model
,snmp_ue_assoc_t
,unsigned,0,"MD5")
3583 UAT_VS_DEF(snmp_users
,priv_proto
,snmp_ue_assoc_t
,unsigned,0,"DES")
3584 UAT_VS_DEF(snmp_users
,priv_key_exp
,snmp_ue_assoc_t
,unsigned,0,"draft-reeder-snmpv3-usm-3desede-00")
3587 snmp_specific_trap_copy_cb(void *dest
, const void *orig
, size_t len _U_
)
3589 snmp_st_assoc_t
*u
= (snmp_st_assoc_t
*)dest
;
3590 const snmp_st_assoc_t
*o
= (const snmp_st_assoc_t
*)orig
;
3592 u
->enterprise
= g_strdup(o
->enterprise
);
3594 u
->desc
= g_strdup(o
->desc
);
3600 snmp_specific_trap_free_cb(void *r
)
3602 snmp_st_assoc_t
*u
= (snmp_st_assoc_t
*)r
;
3604 g_free(u
->enterprise
);
3608 UAT_CSTRING_CB_DEF(specific_traps
, enterprise
, snmp_st_assoc_t
)
3609 UAT_DEC_CB_DEF(specific_traps
, trap
, snmp_st_assoc_t
)
3610 UAT_CSTRING_CB_DEF(specific_traps
, desc
, snmp_st_assoc_t
)
3612 /*--- proto_register_snmp -------------------------------------------*/
3613 void proto_register_snmp(void) {
3614 /* List of fields */
3615 static hf_register_info hf
[] = {
3616 { &hf_snmp_response_in
,
3617 { "Response In", "snmp.response_in", FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0,
3618 "The response to this SNMP request is in this frame", HFILL
}},
3619 { &hf_snmp_response_to
,
3620 { "Response To", "snmp.response_to", FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0,
3621 "This is a response to the SNMP request in this frame", HFILL
}},
3623 { "Time", "snmp.time", FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
3624 "The time between the Request and the Response", HFILL
}},
3625 { &hf_snmp_v3_flags_auth
,
3626 { "Authenticated", "snmp.v3.flags.auth", FT_BOOLEAN
, 8,
3627 TFS(&tfs_set_notset
), TH_AUTH
, NULL
, HFILL
}},
3628 { &hf_snmp_v3_flags_crypt
,
3629 { "Encrypted", "snmp.v3.flags.crypt", FT_BOOLEAN
, 8,
3630 TFS(&tfs_set_notset
), TH_CRYPT
, NULL
, HFILL
}},
3631 { &hf_snmp_v3_flags_report
,
3632 { "Reportable", "snmp.v3.flags.report", FT_BOOLEAN
, 8,
3633 TFS(&tfs_set_notset
), TH_REPORT
, NULL
, HFILL
}},
3634 { &hf_snmp_engineid_conform
, {
3635 "Engine ID Conformance", "snmp.engineid.conform", FT_BOOLEAN
, 8,
3636 TFS(&tfs_snmp_engineid_conform
), F_SNMP_ENGINEID_CONFORM
, "Engine ID RFC3411 Conformance", HFILL
}},
3637 { &hf_snmp_engineid_enterprise
, {
3638 "Engine Enterprise ID", "snmp.engineid.enterprise", FT_UINT32
, BASE_ENTERPRISES
,
3639 STRINGS_ENTERPRISES
, 0, NULL
, HFILL
}},
3640 { &hf_snmp_engineid_format
, {
3641 "Engine ID Format", "snmp.engineid.format", FT_UINT8
, BASE_DEC
,
3642 VALS(snmp_engineid_format_vals
), 0, NULL
, HFILL
}},
3643 { &hf_snmp_engineid_ipv4
, {
3644 "Engine ID Data: IPv4 address", "snmp.engineid.ipv4", FT_IPv4
, BASE_NONE
,
3645 NULL
, 0, NULL
, HFILL
}},
3646 { &hf_snmp_engineid_ipv6
, {
3647 "Engine ID Data: IPv6 address", "snmp.engineid.ipv6", FT_IPv6
, BASE_NONE
,
3648 NULL
, 0, NULL
, HFILL
}},
3649 { &hf_snmp_engineid_cisco_type
, {
3650 "Engine ID Data: Cisco type", "snmp.engineid.cisco.type", FT_UINT8
, BASE_HEX
,
3651 VALS(snmp_engineid_cisco_type_vals
), 0, NULL
, HFILL
}},
3652 { &hf_snmp_engineid_mac
, {
3653 "Engine ID Data: MAC address", "snmp.engineid.mac", FT_ETHER
, BASE_NONE
,
3654 NULL
, 0, NULL
, HFILL
}},
3655 { &hf_snmp_engineid_text
, {
3656 "Engine ID Data: Text", "snmp.engineid.text", FT_STRING
, BASE_NONE
,
3657 NULL
, 0, NULL
, HFILL
}},
3658 { &hf_snmp_engineid_time
, {
3659 "Engine ID Data: Creation Time", "snmp.engineid.time", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
3660 NULL
, 0, NULL
, HFILL
}},
3661 { &hf_snmp_engineid_data
, {
3662 "Engine ID Data", "snmp.engineid.data", FT_BYTES
, BASE_NONE
,
3663 NULL
, 0, NULL
, HFILL
}},
3664 { &hf_snmp_msgAuthentication
, {
3665 "Authentication", "snmp.v3.auth", FT_BOOLEAN
, BASE_NONE
,
3666 TFS(&auth_flags
), 0, NULL
, HFILL
}},
3667 { &hf_snmp_decryptedPDU
, {
3668 "Decrypted ScopedPDU", "snmp.decrypted_pdu", FT_BYTES
, BASE_NONE
,
3669 NULL
, 0, "Decrypted PDU", HFILL
}},
3670 { &hf_snmp_noSuchObject
, {
3671 "noSuchObject", "snmp.noSuchObject", FT_NONE
, BASE_NONE
,
3672 NULL
, 0, NULL
, HFILL
}},
3673 { &hf_snmp_noSuchInstance
, {
3674 "noSuchInstance", "snmp.noSuchInstance", FT_NONE
, BASE_NONE
,
3675 NULL
, 0, NULL
, HFILL
}},
3676 { &hf_snmp_endOfMibView
, {
3677 "endOfMibView", "snmp.endOfMibView", FT_NONE
, BASE_NONE
,
3678 NULL
, 0, NULL
, HFILL
}},
3679 { &hf_snmp_unSpecified
, {
3680 "unSpecified", "snmp.unSpecified", FT_NONE
, BASE_NONE
,
3681 NULL
, 0, NULL
, HFILL
}},
3683 { &hf_snmp_integer32_value
, {
3684 "Value (Integer32)", "snmp.value.int", FT_INT64
, BASE_DEC
,
3685 NULL
, 0, NULL
, HFILL
}},
3686 { &hf_snmp_octetstring_value
, {
3687 "Value (OctetString)", "snmp.value.octets", FT_BYTES
, BASE_SHOW_ASCII_PRINTABLE
,
3688 NULL
, 0, NULL
, HFILL
}},
3689 { &hf_snmp_oid_value
, {
3690 "Value (OID)", "snmp.value.oid", FT_OID
, BASE_NONE
,
3691 NULL
, 0, NULL
, HFILL
}},
3692 { &hf_snmp_null_value
, {
3693 "Value (Null)", "snmp.value.null", FT_NONE
, BASE_NONE
,
3694 NULL
, 0, NULL
, HFILL
}},
3695 { &hf_snmp_ipv4_value
, {
3696 "Value (IpAddress)", "snmp.value.ipv4", FT_IPv4
, BASE_NONE
,
3697 NULL
, 0, NULL
, HFILL
}},
3698 { &hf_snmp_ipv6_value
, {
3699 "Value (IpAddress)", "snmp.value.ipv6", FT_IPv6
, BASE_NONE
,
3700 NULL
, 0, NULL
, HFILL
}},
3701 { &hf_snmp_anyaddress_value
, {
3702 "Value (IpAddress)", "snmp.value.addr", FT_BYTES
, BASE_NONE
,
3703 NULL
, 0, NULL
, HFILL
}},
3704 { &hf_snmp_unsigned32_value
, {
3705 "Value (Unsigned32)", "snmp.value.u32", FT_INT64
, BASE_DEC
,
3706 NULL
, 0, NULL
, HFILL
}},
3707 { &hf_snmp_gauge32_value
, {
3708 "Value (Gauge32)", "snmp.value.g32", FT_INT64
, BASE_DEC
,
3709 NULL
, 0, NULL
, HFILL
}},
3710 { &hf_snmp_unknown_value
, {
3711 "Value (Unknown)", "snmp.value.unk", FT_BYTES
, BASE_NONE
,
3712 NULL
, 0, NULL
, HFILL
}},
3713 { &hf_snmp_counter_value
, {
3714 "Value (Counter32)", "snmp.value.counter", FT_UINT64
, BASE_DEC
,
3715 NULL
, 0, NULL
, HFILL
}},
3716 { &hf_snmp_big_counter_value
, {
3717 "Value (Counter64)", "snmp.value.counter", FT_UINT64
, BASE_DEC
,
3718 NULL
, 0, NULL
, HFILL
}},
3719 { &hf_snmp_nsap_value
, {
3720 "Value (NSAP)", "snmp.value.nsap", FT_UINT64
, BASE_DEC
,
3721 NULL
, 0, NULL
, HFILL
}},
3722 { &hf_snmp_timeticks_value
, {
3723 "Value (Timeticks)", "snmp.value.timeticks", FT_UINT64
, BASE_DEC
,
3724 NULL
, 0, NULL
, HFILL
}},
3725 { &hf_snmp_opaque_value
, {
3726 "Value (Opaque)", "snmp.value.opaque", FT_BYTES
, BASE_NONE
,
3727 NULL
, 0, NULL
, HFILL
}},
3728 { &hf_snmp_objectname
, {
3729 "Object Name", "snmp.name", FT_OID
, BASE_NONE
,
3730 NULL
, 0, NULL
, HFILL
}},
3731 { &hf_snmp_scalar_instance_index
, {
3732 "Scalar Instance Index", "snmp.name.index", FT_UINT64
, BASE_DEC
,
3733 NULL
, 0, NULL
, HFILL
}},
3734 { &hf_snmp_var_bind_str
, {
3735 "Variable-binding-string", "snmp.var-bind_str", FT_STRING
, BASE_NONE
,
3736 NULL
, 0, NULL
, HFILL
}},
3737 { &hf_snmp_agentid_trailer
, {
3738 "AgentID Trailer", "snmp.agentid_trailer", FT_BYTES
, BASE_NONE
,
3739 NULL
, 0, NULL
, HFILL
}},
3742 { &hf_snmp_SMUX_PDUs_PDU
,
3743 { "SMUX-PDUs", "snmp.SMUX_PDUs",
3744 FT_UINT32
, BASE_DEC
, VALS(snmp_SMUX_PDUs_vals
), 0,
3747 { "version", "snmp.version",
3748 FT_INT32
, BASE_DEC
, VALS(snmp_Version_vals
), 0,
3750 { &hf_snmp_community
,
3751 { "community", "snmp.community",
3752 FT_STRING
, BASE_NONE
, NULL
, 0,
3755 { "data", "snmp.data",
3756 FT_UINT32
, BASE_DEC
, VALS(snmp_PDUs_vals
), 0,
3758 { &hf_snmp_parameters
,
3759 { "parameters", "snmp.parameters",
3760 FT_BYTES
, BASE_NONE
, NULL
, 0,
3761 "OCTET_STRING", HFILL
}},
3763 { "datav2u", "snmp.datav2u",
3764 FT_UINT32
, BASE_DEC
, VALS(snmp_T_datav2u_vals
), 0,
3766 { &hf_snmp_v2u_plaintext
,
3767 { "plaintext", "snmp.plaintext",
3768 FT_UINT32
, BASE_DEC
, VALS(snmp_PDUs_vals
), 0,
3770 { &hf_snmp_encrypted
,
3771 { "encrypted", "snmp.encrypted",
3772 FT_BYTES
, BASE_NONE
, NULL
, 0,
3773 "OCTET_STRING", HFILL
}},
3774 { &hf_snmp_msgAuthoritativeEngineID
,
3775 { "msgAuthoritativeEngineID", "snmp.msgAuthoritativeEngineID",
3776 FT_BYTES
, BASE_NONE
, NULL
, 0,
3778 { &hf_snmp_msgAuthoritativeEngineBoots
,
3779 { "msgAuthoritativeEngineBoots", "snmp.msgAuthoritativeEngineBoots",
3780 FT_UINT32
, BASE_DEC
, NULL
, 0,
3782 { &hf_snmp_msgAuthoritativeEngineTime
,
3783 { "msgAuthoritativeEngineTime", "snmp.msgAuthoritativeEngineTime",
3784 FT_UINT32
, BASE_DEC
, NULL
, 0,
3786 { &hf_snmp_msgUserName
,
3787 { "msgUserName", "snmp.msgUserName",
3788 FT_STRING
, BASE_NONE
, NULL
, 0,
3790 { &hf_snmp_msgAuthenticationParameters
,
3791 { "msgAuthenticationParameters", "snmp.msgAuthenticationParameters",
3792 FT_BYTES
, BASE_NONE
, NULL
, 0,
3794 { &hf_snmp_msgPrivacyParameters
,
3795 { "msgPrivacyParameters", "snmp.msgPrivacyParameters",
3796 FT_BYTES
, BASE_NONE
, NULL
, 0,
3798 { &hf_snmp_msgVersion
,
3799 { "msgVersion", "snmp.msgVersion",
3800 FT_INT32
, BASE_DEC
, VALS(snmp_Version_vals
), 0,
3801 "Version", HFILL
}},
3802 { &hf_snmp_msgGlobalData
,
3803 { "msgGlobalData", "snmp.msgGlobalData_element",
3804 FT_NONE
, BASE_NONE
, NULL
, 0,
3805 "HeaderData", HFILL
}},
3806 { &hf_snmp_msgSecurityParameters
,
3807 { "msgSecurityParameters", "snmp.msgSecurityParameters",
3808 FT_BYTES
, BASE_NONE
, NULL
, 0,
3811 { "msgData", "snmp.msgData",
3812 FT_UINT32
, BASE_DEC
, VALS(snmp_ScopedPduData_vals
), 0,
3813 "ScopedPduData", HFILL
}},
3815 { "msgID", "snmp.msgID",
3816 FT_UINT32
, BASE_DEC
, NULL
, 0,
3817 "INTEGER_0_2147483647", HFILL
}},
3818 { &hf_snmp_msgMaxSize
,
3819 { "msgMaxSize", "snmp.msgMaxSize",
3820 FT_UINT32
, BASE_DEC
, NULL
, 0,
3821 "INTEGER_484_2147483647", HFILL
}},
3822 { &hf_snmp_msgFlags
,
3823 { "msgFlags", "snmp.msgFlags",
3824 FT_BYTES
, BASE_NONE
, NULL
, 0,
3826 { &hf_snmp_msgSecurityModel
,
3827 { "msgSecurityModel", "snmp.msgSecurityModel",
3828 FT_UINT32
, BASE_DEC
, VALS(sec_models
), 0,
3830 { &hf_snmp_plaintext
,
3831 { "plaintext", "snmp.plaintext_element",
3832 FT_NONE
, BASE_NONE
, NULL
, 0,
3833 "ScopedPDU", HFILL
}},
3834 { &hf_snmp_encryptedPDU
,
3835 { "encryptedPDU", "snmp.encryptedPDU",
3836 FT_BYTES
, BASE_NONE
, NULL
, 0,
3838 { &hf_snmp_contextEngineID
,
3839 { "contextEngineID", "snmp.contextEngineID",
3840 FT_BYTES
, BASE_NONE
, NULL
, 0,
3841 "SnmpEngineID", HFILL
}},
3842 { &hf_snmp_contextName
,
3843 { "contextName", "snmp.contextName",
3844 FT_STRING
, BASE_NONE
, NULL
, 0,
3845 "OCTET_STRING", HFILL
}},
3846 { &hf_snmp_get_request
,
3847 { "get-request", "snmp.get_request_element",
3848 FT_NONE
, BASE_NONE
, NULL
, 0,
3849 "GetRequest_PDU", HFILL
}},
3850 { &hf_snmp_get_next_request
,
3851 { "get-next-request", "snmp.get_next_request_element",
3852 FT_NONE
, BASE_NONE
, NULL
, 0,
3853 "GetNextRequest_PDU", HFILL
}},
3854 { &hf_snmp_get_response
,
3855 { "get-response", "snmp.get_response_element",
3856 FT_NONE
, BASE_NONE
, NULL
, 0,
3857 "GetResponse_PDU", HFILL
}},
3858 { &hf_snmp_set_request
,
3859 { "set-request", "snmp.set_request_element",
3860 FT_NONE
, BASE_NONE
, NULL
, 0,
3861 "SetRequest_PDU", HFILL
}},
3863 { "trap", "snmp.trap_element",
3864 FT_NONE
, BASE_NONE
, NULL
, 0,
3865 "Trap_PDU", HFILL
}},
3866 { &hf_snmp_getBulkRequest
,
3867 { "getBulkRequest", "snmp.getBulkRequest_element",
3868 FT_NONE
, BASE_NONE
, NULL
, 0,
3869 "GetBulkRequest_PDU", HFILL
}},
3870 { &hf_snmp_informRequest
,
3871 { "informRequest", "snmp.informRequest_element",
3872 FT_NONE
, BASE_NONE
, NULL
, 0,
3873 "InformRequest_PDU", HFILL
}},
3874 { &hf_snmp_snmpV2_trap
,
3875 { "snmpV2-trap", "snmp.snmpV2_trap_element",
3876 FT_NONE
, BASE_NONE
, NULL
, 0,
3877 "SNMPv2_Trap_PDU", HFILL
}},
3879 { "report", "snmp.report_element",
3880 FT_NONE
, BASE_NONE
, NULL
, 0,
3881 "Report_PDU", HFILL
}},
3882 { &hf_snmp_request_id
,
3883 { "request-id", "snmp.request_id",
3884 FT_INT32
, BASE_DEC
, NULL
, 0,
3885 "T_request_id", HFILL
}},
3886 { &hf_snmp_error_status
,
3887 { "error-status", "snmp.error_status",
3888 FT_INT32
, BASE_DEC
, VALS(snmp_T_error_status_vals
), 0,
3890 { &hf_snmp_error_index
,
3891 { "error-index", "snmp.error_index",
3892 FT_INT32
, BASE_DEC
, NULL
, 0,
3893 "INTEGER", HFILL
}},
3894 { &hf_snmp_variable_bindings
,
3895 { "variable-bindings", "snmp.variable_bindings",
3896 FT_UINT32
, BASE_DEC
, NULL
, 0,
3897 "VarBindList", HFILL
}},
3898 { &hf_snmp_bulkPDU_request_id
,
3899 { "request-id", "snmp.request_id",
3900 FT_INT32
, BASE_DEC
, NULL
, 0,
3901 "Integer32", HFILL
}},
3902 { &hf_snmp_non_repeaters
,
3903 { "non-repeaters", "snmp.non_repeaters",
3904 FT_UINT32
, BASE_DEC
, NULL
, 0,
3905 "INTEGER_0_2147483647", HFILL
}},
3906 { &hf_snmp_max_repetitions
,
3907 { "max-repetitions", "snmp.max_repetitions",
3908 FT_UINT32
, BASE_DEC
, NULL
, 0,
3909 "INTEGER_0_2147483647", HFILL
}},
3910 { &hf_snmp_enterprise
,
3911 { "enterprise", "snmp.enterprise",
3912 FT_OID
, BASE_NONE
, NULL
, 0,
3913 "EnterpriseOID", HFILL
}},
3914 { &hf_snmp_agent_addr
,
3915 { "agent-addr", "snmp.agent_addr",
3916 FT_IPv4
, BASE_NONE
, NULL
, 0,
3917 "NetworkAddress", HFILL
}},
3918 { &hf_snmp_generic_trap
,
3919 { "generic-trap", "snmp.generic_trap",
3920 FT_INT32
, BASE_DEC
, VALS(snmp_GenericTrap_vals
), 0,
3921 "GenericTrap", HFILL
}},
3922 { &hf_snmp_specific_trap
,
3923 { "specific-trap", "snmp.specific_trap",
3924 FT_INT32
, BASE_DEC
, NULL
, 0,
3925 "SpecificTrap", HFILL
}},
3926 { &hf_snmp_time_stamp
,
3927 { "time-stamp", "snmp.time_stamp",
3928 FT_UINT32
, BASE_DEC
, NULL
, 0,
3929 "TimeTicks", HFILL
}},
3931 { "name", "snmp.name",
3932 FT_OID
, BASE_NONE
, NULL
, 0,
3933 "ObjectName", HFILL
}},
3934 { &hf_snmp_valueType
,
3935 { "valueType", "snmp.valueType_element",
3936 FT_NONE
, BASE_NONE
, NULL
, 0,
3938 { &hf_snmp_VarBindList_item
,
3939 { "VarBind", "snmp.VarBind_element",
3940 FT_NONE
, BASE_NONE
, NULL
, 0,
3943 { "open", "snmp.open",
3944 FT_UINT32
, BASE_DEC
, VALS(snmp_OpenPDU_vals
), 0,
3945 "OpenPDU", HFILL
}},
3947 { "close", "snmp.close",
3948 FT_INT32
, BASE_DEC
, VALS(snmp_ClosePDU_U_vals
), 0,
3949 "ClosePDU", HFILL
}},
3950 { &hf_snmp_registerRequest
,
3951 { "registerRequest", "snmp.registerRequest_element",
3952 FT_NONE
, BASE_NONE
, NULL
, 0,
3953 "RReqPDU", HFILL
}},
3954 { &hf_snmp_registerResponse
,
3955 { "registerResponse", "snmp.registerResponse",
3956 FT_UINT32
, BASE_DEC
, VALS(snmp_RegisterResponse_vals
), 0,
3958 { &hf_snmp_commitOrRollback
,
3959 { "commitOrRollback", "snmp.commitOrRollback",
3960 FT_INT32
, BASE_DEC
, VALS(snmp_SOutPDU_U_vals
), 0,
3961 "SOutPDU", HFILL
}},
3963 { "rRspPDU", "snmp.rRspPDU",
3964 FT_INT32
, BASE_DEC
, VALS(snmp_RRspPDU_U_vals
), 0,
3967 { "pDUs", "snmp.pDUs",
3968 FT_UINT32
, BASE_DEC
, VALS(snmp_PDUs_vals
), 0,
3970 { &hf_snmp_smux_simple
,
3971 { "smux-simple", "snmp.smux_simple_element",
3972 FT_NONE
, BASE_NONE
, NULL
, 0,
3973 "SimpleOpen", HFILL
}},
3974 { &hf_snmp_smux_version
,
3975 { "smux-version", "snmp.smux_version",
3976 FT_INT32
, BASE_DEC
, VALS(snmp_T_smux_version_vals
), 0,
3978 { &hf_snmp_identity
,
3979 { "identity", "snmp.identity",
3980 FT_OID
, BASE_NONE
, NULL
, 0,
3981 "OBJECT_IDENTIFIER", HFILL
}},
3982 { &hf_snmp_description
,
3983 { "description", "snmp.description",
3984 FT_BYTES
, BASE_NONE
, NULL
, 0,
3985 "DisplayString", HFILL
}},
3986 { &hf_snmp_password
,
3987 { "password", "snmp.password",
3988 FT_BYTES
, BASE_NONE
, NULL
, 0,
3989 "OCTET_STRING", HFILL
}},
3991 { "subtree", "snmp.subtree",
3992 FT_OID
, BASE_NONE
, NULL
, 0,
3993 "ObjectName", HFILL
}},
3994 { &hf_snmp_priority
,
3995 { "priority", "snmp.priority",
3996 FT_INT32
, BASE_DEC
, NULL
, 0,
3997 "INTEGER_M1_2147483647", HFILL
}},
3998 { &hf_snmp_operation
,
3999 { "operation", "snmp.operation",
4000 FT_INT32
, BASE_DEC
, VALS(snmp_T_operation_vals
), 0,
4004 /* List of subtrees */
4005 static int *ett
[] = {
4011 &ett_authParameters
,
4016 &ett_decoding_error
,
4018 &ett_snmp_Messagev2u
,
4019 &ett_snmp_T_datav2u
,
4020 &ett_snmp_UsmSecurityParameters
,
4021 &ett_snmp_SNMPv3Message
,
4022 &ett_snmp_HeaderData
,
4023 &ett_snmp_ScopedPduData
,
4024 &ett_snmp_ScopedPDU
,
4028 &ett_snmp_Trap_PDU_U
,
4030 &ett_snmp_VarBindList
,
4031 &ett_snmp_SMUX_PDUs
,
4032 &ett_snmp_RegisterResponse
,
4034 &ett_snmp_SimpleOpen_U
,
4035 &ett_snmp_RReqPDU_U
,
4037 static ei_register_info ei
[] = {
4038 { &ei_snmp_failed_decrypted_data_pdu
, { "snmp.failed_decrypted_data_pdu", PI_MALFORMED
, PI_WARN
, "Failed to decrypt encryptedPDU", EXPFILL
}},
4039 { &ei_snmp_decrypted_data_bad_formatted
, { "snmp.decrypted_data_bad_formatted", PI_MALFORMED
, PI_WARN
, "Decrypted data not formatted as expected, wrong key?", EXPFILL
}},
4040 { &ei_snmp_verify_authentication_error
, { "snmp.verify_authentication_error", PI_MALFORMED
, PI_ERROR
, "Error while verifying Message authenticity", EXPFILL
}},
4041 { &ei_snmp_authentication_ok
, { "snmp.authentication_ok", PI_CHECKSUM
, PI_CHAT
, "SNMP Authentication OK", EXPFILL
}},
4042 { &ei_snmp_authentication_error
, { "snmp.authentication_error", PI_CHECKSUM
, PI_WARN
, "SNMP Authentication Error", EXPFILL
}},
4043 { &ei_snmp_varbind_not_uni_class_seq
, { "snmp.varbind.not_uni_class_seq", PI_MALFORMED
, PI_WARN
, "VarBind is not an universal class sequence", EXPFILL
}},
4044 { &ei_snmp_varbind_has_indicator
, { "snmp.varbind.has_indicator", PI_MALFORMED
, PI_WARN
, "VarBind has indicator set", EXPFILL
}},
4045 { &ei_snmp_objectname_not_oid
, { "snmp.objectname_not_oid", PI_MALFORMED
, PI_WARN
, "ObjectName not an OID", EXPFILL
}},
4046 { &ei_snmp_objectname_has_indicator
, { "snmp.objectname_has_indicator", PI_MALFORMED
, PI_WARN
, "ObjectName has indicator set", EXPFILL
}},
4047 { &ei_snmp_value_not_primitive_encoding
, { "snmp.value_not_primitive_encoding", PI_MALFORMED
, PI_WARN
, "value not in primitive encoding", EXPFILL
}},
4048 { &ei_snmp_invalid_oid
, { "snmp.invalid_oid", PI_MALFORMED
, PI_WARN
, "invalid oid", EXPFILL
}},
4049 { &ei_snmp_varbind_wrong_tag
, { "snmp.varbind.wrong_tag", PI_MALFORMED
, PI_WARN
, "Wrong tag for SNMP VarBind error value", EXPFILL
}},
4050 { &ei_snmp_varbind_response
, { "snmp.varbind.response", PI_RESPONSE_CODE
, PI_NOTE
, "Response", EXPFILL
}},
4051 { &ei_snmp_no_instance_subid
, { "snmp.no_instance_subid", PI_MALFORMED
, PI_WARN
, "No instance sub-id in scalar value", EXPFILL
}},
4052 { &ei_snmp_wrong_num_of_subids
, { "snmp.wrong_num_of_subids", PI_MALFORMED
, PI_WARN
, "Wrong number of instance sub-ids in scalar value", EXPFILL
}},
4053 { &ei_snmp_index_suboid_too_short
, { "snmp.index_suboid_too_short", PI_MALFORMED
, PI_WARN
, "index sub-oid shorter than expected", EXPFILL
}},
4054 { &ei_snmp_unimplemented_instance_index
, { "snmp.unimplemented_instance_index", PI_UNDECODED
, PI_WARN
, "OID instances not handled, if you want this implemented please contact the wireshark developers", EXPFILL
}},
4055 { &ei_snmp_index_suboid_len0
, { "snmp.ndex_suboid_len0", PI_MALFORMED
, PI_WARN
, "an index sub-oid OID cannot be 0 bytes long!", EXPFILL
}},
4056 { &ei_snmp_index_suboid_too_long
, { "snmp.index_suboid_too_long", PI_MALFORMED
, PI_WARN
, "index sub-oid should not be longer than remaining oid size", EXPFILL
}},
4057 { &ei_snmp_index_string_too_long
, { "snmp.index_string_too_long", PI_MALFORMED
, PI_WARN
, "index string should not be longer than remaining oid size", EXPFILL
}},
4058 { &ei_snmp_column_parent_not_row
, { "snmp.column_parent_not_row", PI_MALFORMED
, PI_ERROR
, "COLUMNS's parent is not a ROW", EXPFILL
}},
4059 { &ei_snmp_uint_too_large
, { "snmp.uint_too_large", PI_UNDECODED
, PI_NOTE
, "Unsigned integer value > 2^64 - 1", EXPFILL
}},
4060 { &ei_snmp_int_too_large
, { "snmp.int_too_large", PI_UNDECODED
, PI_NOTE
, "Signed integer value > 2^63 - 1 or <= -2^63", EXPFILL
}},
4061 { &ei_snmp_integral_value0
, { "snmp.integral_value0", PI_UNDECODED
, PI_NOTE
, "Integral value is zero-length", EXPFILL
}},
4062 { &ei_snmp_missing_mib
, { "snmp.missing_mib", PI_UNDECODED
, PI_NOTE
, "Unresolved value, Missing MIB", EXPFILL
}},
4063 { &ei_snmp_varbind_wrong_length_value
, { "snmp.varbind.wrong_length_value", PI_MALFORMED
, PI_WARN
, "Wrong length for SNMP VarBind/value", EXPFILL
}},
4064 { &ei_snmp_varbind_wrong_class_tag
, { "snmp.varbind.wrong_class_tag", PI_MALFORMED
, PI_WARN
, "Wrong class/tag for SNMP VarBind/value", EXPFILL
}},
4065 { &ei_snmp_rfc1910_non_conformant
, { "snmp.rfc1910_non_conformant", PI_PROTOCOL
, PI_WARN
, "Data not conforming to RFC1910", EXPFILL
}},
4066 { &ei_snmp_rfc3411_non_conformant
, { "snmp.rfc3411_non_conformant", PI_PROTOCOL
, PI_WARN
, "Data not conforming to RFC3411", EXPFILL
}},
4067 { &ei_snmp_version_unknown
, { "snmp.version.unknown", PI_PROTOCOL
, PI_WARN
, "Unknown version", EXPFILL
}},
4068 { &ei_snmp_trap_pdu_obsolete
, { "snmp.trap_pdu_obsolete", PI_PROTOCOL
, PI_WARN
, "Trap-PDU is obsolete in this SNMP version", EXPFILL
}},
4072 expert_module_t
* expert_snmp
;
4073 module_t
*snmp_module
;
4075 static uat_field_t users_fields
[] = {
4076 UAT_FLD_BUFFER(snmp_users
,engine_id
,"Engine ID","Engine-id for this entry (empty = any)"),
4077 UAT_FLD_LSTRING(snmp_users
,userName
,"Username","The username"),
4078 UAT_FLD_VS(snmp_users
,auth_model
,"Authentication model",auth_types
,"Algorithm to be used for authentication."),
4079 UAT_FLD_LSTRING(snmp_users
,authPassword
,"Password","The password used for authenticating packets for this entry"),
4080 UAT_FLD_VS(snmp_users
,priv_proto
,"Privacy protocol",priv_types
,"Algorithm to be used for privacy."),
4081 UAT_FLD_LSTRING(snmp_users
,privPassword
,"Privacy password","The password used for encrypting packets for this entry"),
4082 UAT_FLD_VS(snmp_users
,priv_key_exp
,"Key expansion method",priv_key_exp_types
,"Privacy protocol key expansion method"),
4086 uat_t
*assocs_uat
= uat_new("SNMP Users",
4087 sizeof(snmp_ue_assoc_t
),
4092 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
4093 "ChSNMPUsersSection",
4095 snmp_users_update_cb
,
4101 static const char *assocs_uat_defaults
[] = {
4102 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, "draft-reeder-snmpv3-usm-3desede-00"};
4103 uat_set_default_values(assocs_uat
, assocs_uat_defaults
);
4105 static uat_field_t specific_traps_flds
[] = {
4106 UAT_FLD_CSTRING(specific_traps
,enterprise
,"Enterprise OID","Enterprise Object Identifier"),
4107 UAT_FLD_DEC(specific_traps
,trap
,"Trap Id","The specific-trap value"),
4108 UAT_FLD_CSTRING(specific_traps
,desc
,"Description","Trap type description"),
4112 uat_t
* specific_traps_uat
= uat_new("SNMP Enterprise Specific Trap Types",
4113 sizeof(snmp_st_assoc_t
),
4114 "snmp_specific_traps",
4117 &num_specific_traps
,
4118 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
4119 "ChSNMPEnterpriseSpecificTrapTypes",
4120 snmp_specific_trap_copy_cb
,
4122 snmp_specific_trap_free_cb
,
4125 specific_traps_flds
);
4127 /* Register protocol */
4128 proto_snmp
= proto_register_protocol(PNAME
, PSNAME
, PFNAME
);
4129 snmp_handle
= register_dissector("snmp", dissect_snmp
, proto_snmp
);
4131 /* Register fields and subtrees */
4132 proto_register_field_array(proto_snmp
, hf
, array_length(hf
));
4133 proto_register_subtree_array(ett
, array_length(ett
));
4134 expert_snmp
= expert_register_protocol(proto_snmp
);
4135 expert_register_field_array(expert_snmp
, ei
, array_length(ei
));
4137 /* Register dissector */
4138 snmp_tcp_handle
= register_dissector("snmp.tcp", dissect_snmp_tcp
, proto_snmp
);
4140 /* Register configuration preferences */
4141 snmp_module
= prefs_register_protocol(proto_snmp
, process_prefs
);
4142 prefs_register_bool_preference(snmp_module
, "display_oid",
4143 "Show SNMP OID in info column",
4144 "Whether the SNMP OID should be shown in the info column",
4147 prefs_register_obsolete_preference(snmp_module
, "mib_modules");
4148 prefs_register_obsolete_preference(snmp_module
, "users_file");
4150 prefs_register_bool_preference(snmp_module
, "desegment",
4151 "Reassemble SNMP-over-TCP messages spanning multiple TCP segments",
4152 "Whether the SNMP dissector should reassemble messages spanning multiple TCP segments."
4153 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4156 prefs_register_bool_preference(snmp_module
, "var_in_tree",
4157 "Display dissected variables inside SNMP tree",
4158 "ON - display dissected variables inside SNMP tree, OFF - display dissected variables in root tree after SNMP",
4161 prefs_register_uat_preference(snmp_module
, "users_table",
4163 "Table of engine-user associations used for authentication and decryption",
4166 prefs_register_uat_preference(snmp_module
, "specific_traps_table",
4167 "Enterprise Specific Trap Types",
4168 "Table of enterprise specific-trap type descriptions",
4169 specific_traps_uat
);
4172 prefs_register_static_text_preference(snmp_module
, "info_mibs",
4173 "MIB settings can be changed in the Name Resolution preferences",
4174 "MIB settings can be changed in the Name Resolution preferences");
4177 value_sub_dissectors_table
= register_dissector_table("snmp.variable_oid","SNMP Variable OID", proto_snmp
, FT_STRING
, STRING_CASE_SENSITIVE
);
4179 register_init_routine(init_ue_cache
);
4180 register_cleanup_routine(cleanup_ue_cache
);
4182 register_ber_syntax_dissector("SNMP", proto_snmp
, dissect_snmp_tcp
);
4184 snmp_tap
=register_tap("snmp");
4186 register_srt_table(proto_snmp
, NULL
, 1, snmpstat_packet
, snmpstat_init
, NULL
);
4190 /*--- proto_reg_handoff_snmp ---------------------------------------*/
4191 void proto_reg_handoff_snmp(void) {
4193 dissector_add_uint_with_preference("udp.port", UDP_PORT_SNMP
, snmp_handle
);
4194 dissector_add_uint("ethertype", ETHERTYPE_SNMP
, snmp_handle
);
4195 dissector_add_uint("ipx.socket", IPX_SOCKET_SNMP_AGENT
, snmp_handle
);
4196 dissector_add_uint("ipx.socket", IPX_SOCKET_SNMP_SINK
, snmp_handle
);
4197 dissector_add_uint("hpext.dxsap", HPEXT_SNMP
, snmp_handle
);
4199 dissector_add_uint_with_preference("tcp.port", TCP_PORT_SNMP
, snmp_tcp_handle
);
4200 /* Since "regular" SNMP port and "trap" SNMP port use the same handler,
4201 the "trap" port doesn't really need a separate preference. Just register
4203 dissector_add_uint("tcp.port", TCP_PORT_SNMP_TRAP
, snmp_tcp_handle
);
4204 dissector_add_uint("udp.port", UDP_PORT_SNMP_TRAP
, snmp_handle
);
4205 dissector_add_uint("udp.port", UDP_PORT_SNMP_PATROL
, snmp_handle
);
4207 data_handle
= find_dissector("data");
4209 /* SNMPv2-MIB sysDescr "1.3.6.1.2.1.1.1.0" */
4210 dissector_add_string("snmp.variable_oid", "1.3.6.1.2.1.1.1.0",
4211 create_dissector_handle(dissect_snmp_variable_string
, proto_snmp
));
4212 /* SNMPv2-MIB::sysName.0 (1.3.6.1.2.1.1.5.0) */
4213 dissector_add_string("snmp.variable_oid", "1.3.6.1.2.1.1.5.0",
4214 create_dissector_handle(dissect_snmp_variable_string
, proto_snmp
));
4217 * Process preference settings.
4219 * We can't do this in the register routine, as preferences aren't
4220 * read until all dissector register routines have been called (so
4221 * that all dissector preferences have been registered).
4228 proto_register_smux(void)
4230 static int *ett
[] = {
4234 proto_smux
= proto_register_protocol("SNMP Multiplex Protocol",
4237 proto_register_subtree_array(ett
, array_length(ett
));
4239 smux_handle
= register_dissector("smux", dissect_smux
, proto_smux
);
4243 proto_reg_handoff_smux(void)
4245 dissector_add_uint_with_preference("tcp.port", TCP_PORT_SMUX
, smux_handle
);
4249 * Editor modelines - https://www.wireshark.org/tools/modelines.html
4254 * indent-tabs-mode: t
4257 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4258 * :indentSize=8:tabSize=8:noTabs=false: