2 * Routines for SNMP (simple network management protocol)
3 * Copyright (C) 1998 Didier Jorand
5 * See RFC 1157 for SNMPv1.
7 * See RFCs 1901, 1905, and 1906 for SNMPv2c.
9 * See RFCs 1905, 1906, 1909, and 1910 for SNMPv2u [historic].
11 * See RFCs 2570-2576 for SNMPv3
13 * $Id: packet-snmp.c,v 1.111 2003/08/04 07:38:15 guy Exp $
15 * Ethereal - Network traffic analyzer
16 * By Gerald Combs <gerald@ethereal.com>
17 * Copyright 1998 Gerald Combs
21 * GXSNMP -- An snmp mangament application
22 * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
23 * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version 2
28 * of the License, or (at your option) any later version.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
50 #include <epan/packet.h>
51 #include <epan/strutil.h>
52 #include <epan/conversation.h>
55 #include "packet-ipx.h"
56 #include "packet-hpext.h"
61 # include <net-snmp/net-snmp-config.h>
62 # include <net-snmp/mib_api.h>
63 # include <net-snmp/library/default_store.h>
64 # include <net-snmp/config_api.h>
65 #else /* HAVE_NET_SNMP */
66 # include <ucd-snmp/ucd-snmp-config.h>
67 # include <ucd-snmp/asn1.h>
68 # include <ucd-snmp/snmp_api.h>
69 # include <ucd-snmp/snmp_impl.h>
70 # include <ucd-snmp/mib.h>
71 # include <ucd-snmp/default_store.h>
72 # include <ucd-snmp/read_config.h>
73 # include <ucd-snmp/tools.h>
74 #endif /* HAVE_NET_SNMP */
76 #ifndef NETSNMP_DS_LIBRARY_ID
77 # define NETSNMP_DS_LIBRARY_ID DS_LIBRARY_ID
78 # define NETSNMP_DS_LIB_NO_TOKEN_WARNINGS DS_LIB_NO_TOKEN_WARNINGS
79 # define NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY DS_LIB_PRINT_SUFFIX_ONLY
80 # define netsnmp_ds_set_boolean ds_set_boolean
81 # define netsnmp_ds_set_int ds_set_int
85 # include <epan/filesystem.h>
89 * Define values "sprint_realloc_value()" expects.
91 # define VALTYPE_INTEGER ASN_INTEGER
92 # define VALTYPE_COUNTER ASN_COUNTER
93 # define VALTYPE_GAUGE ASN_GAUGE
94 # define VALTYPE_TIMETICKS ASN_TIMETICKS
95 # define VALTYPE_STRING ASN_OCTET_STR
96 # define VALTYPE_IPADDR ASN_IPADDRESS
97 # define VALTYPE_OPAQUE ASN_OPAQUE
98 # define VALTYPE_NSAP ASN_NSAP
99 # define VALTYPE_OBJECTID ASN_OBJECT_ID
100 # define VALTYPE_BITSTR ASN_BIT_STR
101 # define VALTYPE_COUNTER64 ASN_COUNTER64
103 #endif /* HAVE_SOME_SNMP */
107 #include "packet-snmp.h"
108 #include "format-oid.h"
110 /* Take a pointer that may be null and return a pointer that's not null
111 by turning null pointers into pointers to the above null string,
112 and, if the argument pointer wasn't null, make sure we handle
113 non-printable characters in the string by escaping them. */
114 #define SAFE_STRING(s, l) (((s) != NULL) ? format_text((s), (l)) : "")
116 static int proto_snmp = -1;
118 static gboolean display_oid = TRUE;
120 static gint ett_snmp = -1;
121 static gint ett_parameters = -1;
122 static gint ett_parameters_qos = -1;
123 static gint ett_global = -1;
124 static gint ett_flags = -1;
125 static gint ett_secur = -1;
127 static int hf_snmp_version = -1;
128 static int hf_snmp_community = -1;
129 static int hf_snmp_request_id = -1;
130 static int hf_snmp_pdutype = -1;
131 static int hf_snmp_agent = -1;
132 static int hf_snmp_enterprise = -1;
133 static int hf_snmp_error_status = -1;
134 static int hf_snmp_oid = -1;
135 static int hf_snmp_traptype = -1;
136 static int hf_snmp_spectraptype = -1;
137 static int hf_snmp_timestamp = -1;
138 static int hf_snmpv3_flags = -1;
139 static int hf_snmpv3_flags_auth = -1;
140 static int hf_snmpv3_flags_crypt = -1;
141 static int hf_snmpv3_flags_report = -1;
143 static int proto_smux = -1;
145 static gint ett_smux = -1;
147 static int hf_smux_version = -1;
148 static int hf_smux_pdutype = -1;
150 static dissector_handle_t snmp_handle;
151 static dissector_handle_t data_handle;
154 #define TH_CRYPT 0x02
155 #define TH_REPORT 0x04
157 #define UDP_PORT_SNMP 161
158 #define UDP_PORT_SNMP_TRAP 162
159 #define TCP_PORT_SMUX 199
161 /* Protocol version numbers */
162 #define SNMP_VERSION_1 0
163 #define SNMP_VERSION_2c 1
164 #define SNMP_VERSION_2u 2
165 #define SNMP_VERSION_3 3
167 static const value_string versions[] = {
168 { SNMP_VERSION_1, "1" },
169 { SNMP_VERSION_2c, "2C" },
170 { SNMP_VERSION_2u, "2U" },
171 { SNMP_VERSION_3, "3" },
176 #define SNMP_MSG_GET 0
177 #define SNMP_MSG_GETNEXT 1
178 #define SNMP_MSG_RESPONSE 2
179 #define SNMP_MSG_SET 3
180 #define SNMP_MSG_TRAP 4
182 #define SNMP_MSG_GETBULK 5
183 #define SNMP_MSG_INFORM 6
184 #define SNMP_MSG_TRAP2 7
185 #define SNMP_MSG_REPORT 8
187 static const value_string pdu_types[] = {
188 { SNMP_MSG_GET, "GET" },
189 { SNMP_MSG_GETNEXT, "GET-NEXT" },
190 { SNMP_MSG_SET, "SET" },
191 { SNMP_MSG_RESPONSE, "RESPONSE" },
192 { SNMP_MSG_TRAP, "TRAP-V1" },
193 { SNMP_MSG_GETBULK, "GETBULK" },
194 { SNMP_MSG_INFORM, "INFORM" },
195 { SNMP_MSG_TRAP2, "TRAP-V2" },
196 { SNMP_MSG_REPORT, "REPORT" },
201 #define SMUX_MSG_OPEN 0
202 #define SMUX_MSG_CLOSE 1
203 #define SMUX_MSG_RREQ 2
204 #define SMUX_MSG_RRSP 3
205 #define SMUX_MSG_SOUT 4
207 static const value_string smux_types[] = {
208 { SMUX_MSG_OPEN, "Open" },
209 { SMUX_MSG_CLOSE, "Close" },
210 { SMUX_MSG_RREQ, "Registration Request" },
211 { SMUX_MSG_RRSP, "Registration Response" },
212 { SMUX_MSG_SOUT, "Commit Or Rollback" },
216 /* SMUX Closing causes */
217 #define SMUX_CLOSE_DOWN 0
218 #define SMUX_CLOSE_VERSION 1
219 #define SMUX_CLOSE_PACKET 2
220 #define SMUX_CLOSE_PROTOCOL 3
221 #define SMUX_CLOSE_INTERNAL 4
222 #define SMUX_CLOSE_NOAUTH 5
224 static const value_string smux_close[] = {
225 { SMUX_CLOSE_DOWN, "Going down" },
226 { SMUX_CLOSE_VERSION, "Unsupported Version" },
227 { SMUX_CLOSE_PACKET, "Packet Format Error" },
228 { SMUX_CLOSE_PROTOCOL, "Protocol Error" },
229 { SMUX_CLOSE_INTERNAL, "Internal Error" },
230 { SMUX_CLOSE_NOAUTH, "Unauthorized" },
234 /* SMUX Request codes */
235 #define SMUX_RREQ_DELETE 0
236 #define SMUX_RREQ_READONLY 1
237 #define SMUX_RREQ_READWRITE 2
239 static const value_string smux_rreq[] = {
240 { SMUX_RREQ_DELETE, "Delete" },
241 { SMUX_RREQ_READONLY, "Read Only" },
242 { SMUX_RREQ_READWRITE, "Read Write" },
246 static const value_string smux_prio[] = {
251 /* SMUX SOut codes */
252 #define SMUX_SOUT_COMMIT 0
253 #define SMUX_SOUT_ROLLBACK 1
255 static const value_string smux_sout[] = {
256 { SMUX_SOUT_COMMIT, "Commit" },
257 { SMUX_SOUT_ROLLBACK, "Rollback" },
261 /* Error status values */
262 #ifndef SNMP_ERR_NOERROR
263 #define SNMP_ERR_NOERROR 0
265 #ifndef SNMP_ERR_TOOBIG
266 #define SNMP_ERR_TOOBIG 1
268 #ifndef SNMP_ERR_NOSUCHNAME
269 #define SNMP_ERR_NOSUCHNAME 2
271 #ifndef SNMP_ERR_BADVALUE
272 #define SNMP_ERR_BADVALUE 3
274 #ifndef SNMP_ERR_READONLY
275 #define SNMP_ERR_READONLY 4
277 #ifndef SNMP_ERR_GENERR
278 #define SNMP_ERR_GENERR 5
280 #ifndef SNMP_ERR_NOACCESS
281 #define SNMP_ERR_NOACCESS 6
283 #ifndef SNMP_ERR_WRONGTYPE
284 #define SNMP_ERR_WRONGTYPE 7
286 #ifndef SNMP_ERR_WRONGLENGTH
287 #define SNMP_ERR_WRONGLENGTH 8
289 #ifndef SNMP_ERR_WRONGENCODING
290 #define SNMP_ERR_WRONGENCODING 9
292 #ifndef SNMP_ERR_WRONGVALUE
293 #define SNMP_ERR_WRONGVALUE 10
295 #ifndef SNMP_ERR_NOCREATION
296 #define SNMP_ERR_NOCREATION 11
298 #ifndef SNMP_ERR_INCONSISTENTVALUE
299 #define SNMP_ERR_INCONSISTENTVALUE 12
301 #ifndef SNMP_ERR_RESOURCEUNAVAILABLE
302 #define SNMP_ERR_RESOURCEUNAVAILABLE 13
304 #ifndef SNMP_ERR_COMMITFAILED
305 #define SNMP_ERR_COMMITFAILED 14
307 #ifndef SNMP_ERR_UNDOFAILED
308 #define SNMP_ERR_UNDOFAILED 15
310 #ifndef SNMP_ERR_AUTHORIZATIONERROR
311 #define SNMP_ERR_AUTHORIZATIONERROR 16
313 #ifndef SNMP_ERR_NOTWRITABLE
314 #define SNMP_ERR_NOTWRITABLE 17
316 #ifndef SNMP_ERR_INCONSISTENTNAME
317 #define SNMP_ERR_INCONSISTENTNAME 18
320 static const value_string error_statuses[] = {
321 { SNMP_ERR_NOERROR, "NO ERROR" },
322 { SNMP_ERR_TOOBIG, "TOOBIG" },
323 { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" },
324 { SNMP_ERR_BADVALUE, "BAD VALUE" },
325 { SNMP_ERR_READONLY, "READ ONLY" },
326 { SNMP_ERR_GENERR, "GENERIC ERROR" },
327 { SNMP_ERR_NOACCESS, "NO ACCESS" },
328 { SNMP_ERR_WRONGTYPE, "WRONG TYPE" },
329 { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" },
330 { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" },
331 { SNMP_ERR_WRONGVALUE, "WRONG VALUE" },
332 { SNMP_ERR_NOCREATION, "NO CREATION" },
333 { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" },
334 { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" },
335 { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" },
336 { SNMP_ERR_UNDOFAILED, "UNDO FAILED" },
337 { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" },
338 { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" },
339 { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" },
343 /* General SNMP V1 Traps */
345 #ifndef SNMP_TRAP_COLDSTART
346 #define SNMP_TRAP_COLDSTART 0
348 #ifndef SNMP_TRAP_WARMSTART
349 #define SNMP_TRAP_WARMSTART 1
351 #ifndef SNMP_TRAP_LINKDOWN
352 #define SNMP_TRAP_LINKDOWN 2
354 #ifndef SNMP_TRAP_LINKUP
355 #define SNMP_TRAP_LINKUP 3
357 #ifndef SNMP_TRAP_AUTHFAIL
358 #define SNMP_TRAP_AUTHFAIL 4
360 #ifndef SNMP_TRAP_EGPNEIGHBORLOSS
361 #define SNMP_TRAP_EGPNEIGHBORLOSS 5
363 #ifndef SNMP_TRAP_ENTERPRISESPECIFIC
364 #define SNMP_TRAP_ENTERPRISESPECIFIC 6
367 static const value_string trap_types[] = {
368 { SNMP_TRAP_COLDSTART, "COLD START" },
369 { SNMP_TRAP_WARMSTART, "WARM START" },
370 { SNMP_TRAP_LINKDOWN, "LINK DOWN" },
371 { SNMP_TRAP_LINKUP, "LINK UP" },
372 { SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
373 { SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
374 { SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
378 /* Security Models */
380 #define SNMP_SEC_ANY 0
381 #define SNMP_SEC_V1 1
382 #define SNMP_SEC_V2C 2
383 #define SNMP_SEC_USM 3
385 static const value_string sec_models[] = {
386 { SNMP_SEC_ANY, "Any" },
387 { SNMP_SEC_V1, "V1" },
388 { SNMP_SEC_V2C, "V2C" },
389 { SNMP_SEC_USM, "USM" },
395 #define SNMP_IPA 0 /* IP Address */
396 #define SNMP_CNT 1 /* Counter (Counter32) */
397 #define SNMP_GGE 2 /* Gauge (Gauge32) */
398 #define SNMP_TIT 3 /* TimeTicks */
399 #define SNMP_OPQ 4 /* Opaque */
400 #define SNMP_NSP 5 /* NsapAddress */
401 #define SNMP_C64 6 /* Counter64 */
402 #define SNMP_U32 7 /* Uinteger32 */
411 #define SNMP_INTEGER 1 /* l */
412 #define SNMP_OCTETSTR 2 /* c */
413 #define SNMP_DISPLAYSTR 2 /* c */
414 #define SNMP_OBJECTID 3 /* ul */
415 #define SNMP_IPADDR 4 /* uc */
416 #define SNMP_COUNTER 5 /* ul */
417 #define SNMP_GAUGE 6 /* ul */
418 #define SNMP_TIMETICKS 7 /* ul */
419 #define SNMP_OPAQUE 8 /* c */
421 /* additional SNMPv2 Types */
423 #define SNMP_UINTEGER 5 /* ul */
424 #define SNMP_BITSTR 9 /* uc */
425 #define SNMP_NSAP 10 /* uc */
426 #define SNMP_COUNTER64 11 /* ul */
427 #define SNMP_NOSUCHOBJECT 12
428 #define SNMP_NOSUCHINSTANCE 13
429 #define SNMP_ENDOFMIBVIEW 14
431 typedef struct _SNMP_CNV SNMP_CNV;
441 static SNMP_CNV SnmpCnv [] =
443 {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"},
444 {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"},
445 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"},
446 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"},
447 {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"},
448 {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */
449 {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */
450 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"},
451 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"},
453 /* SNMPv2 data types and errors */
455 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"},
456 {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"},
457 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"},
458 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"},
459 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"},
464 * NAME: g_snmp_tag_cls2syntax
465 * SYNOPSIS: gboolean g_snmp_tag_cls2syntax
471 * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name.
472 * See SnmpCnv for conversion.
473 * RETURNS: name on success, NULL on failure
477 snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
482 while (cnv->syntax != -1)
484 if (cnv->tag == tag && cnv->class == cls)
486 *syntax = cnv->syntax;
495 dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
496 proto_tree *tree, const char *field_name, int ret)
500 errstr = asn1_err_to_str(ret);
502 if (check_col(pinfo->cinfo, COL_INFO)) {
503 col_add_fstr(pinfo->cinfo, COL_INFO,
504 "ERROR: Couldn't parse %s: %s", field_name, errstr);
507 proto_tree_add_text(tree, tvb, offset, 0,
508 "ERROR: Couldn't parse %s: %s", field_name, errstr);
509 call_dissector(data_handle,
510 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
515 dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
516 proto_tree *tree, const char *message)
518 if (check_col(pinfo->cinfo, COL_INFO))
519 col_add_str(pinfo->cinfo, COL_INFO, message);
522 proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
523 call_dissector(data_handle,
524 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
529 format_oid(subid_t *oid, guint oid_length)
536 #ifdef HAVE_SOME_SNMP
538 size_t oid_string_len;
542 result_len = oid_length * 22;
544 #ifdef HAVE_SOME_SNMP
546 * Get the decoded form of the OID, and add its length to the
547 * length of the result string.
549 * XXX - check for "sprint_realloc_objid()" failure.
551 oid_string_len = 256;
552 oid_string = g_malloc(oid_string_len);
555 sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
557 result_len += strlen(oid_string) + 3;
560 result = g_malloc(result_len + 1);
562 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
564 for (i = 1; i < oid_length;i++) {
565 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
569 #ifdef HAVE_SOME_SNMP
571 * Append the decoded form of the OID.
573 sprintf(buf, " (%s)", oid_string);
580 /* returns the decoded (can be NULL) and non_decoded OID strings,
581 returned pointers shall be freed by the caller */
583 new_format_oid(subid_t *oid, guint oid_length,
584 gchar **non_decoded, gchar **decoded)
590 #ifdef HAVE_SOME_SNMP
592 size_t oid_string_len;
596 * Get the decoded form of the OID, and add its length to the
597 * length of the result string.
600 oid_string_len = 256;
601 oid_string = g_malloc(oid_string_len);
604 sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
606 *decoded = oid_string;
611 *non_decoded = g_malloc(oid_length * 22 + 1);
613 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
615 for (i = 1; i < oid_length; i++) {
616 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
621 #ifdef HAVE_SOME_SNMP
623 check_var_length(guint vb_length, guint required_length)
626 static const char badlen_fmt[] = "Length is %u, should be %u";
628 if (vb_length != required_length) {
629 /* Enough room for the largest "Length is XXX,
630 should be XXX" message - 10 digits for each
632 buf = g_malloc(sizeof badlen_fmt + 10 + 10);
633 sprintf(buf, badlen_fmt, vb_length, required_length);
636 return NULL; /* length is OK */
640 format_var(struct variable_list *variable, subid_t *variable_oid,
641 guint variable_oid_length, gushort vb_type, guint val_len)
651 /* Length has to be 4 bytes. */
652 buf = check_var_length(val_len, 4);
654 return buf; /* it's not 4 bytes */
658 /* Length has to be 8 bytes. */
659 buf = check_var_length(val_len, 8);
661 return buf; /* it's not 8 bytes */
668 variable->next_variable = NULL;
669 variable->name = variable_oid;
670 variable->name_length = variable_oid_length;
674 variable->type = VALTYPE_INTEGER;
678 variable->type = VALTYPE_COUNTER;
682 variable->type = VALTYPE_GAUGE;
686 variable->type = VALTYPE_TIMETICKS;
690 variable->type = VALTYPE_STRING;
694 variable->type = VALTYPE_IPADDR;
698 variable->type = VALTYPE_OPAQUE;
702 variable->type = VALTYPE_NSAP;
706 variable->type = VALTYPE_OBJECTID;
710 variable->type = VALTYPE_BITSTR;
714 variable->type = VALTYPE_COUNTER64;
717 variable->val_len = val_len;
720 * XXX - check for "sprint_realloc_objid()" failure.
723 buf = g_malloc(buf_len);
726 sprint_realloc_value(&buf, &buf_len, &out_len, 1, variable_oid,
727 variable_oid_length, variable);
730 * "sprint_realloc_value" can put newlines into the string it
731 * produces; turn them into spaces, as this is all supposed to be
734 for (i = 0; i < out_len; i++) {
744 snmp_variable_decode(proto_tree *snmp_tree,
745 subid_t *variable_oid
746 #ifndef HAVE_SOME_SNMP
750 guint variable_oid_length
751 #ifndef HAVE_SOME_SNMP
755 ASN1_SCK *asn1, int offset, guint *lengthp)
766 gint32 vb_integer_value;
767 guint32 vb_uinteger_value;
769 guint8 *vb_octet_string;
774 gchar *vb_display_string;
776 #ifdef HAVE_SOME_SNMP
777 struct variable_list variable;
779 #else /* HAVE_SOME_SNMP */
783 #endif /* HAVE_SOME_SNMP */
785 /* parse the type of the object */
786 start = asn1->offset;
787 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
788 if (ret != ASN1_ERR_NOERROR)
791 return ASN1_ERR_LENGTH_NOT_DEFINITE;
793 /* Convert the class, constructed flag, and tag to a type. */
794 vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
795 if (vb_type_name == NULL) {
798 * Dissect the value as an opaque string of octets.
800 vb_type_name = "unsupported type";
801 vb_type = SNMP_OPAQUE;
804 /* parse the value */
808 ret = asn1_int32_value_decode(asn1, vb_length,
810 if (ret != ASN1_ERR_NOERROR)
812 length = asn1->offset - start;
814 #ifdef HAVE_SOME_SNMP
815 value = vb_integer_value;
816 variable.val.integer = &value;
817 vb_display_string = format_var(&variable,
818 variable_oid, variable_oid_length, vb_type,
820 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
822 "Value: %s", vb_display_string);
823 g_free(vb_display_string);
824 #else /* HAVE_SOME_SNMP */
825 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
827 "Value: %s: %d (%#x)", vb_type_name,
828 vb_integer_value, vb_integer_value);
829 #endif /* HAVE_SOME_SNMP */
836 ret = asn1_uint32_value_decode(asn1, vb_length,
838 if (ret != ASN1_ERR_NOERROR)
840 length = asn1->offset - start;
842 #ifdef HAVE_SOME_SNMP
843 value = vb_uinteger_value;
844 variable.val.integer = &value;
845 vb_display_string = format_var(&variable,
846 variable_oid, variable_oid_length, vb_type,
848 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
850 "Value: %s", vb_display_string);
851 g_free(vb_display_string);
852 #else /* HAVE_SOME_SNMP */
853 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
855 "Value: %s: %u (%#x)", vb_type_name,
856 vb_uinteger_value, vb_uinteger_value);
857 #endif /* HAVE_SOME_SNMP */
867 ret = asn1_string_value_decode (asn1, vb_length,
869 if (ret != ASN1_ERR_NOERROR)
871 length = asn1->offset - start;
873 #ifdef HAVE_SOME_SNMP
874 variable.val.string = vb_octet_string;
875 vb_display_string = format_var(&variable,
876 variable_oid, variable_oid_length, vb_type,
878 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
880 "Value: %s", vb_display_string);
881 g_free(vb_display_string);
882 #else /* HAVE_SOME_SNMP */
884 * If some characters are not printable, display
885 * the string as bytes.
887 for (i = 0; i < vb_length; i++) {
888 if (!(isprint(vb_octet_string[i])
889 || isspace(vb_octet_string[i])))
894 * We stopped, due to a non-printable
895 * character, before we got to the end
898 vb_display_string = g_malloc(4*vb_length);
899 buf = &vb_display_string[0];
900 len = sprintf(buf, "%03u", vb_octet_string[0]);
902 for (i = 1; i < vb_length; i++) {
903 len = sprintf(buf, ".%03u",
907 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
909 "Value: %s: %s", vb_type_name,
911 g_free(vb_display_string);
913 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
915 "Value: %s: %s", vb_type_name,
916 SAFE_STRING(vb_octet_string, vb_length));
918 #endif /* HAVE_SOME_SNMP */
920 g_free(vb_octet_string);
924 ret = asn1_null_decode (asn1, vb_length);
925 if (ret != ASN1_ERR_NOERROR)
927 length = asn1->offset - start;
929 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
930 "Value: %s", vb_type_name);
935 ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
937 if (ret != ASN1_ERR_NOERROR)
939 length = asn1->offset - start;
941 #ifdef HAVE_SOME_SNMP
942 variable.val.objid = vb_oid;
943 vb_display_string = format_var(&variable,
944 variable_oid, variable_oid_length, vb_type,
945 vb_oid_length * sizeof (subid_t));
946 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
948 "Value: %s", vb_display_string);
949 g_free(vb_display_string);
950 #else /* HAVE_SOME_SNMP */
951 vb_display_string = format_oid(vb_oid, vb_oid_length);
952 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
954 "Value: %s: %s", vb_type_name, vb_display_string);
955 g_free(vb_display_string);
956 #endif /* HAVE_SOME_SNMP */
961 case SNMP_NOSUCHOBJECT:
962 length = asn1->offset - start;
964 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
965 "Value: %s: no such object", vb_type_name);
969 case SNMP_NOSUCHINSTANCE:
970 length = asn1->offset - start;
972 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
973 "Value: %s: no such instance", vb_type_name);
977 case SNMP_ENDOFMIBVIEW:
978 length = asn1->offset - start;
980 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
981 "Value: %s: end of mib view", vb_type_name);
986 g_assert_not_reached();
987 return ASN1_ERR_WRONG_TYPE;
990 return ASN1_ERR_NOERROR;
994 dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
995 proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
999 guint sequence_length;
1003 guint32 error_status;
1005 guint32 error_index;
1007 char *pdu_type_string;
1009 subid_t *enterprise;
1010 guint enterprise_length;
1012 guint32 agent_ipaddr;
1014 guint8 *agent_address;
1015 guint agent_address_length;
1019 guint32 specific_type;
1022 guint timestamp_length;
1026 guint variable_bindings_length;
1029 guint variable_length;
1030 subid_t *variable_oid;
1031 guint variable_oid_length;
1034 guint cls, con, tag;
1036 pdu_type_string = val_to_str(pdu_type, pdu_types,
1037 "Unknown PDU type %#x");
1038 if (check_col(pinfo->cinfo, COL_INFO))
1039 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1040 length = asn1.offset - start;
1042 proto_tree_add_uint(tree, hf_snmp_pdutype, tvb, offset, length,
1047 /* get the fields in the PDU preceeding the variable-bindings sequence */
1051 case SNMP_MSG_GETNEXT:
1052 case SNMP_MSG_RESPONSE:
1054 case SNMP_MSG_GETBULK:
1055 case SNMP_MSG_INFORM:
1056 case SNMP_MSG_TRAP2:
1057 case SNMP_MSG_REPORT:
1059 ret = asn1_uint32_decode (&asn1, &request_id, &length);
1060 if (ret != ASN1_ERR_NOERROR) {
1061 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1066 proto_tree_add_uint(tree, hf_snmp_request_id,
1067 tvb, offset, length, request_id);
1071 /* error status, or getbulk non-repeaters */
1072 ret = asn1_uint32_decode (&asn1, &error_status, &length);
1073 if (ret != ASN1_ERR_NOERROR) {
1074 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1075 (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
1081 if (pdu_type == SNMP_MSG_GETBULK) {
1082 proto_tree_add_text(tree, tvb, offset,
1083 length, "Non-repeaters: %u", error_status);
1085 proto_tree_add_uint(tree,
1086 hf_snmp_error_status,
1088 length, error_status);
1093 /* error index, or getbulk max-repetitions */
1094 ret = asn1_uint32_decode (&asn1, &error_index, &length);
1095 if (ret != ASN1_ERR_NOERROR) {
1096 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1097 (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
1103 if (pdu_type == SNMP_MSG_GETBULK) {
1104 proto_tree_add_text(tree, tvb, offset,
1105 length, "Max repetitions: %u", error_index);
1107 proto_tree_add_text(tree, tvb, offset,
1108 length, "Error Index: %u", error_index);
1116 ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
1118 if (ret != ASN1_ERR_NOERROR) {
1119 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1120 "enterprise OID", ret);
1124 oid_string = format_oid(enterprise, enterprise_length);
1125 proto_tree_add_string(tree, hf_snmp_enterprise, tvb,
1126 offset, length, oid_string);
1133 start = asn1.offset;
1134 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1135 &def, &agent_address_length);
1136 if (ret != ASN1_ERR_NOERROR) {
1137 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1138 "agent address", ret);
1141 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
1142 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
1143 /* GXSNMP 0.0.15 says the latter is "needed for
1145 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1146 "agent_address", ASN1_ERR_WRONG_TYPE);
1149 if (agent_address_length != 4) {
1150 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1151 "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
1154 ret = asn1_string_value_decode (&asn1,
1155 agent_address_length, &agent_address);
1156 if (ret != ASN1_ERR_NOERROR) {
1157 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1158 "agent address", ret);
1161 length = asn1.offset - start;
1163 if (agent_address_length != 4) {
1164 proto_tree_add_text(tree, tvb, offset,
1166 "Agent address: <length is %u, not 4>",
1167 agent_address_length);
1169 memcpy((guint8 *)&agent_ipaddr, agent_address,
1170 agent_address_length);
1171 proto_tree_add_ipv4(tree, hf_snmp_agent, tvb,
1172 offset, length, agent_ipaddr);
1175 g_free(agent_address);
1178 /* generic trap type */
1179 ret = asn1_uint32_decode (&asn1, &trap_type, &length);
1180 if (ret != ASN1_ERR_NOERROR) {
1181 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1182 "generic trap type", ret);
1186 proto_tree_add_uint(tree, hf_snmp_traptype, tvb,
1187 offset, length, trap_type);
1191 /* specific trap type */
1192 ret = asn1_uint32_decode (&asn1, &specific_type, &length);
1193 if (ret != ASN1_ERR_NOERROR) {
1194 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1195 "specific trap type", ret);
1199 proto_tree_add_uint(tree, hf_snmp_spectraptype, tvb,
1200 offset, length, specific_type);
1205 start = asn1.offset;
1206 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1207 &def, ×tamp_length);
1208 if (ret != ASN1_ERR_NOERROR) {
1209 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1213 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
1214 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
1215 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1216 "timestamp", ASN1_ERR_WRONG_TYPE);
1219 ret = asn1_uint32_value_decode(&asn1, timestamp_length,
1221 if (ret != ASN1_ERR_NOERROR) {
1222 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1226 length = asn1.offset - start;
1228 proto_tree_add_uint(tree, hf_snmp_timestamp, tvb,
1229 offset, length, timestamp);
1235 /* variable bindings */
1236 /* get header for variable-bindings sequence */
1237 ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
1238 if (ret != ASN1_ERR_NOERROR) {
1239 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1240 "variable bindings header", ret);
1245 /* loop on variable bindings */
1247 while (variable_bindings_length > 0) {
1249 sequence_length = 0;
1252 ret = asn1_sequence_decode(&asn1, &variable_length, &length);
1253 if (ret != ASN1_ERR_NOERROR) {
1254 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1255 "variable binding header", ret);
1258 sequence_length += length;
1260 /* parse object identifier */
1261 ret = asn1_oid_decode (&asn1, &variable_oid,
1262 &variable_oid_length, &length);
1263 if (ret != ASN1_ERR_NOERROR) {
1264 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1265 "variable binding OID", ret);
1268 sequence_length += length;
1270 if (display_oid || tree) {
1273 gchar *non_decoded_oid;
1275 new_format_oid(variable_oid, variable_oid_length,
1276 &non_decoded_oid, &decoded_oid);
1278 if (display_oid && check_col(pinfo->cinfo, COL_INFO)) {
1279 col_append_fstr(pinfo->cinfo, COL_INFO,
1281 (decoded_oid == NULL) ? non_decoded_oid :
1287 proto_tree_add_string_format(tree, hf_snmp_oid,
1291 "Object identifier %d: %s (%s)",
1295 /* add also the non decoded oid string */
1296 proto_tree_add_string_hidden(tree, hf_snmp_oid,
1301 proto_tree_add_string_format(tree, hf_snmp_oid,
1305 "Object identifier %d: %s",
1311 if (decoded_oid) g_free(decoded_oid);
1312 g_free(non_decoded_oid);
1316 offset += sequence_length;
1317 variable_bindings_length -= sequence_length;
1319 /* Parse the variable's value */
1320 ret = snmp_variable_decode(tree, variable_oid,
1321 variable_oid_length, &asn1, offset, &length);
1322 if (ret != ASN1_ERR_NOERROR) {
1323 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1328 variable_bindings_length -= length;
1332 static const value_string qos_vals[] = {
1333 { 0x0, "No authentication or privacy" },
1334 { 0x1, "Authentication, no privacy" },
1335 { 0x2, "Authentication and privacy" },
1336 { 0x3, "Authentication and privacy" },
1341 dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
1342 guchar *parameters, int parameters_length)
1345 proto_tree *parameters_tree;
1346 proto_tree *qos_tree;
1351 item = proto_tree_add_text(tree, tvb, offset, length,
1353 parameters_tree = proto_item_add_subtree(item, ett_parameters);
1354 offset += length - parameters_length;
1356 if (parameters_length < 1)
1358 model = *parameters;
1359 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1360 "model: %u", model);
1363 parameters_length -= 1;
1365 /* Unknown model. */
1366 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length, "parameters: %s",
1367 bytes_to_str(parameters, parameters_length));
1371 if (parameters_length < 1)
1374 item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
1376 qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
1377 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1378 decode_boolean_bitfield(qos, 0x04,
1379 8, "Generation of report PDU allowed",
1380 "Generation of report PDU not allowed"));
1381 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1382 decode_enumerated_bitfield(qos, 0x03,
1383 8, qos_vals, "%s"));
1386 parameters_length -= 1;
1388 if (parameters_length < 12)
1390 proto_tree_add_text(parameters_tree, tvb, offset, 12,
1391 "agentID: %s", bytes_to_str(parameters, 12));
1394 parameters_length -= 12;
1396 if (parameters_length < 4)
1398 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1399 "agentBoots: %u", pntohl(parameters));
1402 parameters_length -= 4;
1404 if (parameters_length < 4)
1406 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1407 "agentTime: %u", pntohl(parameters));
1410 parameters_length -= 4;
1412 if (parameters_length < 2)
1414 proto_tree_add_text(parameters_tree, tvb, offset, 2,
1415 "maxSize: %u", pntohs(parameters));
1418 parameters_length -= 2;
1420 if (parameters_length < 1)
1423 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1424 "userLen: %u", len);
1427 parameters_length -= 1;
1429 if (parameters_length < len)
1431 proto_tree_add_text(parameters_tree, tvb, offset, len,
1432 "userName: %.*s", len, parameters);
1435 parameters_length -= len;
1437 if (parameters_length < 1)
1440 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1441 "authLen: %u", len);
1444 parameters_length -= 1;
1446 if (parameters_length < len)
1448 proto_tree_add_text(parameters_tree, tvb, offset, len,
1449 "authDigest: %s", bytes_to_str(parameters, len));
1452 parameters_length -= len;
1454 if (parameters_length < 1)
1456 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
1457 "contextSelector: %s", bytes_to_str(parameters, parameters_length));
1461 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1462 proto_tree *tree, char *proto_name, int proto, gint ett)
1469 guint message_length;
1470 guint global_length;
1476 guint32 engineboots;
1490 int msgflags_length;
1491 int community_length;
1493 int cengineid_length;
1495 int cryptpdu_length;
1496 int aengineid_length;
1497 int username_length;
1504 proto_tree *snmp_tree = NULL;
1505 proto_tree *global_tree = NULL;
1506 proto_tree *flags_tree = NULL;
1507 proto_tree *secur_tree = NULL;
1508 proto_item *item = NULL;
1510 guint cls, con, tag;
1512 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1513 col_add_str(pinfo->cinfo, COL_PROTOCOL, proto_name);
1516 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
1517 snmp_tree = proto_item_add_subtree(item, ett);
1520 /* NOTE: we have to parse the message piece by piece, since the
1521 * capture length may be less than the message length: a 'global'
1522 * parsing is likely to fail.
1524 /* parse the SNMP header */
1525 asn1_open(&asn1, tvb, offset);
1526 ret = asn1_sequence_decode(&asn1, &message_length, &length);
1527 if (ret != ASN1_ERR_NOERROR) {
1528 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1529 "message header", ret);
1534 ret = asn1_uint32_decode (&asn1, &version, &length);
1535 if (ret != ASN1_ERR_NOERROR) {
1536 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1537 "version number", ret);
1541 proto_tree_add_uint(snmp_tree, hf_snmp_version, tvb, offset,
1548 case SNMP_VERSION_1:
1549 case SNMP_VERSION_2c:
1550 ret = asn1_octet_string_decode (&asn1, &community,
1551 &community_length, &length);
1552 if (ret != ASN1_ERR_NOERROR) {
1553 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1558 commustr = g_malloc(community_length+1);
1559 memcpy(commustr, community, community_length);
1560 commustr[community_length] = '\0';
1562 proto_tree_add_string(snmp_tree, hf_snmp_community,
1563 tvb, offset, length, commustr);
1569 case SNMP_VERSION_2u:
1570 ret = asn1_octet_string_decode (&asn1, &community,
1571 &community_length, &length);
1573 dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
1574 community, community_length);
1579 case SNMP_VERSION_3:
1580 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1581 if (ret != ASN1_ERR_NOERROR) {
1582 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1583 "message global header", ret);
1587 item = proto_tree_add_text(snmp_tree, tvb, offset,
1588 global_length + length, "Message Global Header");
1589 global_tree = proto_item_add_subtree(item, ett_global);
1590 proto_tree_add_text(global_tree, tvb, offset,
1592 "Message Global Header Length: %d", global_length);
1595 ret = asn1_uint32_decode (&asn1, &msgid, &length);
1596 if (ret != ASN1_ERR_NOERROR) {
1597 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1602 proto_tree_add_text(global_tree, tvb, offset,
1603 length, "Message ID: %d", msgid);
1606 ret = asn1_uint32_decode (&asn1, &msgmax, &length);
1607 if (ret != ASN1_ERR_NOERROR) {
1608 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1609 "message max size", ret);
1613 proto_tree_add_text(global_tree, tvb, offset,
1614 length, "Message Max Size: %d", msgmax);
1617 ret = asn1_octet_string_decode (&asn1, &msgflags,
1618 &msgflags_length, &length);
1619 if (ret != ASN1_ERR_NOERROR) {
1620 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1621 "message flags", ret);
1624 if (msgflags_length != 1) {
1625 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1626 "message flags wrong length", ret);
1631 item = proto_tree_add_uint_format(global_tree,
1632 hf_snmpv3_flags, tvb, offset, length,
1633 msgflags[0], "Flags: 0x%02x", msgflags[0]);
1634 flags_tree = proto_item_add_subtree(item, ett_flags);
1635 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
1636 tvb, offset, length, msgflags[0]);
1637 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
1638 tvb, offset, length, msgflags[0]);
1639 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
1640 tvb, offset, length, msgflags[0]);
1642 encrypted = msgflags[0] & TH_CRYPT;
1645 ret = asn1_uint32_decode (&asn1, &msgsec, &length);
1646 if (ret != ASN1_ERR_NOERROR) {
1647 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1648 "message security model", ret);
1652 proto_tree_add_text(global_tree, tvb, offset,
1653 length, "Message Security Model: %s",
1654 val_to_str(msgsec, sec_models,
1655 "Unknown model %#x"));
1660 start = asn1.offset;
1661 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1662 &def, &secparm_length);
1663 length = asn1.offset - start;
1664 if (cls != ASN1_UNI && con != ASN1_PRI &&
1666 dissect_snmp_parse_error(tvb, offset, pinfo,
1667 snmp_tree, "Message Security Parameters",
1668 ASN1_ERR_WRONG_TYPE);
1672 item = proto_tree_add_text(snmp_tree, tvb,
1673 offset, secparm_length + length,
1674 "Message Security Parameters");
1675 secur_tree = proto_item_add_subtree(item,
1677 proto_tree_add_text(secur_tree, tvb, offset,
1679 "Message Security Parameters Length: %d",
1683 ret = asn1_sequence_decode(&asn1, &secparm_length,
1685 if (ret != ASN1_ERR_NOERROR) {
1686 dissect_snmp_parse_error(tvb, offset, pinfo,
1687 snmp_tree, "USM sequence header", ret);
1691 ret = asn1_octet_string_decode (&asn1, &aengineid,
1692 &aengineid_length, &length);
1693 if (ret != ASN1_ERR_NOERROR) {
1694 dissect_snmp_parse_error(tvb, offset, pinfo,
1695 snmp_tree, "authoritative engine id", ret);
1699 proto_tree_add_text(secur_tree, tvb, offset,
1700 length, "Authoritative Engine ID: %s",
1701 bytes_to_str(aengineid, aengineid_length));
1705 ret = asn1_uint32_decode (&asn1, &engineboots, &length);
1706 if (ret != ASN1_ERR_NOERROR) {
1707 dissect_snmp_parse_error(tvb, offset, pinfo,
1708 snmp_tree, "engine boots", ret);
1712 proto_tree_add_text(secur_tree, tvb,
1713 offset, length, "Engine Boots: %d",
1717 ret = asn1_uint32_decode (&asn1, &enginetime, &length);
1718 if (ret != ASN1_ERR_NOERROR) {
1719 dissect_snmp_parse_error(tvb, offset, pinfo,
1720 snmp_tree, "engine time", ret);
1724 proto_tree_add_text(secur_tree, tvb,
1725 offset, length, "Engine Time: %d",
1729 ret = asn1_octet_string_decode (&asn1, &username,
1730 &username_length, &length);
1731 if (ret != ASN1_ERR_NOERROR) {
1732 dissect_snmp_parse_error(tvb, offset, pinfo,
1733 snmp_tree, "user name", ret);
1737 proto_tree_add_text(secur_tree, tvb, offset,
1738 length, "User Name: %s",
1739 SAFE_STRING(username, username_length));
1743 ret = asn1_octet_string_decode (&asn1, &authpar,
1744 &authpar_length, &length);
1745 if (ret != ASN1_ERR_NOERROR) {
1746 dissect_snmp_parse_error(tvb, offset, pinfo,
1747 snmp_tree, "authentication parameter", ret);
1751 proto_tree_add_text(secur_tree, tvb, offset,
1752 length, "Authentication Parameter: %s",
1753 bytes_to_str(authpar, authpar_length));
1757 ret = asn1_octet_string_decode (&asn1, &privpar,
1758 &privpar_length, &length);
1759 if (ret != ASN1_ERR_NOERROR) {
1760 dissect_snmp_parse_error(tvb, offset, pinfo,
1761 snmp_tree, "privacy parameter", ret);
1765 proto_tree_add_text(secur_tree, tvb, offset,
1766 length, "Privacy Parameter: %s",
1767 bytes_to_str(privpar, privpar_length));
1773 ret = asn1_octet_string_decode (&asn1,
1774 &secparm, &secparm_length, &length);
1775 if (ret != ASN1_ERR_NOERROR) {
1776 dissect_snmp_parse_error(tvb, offset, pinfo,
1777 snmp_tree, "Message Security Parameters",
1782 proto_tree_add_text(snmp_tree, tvb, offset,
1784 "Message Security Parameters Data"
1785 " (%d bytes)", secparm_length);
1791 /* PDU starts here */
1793 ret = asn1_octet_string_decode (&asn1, &cryptpdu,
1794 &cryptpdu_length, &length);
1795 if (ret != ASN1_ERR_NOERROR) {
1796 dissect_snmp_parse_error(tvb, offset, pinfo,
1797 snmp_tree, "encrypted PDU header", ret);
1800 proto_tree_add_text(snmp_tree, tvb, offset, length,
1801 "Encrypted PDU (%d bytes)", length);
1803 if (check_col(pinfo->cinfo, COL_INFO))
1804 col_set_str(pinfo->cinfo, COL_INFO, "Encrypted PDU");
1807 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1808 if (ret != ASN1_ERR_NOERROR) {
1809 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1814 ret = asn1_octet_string_decode (&asn1, &cengineid,
1815 &cengineid_length, &length);
1816 if (ret != ASN1_ERR_NOERROR) {
1817 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1818 "context engine id", ret);
1822 proto_tree_add_text(snmp_tree, tvb, offset, length,
1823 "Context Engine ID: %s",
1824 bytes_to_str(cengineid, cengineid_length));
1828 ret = asn1_octet_string_decode (&asn1, &cname,
1829 &cname_length, &length);
1830 if (ret != ASN1_ERR_NOERROR) {
1831 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1832 "context name", ret);
1836 proto_tree_add_text(snmp_tree, tvb, offset, length,
1838 SAFE_STRING(cname, cname_length));
1844 dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
1845 "PDU for unknown version of SNMP");
1849 start = asn1.offset;
1850 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1852 if (ret != ASN1_ERR_NOERROR) {
1853 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1857 if (cls != ASN1_CTX || con != ASN1_CON) {
1858 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1859 "PDU type", ASN1_ERR_WRONG_TYPE);
1862 dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
1866 dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1867 proto_tree *tree, int proto, gint ett)
1875 char *pdu_type_string;
1885 int password_length;
1887 guchar *application;
1888 int application_length;
1895 proto_tree *smux_tree = NULL;
1896 proto_item *item = NULL;
1900 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1901 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
1904 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
1905 smux_tree = proto_item_add_subtree(item, ett);
1908 /* NOTE: we have to parse the message piece by piece, since the
1909 * capture length may be less than the message length: a 'global'
1910 * parsing is likely to fail.
1912 /* parse the SNMP header */
1913 asn1_open(&asn1, tvb, offset);
1914 start = asn1.offset;
1915 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1917 if (ret != ASN1_ERR_NOERROR) {
1918 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1923 /* Dissect SMUX here */
1924 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
1925 pdu_type_string = val_to_str(pdu_type, smux_types,
1926 "Unknown PDU type %#x");
1927 if (check_col(pinfo->cinfo, COL_INFO))
1928 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1929 length = asn1.offset - start;
1931 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
1932 offset, length, pdu_type);
1935 ret = asn1_uint32_decode (&asn1, &version, &length);
1936 if (ret != ASN1_ERR_NOERROR) {
1937 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1942 proto_tree_add_uint(smux_tree, hf_smux_version, tvb,
1943 offset, length, version);
1947 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1948 if (ret != ASN1_ERR_NOERROR) {
1949 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1950 "registration OID", ret);
1954 oid_string = format_oid(regid, regid_length);
1955 proto_tree_add_text(smux_tree, tvb, offset, length,
1956 "Registration: %s", oid_string);
1962 ret = asn1_octet_string_decode (&asn1, &application,
1963 &application_length, &length);
1964 if (ret != ASN1_ERR_NOERROR) {
1965 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1966 "application", ret);
1970 proto_tree_add_text(smux_tree, tvb, offset, length,
1972 SAFE_STRING(application, application_length));
1974 g_free(application);
1977 ret = asn1_octet_string_decode (&asn1, &password,
1978 &password_length, &length);
1979 if (ret != ASN1_ERR_NOERROR) {
1980 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1985 proto_tree_add_text(smux_tree, tvb, offset, length,
1987 SAFE_STRING(password, password_length));
1993 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
1994 pdu_type_string = val_to_str(pdu_type, smux_types,
1995 "Unknown PDU type %#x");
1996 if (check_col(pinfo->cinfo, COL_INFO))
1997 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1998 length = asn1.offset - start;
2000 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2001 offset, length, pdu_type);
2004 ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
2005 if (ret != ASN1_ERR_NOERROR) {
2006 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2011 proto_tree_add_text(smux_tree, tvb, offset,
2012 pdu_length, "Cause: %s",
2013 val_to_str(cause, smux_close,
2014 "Unknown cause %#x"));
2016 offset += pdu_length;
2019 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
2020 pdu_type_string = val_to_str(pdu_type, smux_types,
2021 "Unknown PDU type %#x");
2022 if (check_col(pinfo->cinfo, COL_INFO))
2023 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2024 length = asn1.offset - start;
2026 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2027 offset, length, pdu_type);
2030 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
2031 if (ret != ASN1_ERR_NOERROR) {
2032 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2033 "registration subtree", ret);
2037 oid_string = format_oid(regid, regid_length);
2038 proto_tree_add_text(smux_tree, tvb, offset, length,
2039 "Registration: %s", oid_string);
2045 ret = asn1_uint32_decode (&asn1, &priority, &length);
2046 if (ret != ASN1_ERR_NOERROR) {
2047 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2052 proto_tree_add_text(smux_tree, tvb, offset, length,
2053 "Priority: %d", priority);
2057 ret = asn1_uint32_decode (&asn1, &operation, &length);
2058 if (ret != ASN1_ERR_NOERROR) {
2059 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2064 proto_tree_add_text(smux_tree, tvb, offset, length,
2066 val_to_str(operation, smux_rreq,
2067 "Unknown operation %#x"));
2072 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
2073 pdu_type_string = val_to_str(pdu_type, smux_types,
2074 "Unknown PDU type %#x");
2075 if (check_col(pinfo->cinfo, COL_INFO))
2076 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2077 length = asn1.offset - start;
2079 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2080 offset, length, pdu_type);
2083 ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
2084 if (ret != ASN1_ERR_NOERROR) {
2085 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2090 proto_tree_add_text(smux_tree, tvb, offset,
2092 val_to_str(priority, smux_prio,
2095 offset += pdu_length;
2098 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
2099 pdu_type_string = val_to_str(pdu_type, smux_types,
2100 "Unknown PDU type %#x");
2101 if (check_col(pinfo->cinfo, COL_INFO))
2102 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2103 length = asn1.offset - start;
2105 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2106 offset, length, pdu_type);
2109 ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
2110 if (ret != ASN1_ERR_NOERROR) {
2111 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2116 proto_tree_add_text(smux_tree, tvb, offset,
2118 val_to_str(commit, smux_sout,
2119 "Unknown SOUT Value: %#x"));
2121 offset += pdu_length;
2124 if (cls != ASN1_CTX || con != ASN1_CON) {
2125 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2126 "PDU type", ASN1_ERR_WRONG_TYPE);
2129 dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
2133 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2135 conversation_t *conversation;
2138 * The first SNMP packet goes to the SNMP port; the second one
2139 * may come from some *other* port, but goes back to the same
2140 * IP address and port as the ones from which the first packet
2141 * came; all subsequent packets presumably go between those two
2142 * IP addresses and ports.
2144 * If this packet went to the SNMP port, we check to see if
2145 * there's already a conversation with one address/port pair
2146 * matching the source IP address and port of this packet,
2147 * the other address matching the destination IP address of this
2148 * packet, and any destination port.
2150 * If not, we create one, with its address 1/port 1 pair being
2151 * the source address/port of this packet, its address 2 being
2152 * the destination address of this packet, and its port 2 being
2153 * wildcarded, and give it the SNMP dissector as a dissector.
2155 if (pinfo->destport == UDP_PORT_SNMP) {
2156 conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
2157 pinfo->srcport, 0, NO_PORT_B);
2158 if (conversation == NULL) {
2159 conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
2160 pinfo->srcport, 0, NO_PORT2);
2161 conversation_set_dissector(conversation, snmp_handle);
2165 dissect_snmp_pdu(tvb, 0, pinfo, tree, "SNMP", proto_snmp, ett_snmp);
2169 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2171 dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
2175 proto_register_snmp(void)
2177 #if defined(WIN32) && defined(HAVE_SOME_SNMP)
2179 #define MIB_PATH_APPEND "snmp\\mibs"
2182 static hf_register_info hf[] = {
2184 { "Version", "snmp.version", FT_UINT8, BASE_DEC, VALS(versions),
2186 { &hf_snmp_community,
2187 { "Community", "snmp.community", FT_STRING, BASE_NONE, NULL,
2189 { &hf_snmp_request_id,
2190 { "Request Id", "snmp.id", FT_UINT32, BASE_HEX, NULL,
2191 0x0, "Id for this transaction", HFILL }},
2193 { "PDU type", "snmp.pdutype", FT_UINT8, BASE_DEC, VALS(pdu_types),
2196 { "Agent address", "snmp.agent", FT_IPv4, BASE_NONE, NULL,
2198 { &hf_snmp_enterprise,
2199 { "Enterprise", "snmp.enterprise", FT_STRING, BASE_NONE, NULL,
2201 { &hf_snmp_error_status,
2202 { "Error Status", "snmp.error", FT_UINT8, BASE_DEC, VALS(error_statuses),
2205 { "Object identifier", "snmp.oid", FT_STRING, BASE_NONE, NULL,
2207 { &hf_snmp_traptype,
2208 { "Trap type", "snmp.traptype", FT_UINT8, BASE_DEC, VALS(trap_types),
2210 { &hf_snmp_spectraptype,
2211 { "Specific trap type", "snmp.spectraptype", FT_UINT32, BASE_DEC, NULL,
2213 { &hf_snmp_timestamp,
2214 { "Timestamp", "snmp.timestamp", FT_UINT8, BASE_DEC, NULL,
2217 { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
2219 { &hf_snmpv3_flags_auth,
2220 { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
2221 TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
2222 { &hf_snmpv3_flags_crypt,
2223 { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
2224 TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
2225 { &hf_snmpv3_flags_report,
2226 { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
2227 TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
2229 static gint *ett[] = {
2232 &ett_parameters_qos,
2237 module_t *snmp_module;
2239 #ifdef HAVE_SOME_SNMP
2242 /* Set MIBDIRS so that the SNMP library can find its mibs. */
2243 /* XXX - Should we set MIBS or MIBFILES as well? */
2245 mib_path = g_malloc (strlen(get_datafile_dir()) + strlen(MIB_PATH_APPEND) + 20);
2246 sprintf (mib_path, "MIBDIRS=%s\\%s", get_datafile_dir(), MIB_PATH_APPEND);
2247 /* Amazingly enough, Windows does not provide setenv(). */
2248 if (getenv("MIBDIRS") == NULL)
2255 * Suppress warnings about unknown tokens - we aren't initializing
2256 * UCD SNMP in its entirety, we're just initializing the
2257 * MIB-handling part because that's all we're using, which
2258 * means that entries in the configuration file for other
2259 * pars of the library will not be handled, and we don't want
2260 * the config file reading code to whine about that.
2262 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
2263 NETSNMP_DS_LIB_NO_TOKEN_WARNINGS, TRUE);
2264 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
2265 NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 2);
2266 register_mib_handlers();
2267 read_premib_configs();
2270 #endif /* HAVE_SOME_SNMP */
2271 proto_snmp = proto_register_protocol("Simple Network Management Protocol",
2273 proto_register_field_array(proto_snmp, hf, array_length(hf));
2274 proto_register_subtree_array(ett, array_length(ett));
2275 snmp_handle = create_dissector_handle(dissect_snmp, proto_snmp);
2277 /* Register configuration preferences */
2278 snmp_module = prefs_register_protocol(proto_snmp, NULL);
2279 prefs_register_bool_preference(snmp_module, "display_oid",
2280 "Show SNMP OID in info column",
2281 "Whether the SNMP OID should be shown in the info column",
2286 proto_reg_handoff_snmp(void)
2288 dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
2289 dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
2290 dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
2291 dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
2292 dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
2293 dissector_add("hpext.dxsap", HPEXT_SNMP, snmp_handle);
2294 data_handle = find_dissector("data");
2298 proto_register_smux(void)
2300 static hf_register_info hf[] = {
2302 { "Version", "smux.version", FT_UINT8, BASE_DEC, NULL,
2305 { "PDU type", "smux.pdutype", FT_UINT8, BASE_DEC, VALS(smux_types),
2308 static gint *ett[] = {
2312 proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2314 proto_register_field_array(proto_smux, hf, array_length(hf));
2315 proto_register_subtree_array(ett, array_length(ett));
2319 proto_reg_handoff_smux(void)
2321 dissector_handle_t smux_handle;
2323 smux_handle = create_dissector_handle(dissect_smux, proto_smux);
2324 dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);