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.
11 * $Id: packet-snmp.c,v 1.92 2002/04/08 01:55:05 guy Exp $
13 * Ethereal - Network traffic analyzer
14 * By Gerald Combs <gerald@ethereal.com>
15 * Copyright 1998 Gerald Combs
19 * GXSNMP -- An snmp mangament application
20 * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
21 * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version 2
26 * of the License, or (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #ifdef HAVE_SYS_TYPES_H
47 # include <sys/types.h>
50 #ifdef HAVE_NETINET_IN_H
51 # include <netinet/in.h>
56 #include <epan/packet.h>
57 #include <epan/strutil.h>
58 #include <epan/conversation.h>
60 #include "packet-ipx.h"
63 # include <ucd-snmp/ucd-snmp-config.h>
64 # include <ucd-snmp/asn1.h>
65 # include <ucd-snmp/snmp_api.h>
66 # include <ucd-snmp/snmp_impl.h>
67 # include <ucd-snmp/mib.h>
68 # include <ucd-snmp/default_store.h>
69 # include <ucd-snmp/read_config.h>
70 # include <ucd-snmp/tools.h>
73 * Define values "sprint_realloc_value()" expects.
75 # define VALTYPE_INTEGER ASN_INTEGER
76 # define VALTYPE_COUNTER ASN_COUNTER
77 # define VALTYPE_GAUGE ASN_GAUGE
78 # define VALTYPE_TIMETICKS ASN_TIMETICKS
79 # define VALTYPE_STRING ASN_OCTET_STR
80 # define VALTYPE_IPADDR ASN_IPADDRESS
81 # define VALTYPE_OPAQUE ASN_OPAQUE
82 # define VALTYPE_NSAP ASN_NSAP
83 # define VALTYPE_OBJECTID ASN_OBJECT_ID
84 # define VALTYPE_BITSTR ASN_BIT_STR
85 # define VALTYPE_COUNTER64 ASN_COUNTER64
91 #include "packet-snmp.h"
92 #include "format-oid.h"
94 /* Null string of type "guchar[]". */
95 static const guchar nullstring[] = "";
97 /* Take a pointer that may be null and return a pointer that's not null
98 by turning null pointers into pointers to the above null string. */
99 #define SAFE_STRING(s) (((s) != NULL) ? (s) : nullstring)
101 static int proto_snmp = -1;
102 static int proto_smux = -1;
104 static gint ett_snmp = -1;
105 static gint ett_smux = -1;
106 static gint ett_parameters = -1;
107 static gint ett_parameters_qos = -1;
108 static gint ett_global = -1;
109 static gint ett_flags = -1;
110 static gint ett_secur = -1;
112 static int hf_snmpv3_flags = -1;
113 static int hf_snmpv3_flags_auth = -1;
114 static int hf_snmpv3_flags_crypt = -1;
115 static int hf_snmpv3_flags_report = -1;
117 static dissector_handle_t snmp_handle;
118 static dissector_handle_t data_handle;
121 #define TH_CRYPT 0x02
122 #define TH_REPORT 0x04
124 static const true_false_string flags_set_truth = {
129 #define UDP_PORT_SNMP 161
130 #define UDP_PORT_SNMP_TRAP 162
131 #define TCP_PORT_SMUX 199
133 /* Protocol version numbers */
134 #define SNMP_VERSION_1 0
135 #define SNMP_VERSION_2c 1
136 #define SNMP_VERSION_2u 2
137 #define SNMP_VERSION_3 3
139 static const value_string versions[] = {
140 { SNMP_VERSION_1, "1" },
141 { SNMP_VERSION_2c, "2C" },
142 { SNMP_VERSION_2u, "2U" },
143 { SNMP_VERSION_3, "3" },
148 #define SNMP_MSG_GET 0
149 #define SNMP_MSG_GETNEXT 1
150 #define SNMP_MSG_RESPONSE 2
151 #define SNMP_MSG_SET 3
152 #define SNMP_MSG_TRAP 4
154 #define SNMP_MSG_GETBULK 5
155 #define SNMP_MSG_INFORM 6
156 #define SNMP_MSG_TRAP2 7
157 #define SNMP_MSG_REPORT 8
159 static const value_string pdu_types[] = {
160 { SNMP_MSG_GET, "GET" },
161 { SNMP_MSG_GETNEXT, "GET-NEXT" },
162 { SNMP_MSG_SET, "SET" },
163 { SNMP_MSG_RESPONSE, "RESPONSE" },
164 { SNMP_MSG_TRAP, "TRAP-V1" },
165 { SNMP_MSG_GETBULK, "GETBULK" },
166 { SNMP_MSG_INFORM, "INFORM" },
167 { SNMP_MSG_TRAP2, "TRAP-V2" },
168 { SNMP_MSG_REPORT, "REPORT" },
173 #define SMUX_MSG_OPEN 0
174 #define SMUX_MSG_CLOSE 1
175 #define SMUX_MSG_RREQ 2
176 #define SMUX_MSG_RRSP 3
177 #define SMUX_MSG_SOUT 4
179 static const value_string smux_types[] = {
180 { SMUX_MSG_OPEN, "Open" },
181 { SMUX_MSG_CLOSE, "Close" },
182 { SMUX_MSG_RREQ, "Registration Request" },
183 { SMUX_MSG_RRSP, "Registration Response" },
184 { SMUX_MSG_SOUT, "Commit Or Rollback" },
188 /* SMUX Closing causes */
189 #define SMUX_CLOSE_DOWN 0
190 #define SMUX_CLOSE_VERSION 1
191 #define SMUX_CLOSE_PACKET 2
192 #define SMUX_CLOSE_PROTOCOL 3
193 #define SMUX_CLOSE_INTERNAL 4
194 #define SMUX_CLOSE_NOAUTH 5
196 static const value_string smux_close[] = {
197 { SMUX_CLOSE_DOWN, "Going down" },
198 { SMUX_CLOSE_VERSION, "Unsupported Version" },
199 { SMUX_CLOSE_PACKET, "Packet Format Error" },
200 { SMUX_CLOSE_PROTOCOL, "Protocol Error" },
201 { SMUX_CLOSE_INTERNAL, "Internal Error" },
202 { SMUX_CLOSE_NOAUTH, "Unauthorized" },
206 /* SMUX Request codes */
207 #define SMUX_RREQ_DELETE 0
208 #define SMUX_RREQ_READONLY 1
209 #define SMUX_RREQ_READWRITE 2
211 static const value_string smux_rreq[] = {
212 { SMUX_RREQ_DELETE, "Delete" },
213 { SMUX_RREQ_READONLY, "Read Only" },
214 { SMUX_RREQ_READWRITE, "Read Write" },
218 static const value_string smux_prio[] = {
223 /* SMUX SOut codes */
224 #define SMUX_SOUT_COMMIT 0
225 #define SMUX_SOUT_ROLLBACK 1
227 static const value_string smux_sout[] = {
228 { SMUX_SOUT_COMMIT, "Commit" },
229 { SMUX_SOUT_ROLLBACK, "Rollback" },
233 /* Error status values */
234 #define SNMP_ERR_NOERROR 0
235 #define SNMP_ERR_TOOBIG 1
236 #define SNMP_ERR_NOSUCHNAME 2
237 #define SNMP_ERR_BADVALUE 3
238 #define SNMP_ERR_READONLY 4
239 #define SNMP_ERR_GENERROR 5
241 #define SNMP_ERR_NOACCESS 6
242 #define SNMP_ERR_WRONGTYPE 7
243 #define SNMP_ERR_WRONGLENGTH 8
244 #define SNMP_ERR_WRONGENCODING 9
245 #define SNMP_ERR_WRONGVALUE 10
246 #define SNMP_ERR_NOCREATION 11
247 #define SNMP_ERR_INCONSISTENTVALUE 12
248 #define SNMP_ERR_RESOURCEUNAVAILABLE 13
249 #define SNMP_ERR_COMMITFAILED 14
250 #define SNMP_ERR_UNDOFAILED 15
251 #define SNMP_ERR_AUTHORIZATIONERROR 16
252 #define SNMP_ERR_NOTWRITABLE 17
253 #define SNMP_ERR_INCONSISTENTNAME 18
255 static const value_string error_statuses[] = {
256 { SNMP_ERR_NOERROR, "NO ERROR" },
257 { SNMP_ERR_TOOBIG, "TOOBIG" },
258 { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" },
259 { SNMP_ERR_BADVALUE, "BAD VALUE" },
260 { SNMP_ERR_READONLY, "READ ONLY" },
261 { SNMP_ERR_GENERROR, "GENERIC ERROR" },
262 { SNMP_ERR_NOACCESS, "NO ACCESS" },
263 { SNMP_ERR_WRONGTYPE, "WRONG TYPE" },
264 { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" },
265 { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" },
266 { SNMP_ERR_WRONGVALUE, "WRONG VALUE" },
267 { SNMP_ERR_NOCREATION, "NO CREATION" },
268 { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" },
269 { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" },
270 { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" },
271 { SNMP_ERR_UNDOFAILED, "UNDO FAILED" },
272 { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" },
273 { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" },
274 { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" },
278 /* General SNMP V1 Traps */
280 #define SNMP_TRAP_COLDSTART 0
281 #define SNMP_TRAP_WARMSTART 1
282 #define SNMP_TRAP_LINKDOWN 2
283 #define SNMP_TRAP_LINKUP 3
284 #define SNMP_TRAP_AUTHFAIL 4
285 #define SNMP_TRAP_EGPNEIGHBORLOSS 5
286 #define SNMP_TRAP_ENTERPRISESPECIFIC 6
288 static const value_string trap_types[] = {
289 { SNMP_TRAP_COLDSTART, "COLD START" },
290 { SNMP_TRAP_WARMSTART, "WARM START" },
291 { SNMP_TRAP_LINKDOWN, "LINK DOWN" },
292 { SNMP_TRAP_LINKUP, "LINK UP" },
293 { SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
294 { SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
295 { SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
299 /* Security Models */
301 #define SNMP_SEC_ANY 0
302 #define SNMP_SEC_V1 1
303 #define SNMP_SEC_V2C 2
304 #define SNMP_SEC_USM 3
306 static const value_string sec_models[] = {
307 { SNMP_SEC_ANY, "Any" },
308 { SNMP_SEC_V1, "V1" },
309 { SNMP_SEC_V2C, "V2C" },
310 { SNMP_SEC_USM, "USM" },
316 #define SNMP_IPA 0 /* IP Address */
317 #define SNMP_CNT 1 /* Counter (Counter32) */
318 #define SNMP_GGE 2 /* Gauge (Gauge32) */
319 #define SNMP_TIT 3 /* TimeTicks */
320 #define SNMP_OPQ 4 /* Opaque */
321 #define SNMP_NSP 5 /* NsapAddress */
322 #define SNMP_C64 6 /* Counter64 */
323 #define SNMP_U32 7 /* Uinteger32 */
332 #define SNMP_INTEGER 1 /* l */
333 #define SNMP_OCTETSTR 2 /* c */
334 #define SNMP_DISPLAYSTR 2 /* c */
335 #define SNMP_OBJECTID 3 /* ul */
336 #define SNMP_IPADDR 4 /* uc */
337 #define SNMP_COUNTER 5 /* ul */
338 #define SNMP_GAUGE 6 /* ul */
339 #define SNMP_TIMETICKS 7 /* ul */
340 #define SNMP_OPAQUE 8 /* c */
342 /* additional SNMPv2 Types */
344 #define SNMP_UINTEGER 5 /* ul */
345 #define SNMP_BITSTR 9 /* uc */
346 #define SNMP_NSAP 10 /* uc */
347 #define SNMP_COUNTER64 11 /* ul */
348 #define SNMP_NOSUCHOBJECT 12
349 #define SNMP_NOSUCHINSTANCE 13
350 #define SNMP_ENDOFMIBVIEW 14
352 typedef struct _SNMP_CNV SNMP_CNV;
362 static SNMP_CNV SnmpCnv [] =
364 {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"},
365 {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"},
366 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"},
367 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"},
368 {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"},
369 {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */
370 {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */
371 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"},
372 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"},
374 /* SNMPv2 data types and errors */
376 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"},
377 {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"},
378 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"},
379 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"},
380 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"},
385 * NAME: g_snmp_tag_cls2syntax
386 * SYNOPSIS: gboolean g_snmp_tag_cls2syntax
392 * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name.
393 * See SnmpCnv for conversion.
394 * RETURNS: name on success, NULL on failure
398 snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
403 while (cnv->syntax != -1)
405 if (cnv->tag == tag && cnv->class == cls)
407 *syntax = cnv->syntax;
416 dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
417 proto_tree *tree, const char *field_name, int ret)
421 errstr = asn1_err_to_str(ret);
423 if (check_col(pinfo->cinfo, COL_INFO)) {
424 col_add_fstr(pinfo->cinfo, COL_INFO,
425 "ERROR: Couldn't parse %s: %s", field_name, errstr);
428 proto_tree_add_text(tree, tvb, offset, 0,
429 "ERROR: Couldn't parse %s: %s", field_name, errstr);
430 call_dissector(data_handle,
431 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
436 dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
437 proto_tree *tree, const char *message)
439 if (check_col(pinfo->cinfo, COL_INFO))
440 col_add_str(pinfo->cinfo, COL_INFO, message);
443 proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
444 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, tree);
449 format_oid(subid_t *oid, guint oid_length)
458 size_t oid_string_len;
462 result_len = oid_length * 22;
466 * Get the decoded form of the OID, and add its length to the
467 * length of the result string.
469 * XXX - check for "malloc" and "sprint_realloc_objid()" failure.
471 oid_string_len = 256;
472 oid_string = malloc(oid_string_len);
475 sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
477 result_len += strlen(oid_string) + 3;
480 result = g_malloc(result_len + 1);
482 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
484 for (i = 1; i < oid_length;i++) {
485 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
491 * Append the decoded form of the OID.
493 sprintf(buf, " (%s)", oid_string);
502 check_var_length(guint vb_length, guint required_length)
505 static const char badlen_fmt[] = "Length is %u, should be %u";
507 if (vb_length != required_length) {
508 /* Enough room for the largest "Length is XXX,
509 should be XXX" message - 10 digits for each
511 buf = malloc(sizeof badlen_fmt + 10 + 10);
512 sprintf(buf, badlen_fmt, vb_length, required_length);
515 return NULL; /* length is OK */
519 format_var(struct variable_list *variable, subid_t *variable_oid,
520 guint variable_oid_length, gushort vb_type, guint val_len)
529 /* Length has to be 4 bytes. */
530 buf = check_var_length(val_len, 4);
532 return buf; /* it's not 4 bytes */
536 /* Length has to be 8 bytes. */
537 buf = check_var_length(val_len, 8);
539 return buf; /* it's not 8 bytes */
546 variable->next_variable = NULL;
547 variable->name = variable_oid;
548 variable->name_length = variable_oid_length;
552 variable->type = VALTYPE_INTEGER;
556 variable->type = VALTYPE_COUNTER;
560 variable->type = VALTYPE_GAUGE;
564 variable->type = VALTYPE_TIMETICKS;
568 variable->type = VALTYPE_STRING;
572 variable->type = VALTYPE_IPADDR;
576 variable->type = VALTYPE_OPAQUE;
580 variable->type = VALTYPE_NSAP;
584 variable->type = VALTYPE_OBJECTID;
588 variable->type = VALTYPE_BITSTR;
592 variable->type = VALTYPE_COUNTER64;
595 variable->val_len = val_len;
598 * XXX - check for "malloc" and "sprint_realloc_objid()" failure.
601 buf = malloc(buf_len);
604 sprint_realloc_value(&buf, &buf_len, &out_len, 1, variable_oid,
605 variable_oid_length, variable);
611 snmp_variable_decode(proto_tree *snmp_tree,
612 subid_t *variable_oid
613 #ifndef HAVE_UCD_SNMP
617 guint variable_oid_length
618 #ifndef HAVE_UCD_SNMP
622 ASN1_SCK *asn1, int offset, guint *lengthp)
633 gint32 vb_integer_value;
634 guint32 vb_uinteger_value;
636 guint8 *vb_octet_string;
641 gchar *vb_display_string;
644 struct variable_list variable;
646 #else /* HAVE_UCD_SNMP */
650 #endif /* HAVE_UCD_SNMP */
652 /* parse the type of the object */
653 start = asn1->offset;
654 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
655 if (ret != ASN1_ERR_NOERROR)
658 return ASN1_ERR_LENGTH_NOT_DEFINITE;
660 /* Convert the class, constructed flag, and tag to a type. */
661 vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
662 if (vb_type_name == NULL) {
665 * Dissect the value as an opaque string of octets.
667 vb_type_name = "unsupported type";
668 vb_type = SNMP_OPAQUE;
671 /* parse the value */
675 ret = asn1_int32_value_decode(asn1, vb_length,
677 if (ret != ASN1_ERR_NOERROR)
679 length = asn1->offset - start;
682 value = vb_integer_value;
683 variable.val.integer = &value;
684 vb_display_string = format_var(&variable,
685 variable_oid, variable_oid_length, vb_type,
687 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
689 "Value: %s", vb_display_string);
690 free(vb_display_string);
691 #else /* HAVE_UCD_SNMP */
692 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
694 "Value: %s: %d (%#x)", vb_type_name,
695 vb_integer_value, vb_integer_value);
696 #endif /* HAVE_UCD_SNMP */
703 ret = asn1_uint32_value_decode(asn1, vb_length,
705 if (ret != ASN1_ERR_NOERROR)
707 length = asn1->offset - start;
710 value = vb_uinteger_value;
711 variable.val.integer = &value;
712 vb_display_string = format_var(&variable,
713 variable_oid, variable_oid_length, vb_type,
715 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
717 "Value: %s", vb_display_string);
718 free(vb_display_string);
719 #else /* HAVE_UCD_SNMP */
720 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
722 "Value: %s: %u (%#x)", vb_type_name,
723 vb_uinteger_value, vb_uinteger_value);
724 #endif /* HAVE_UCD_SNMP */
734 ret = asn1_string_value_decode (asn1, vb_length,
736 if (ret != ASN1_ERR_NOERROR)
738 length = asn1->offset - start;
741 variable.val.string = vb_octet_string;
742 vb_display_string = format_var(&variable,
743 variable_oid, variable_oid_length, vb_type,
745 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
747 "Value: %s", vb_display_string);
748 free(vb_display_string);
749 #else /* HAVE_UCD_SNMP */
751 * If some characters are not printable, display
752 * the string as bytes.
754 for (i = 0; i < vb_length; i++) {
755 if (!(isprint(vb_octet_string[i])
756 || isspace(vb_octet_string[i])))
761 * We stopped, due to a non-printable
762 * character, before we got to the end
765 vb_display_string = g_malloc(4*vb_length);
766 buf = &vb_display_string[0];
767 len = sprintf(buf, "%03u", vb_octet_string[0]);
769 for (i = 1; i < vb_length; i++) {
770 len = sprintf(buf, ".%03u",
774 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
776 "Value: %s: %s", vb_type_name,
778 g_free(vb_display_string);
780 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
782 "Value: %s: %.*s", vb_type_name,
784 SAFE_STRING(vb_octet_string));
786 #endif /* HAVE_UCD_SNMP */
788 g_free(vb_octet_string);
792 ret = asn1_null_decode (asn1, vb_length);
793 if (ret != ASN1_ERR_NOERROR)
795 length = asn1->offset - start;
797 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
798 "Value: %s", vb_type_name);
803 ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
805 if (ret != ASN1_ERR_NOERROR)
807 length = asn1->offset - start;
810 variable.val.objid = vb_oid;
811 vb_display_string = format_var(&variable,
812 variable_oid, variable_oid_length, vb_type,
813 vb_oid_length * sizeof (subid_t));
814 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
816 "Value: %s", vb_display_string);
817 free(vb_display_string);
818 #else /* HAVE_UCD_SNMP */
819 vb_display_string = format_oid(vb_oid, vb_oid_length);
820 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
822 "Value: %s: %s", vb_type_name, vb_display_string);
823 g_free(vb_display_string);
824 #endif /* HAVE_UCD_SNMP */
829 case SNMP_NOSUCHOBJECT:
830 length = asn1->offset - start;
832 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
833 "Value: %s: no such object", vb_type_name);
837 case SNMP_NOSUCHINSTANCE:
838 length = asn1->offset - start;
840 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
841 "Value: %s: no such instance", vb_type_name);
845 case SNMP_ENDOFMIBVIEW:
846 length = asn1->offset - start;
848 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
849 "Value: %s: end of mib view", vb_type_name);
854 g_assert_not_reached();
855 return ASN1_ERR_WRONG_TYPE;
858 return ASN1_ERR_NOERROR;
862 dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
863 proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
867 guint sequence_length;
871 guint32 error_status;
875 char *pdu_type_string;
878 guint enterprise_length;
880 guint8 *agent_address;
881 guint agent_address_length;
885 guint32 specific_type;
888 guint timestamp_length;
892 guint variable_bindings_length;
895 guint variable_length;
896 subid_t *variable_oid;
897 guint variable_oid_length;
902 pdu_type_string = val_to_str(pdu_type, pdu_types,
903 "Unknown PDU type %#x");
904 if (check_col(pinfo->cinfo, COL_INFO))
905 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
906 length = asn1.offset - start;
908 proto_tree_add_text(tree, tvb, offset, length,
909 "PDU type: %s", pdu_type_string);
913 /* get the fields in the PDU preceeding the variable-bindings sequence */
917 case SNMP_MSG_GETNEXT:
918 case SNMP_MSG_RESPONSE:
920 case SNMP_MSG_GETBULK:
921 case SNMP_MSG_INFORM:
923 case SNMP_MSG_REPORT:
925 ret = asn1_uint32_decode (&asn1, &request_id, &length);
926 if (ret != ASN1_ERR_NOERROR) {
927 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
932 proto_tree_add_text(tree, tvb, offset, length,
933 "Request Id: %#x", request_id);
937 /* error status, or getbulk non-repeaters */
938 ret = asn1_uint32_decode (&asn1, &error_status, &length);
939 if (ret != ASN1_ERR_NOERROR) {
940 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
941 (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
947 if (pdu_type == SNMP_MSG_GETBULK) {
948 proto_tree_add_text(tree, tvb, offset,
949 length, "Non-repeaters: %u", error_status);
951 proto_tree_add_text(tree, tvb, offset,
952 length, "Error Status: %s",
953 val_to_str(error_status, error_statuses,
959 /* error index, or getbulk max-repetitions */
960 ret = asn1_uint32_decode (&asn1, &error_index, &length);
961 if (ret != ASN1_ERR_NOERROR) {
962 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
963 (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
969 if (pdu_type == SNMP_MSG_GETBULK) {
970 proto_tree_add_text(tree, tvb, offset,
971 length, "Max repetitions: %u", error_index);
973 proto_tree_add_text(tree, tvb, offset,
974 length, "Error Index: %u", error_index);
982 ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
984 if (ret != ASN1_ERR_NOERROR) {
985 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
986 "enterprise OID", ret);
990 oid_string = format_oid(enterprise, enterprise_length);
991 proto_tree_add_text(tree, tvb, offset, length,
992 "Enterprise: %s", oid_string);
1000 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1001 &def, &agent_address_length);
1002 if (ret != ASN1_ERR_NOERROR) {
1003 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1004 "agent address", ret);
1007 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
1008 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
1009 /* GXSNMP 0.0.15 says the latter is "needed for
1011 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1012 "agent_address", ASN1_ERR_WRONG_TYPE);
1015 if (agent_address_length != 4) {
1016 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1017 "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
1020 ret = asn1_string_value_decode (&asn1,
1021 agent_address_length, &agent_address);
1022 if (ret != ASN1_ERR_NOERROR) {
1023 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1024 "agent address", ret);
1027 length = asn1.offset - start;
1029 if (agent_address_length != 4) {
1030 proto_tree_add_text(tree, tvb, offset,
1032 "Agent address: <length is %u, not 4>",
1033 agent_address_length);
1035 proto_tree_add_text(tree, tvb, offset,
1037 "Agent address: %s",
1038 ip_to_str(agent_address));
1041 g_free(agent_address);
1044 /* generic trap type */
1045 ret = asn1_uint32_decode (&asn1, &trap_type, &length);
1046 if (ret != ASN1_ERR_NOERROR) {
1047 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1048 "generic trap type", ret);
1052 proto_tree_add_text(tree, tvb, offset, length,
1054 val_to_str(trap_type, trap_types, "Unknown (%u)"));
1058 /* specific trap type */
1059 ret = asn1_uint32_decode (&asn1, &specific_type, &length);
1060 if (ret != ASN1_ERR_NOERROR) {
1061 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1062 "specific trap type", ret);
1066 proto_tree_add_text(tree, tvb, offset, length,
1067 "Specific trap type: %u (%#x)",
1068 specific_type, specific_type);
1073 start = asn1.offset;
1074 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1075 &def, ×tamp_length);
1076 if (ret != ASN1_ERR_NOERROR) {
1077 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1081 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
1082 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
1083 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1084 "timestamp", ASN1_ERR_WRONG_TYPE);
1087 ret = asn1_uint32_value_decode(&asn1, timestamp_length,
1089 if (ret != ASN1_ERR_NOERROR) {
1090 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1094 length = asn1.offset - start;
1096 proto_tree_add_text(tree, tvb, offset, length,
1097 "Timestamp: %u", timestamp);
1103 /* variable bindings */
1104 /* get header for variable-bindings sequence */
1105 ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
1106 if (ret != ASN1_ERR_NOERROR) {
1107 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1108 "variable bindings header", ret);
1113 /* loop on variable bindings */
1115 while (variable_bindings_length > 0) {
1117 sequence_length = 0;
1120 ret = asn1_sequence_decode(&asn1, &variable_length, &length);
1121 if (ret != ASN1_ERR_NOERROR) {
1122 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1123 "variable binding header", ret);
1126 sequence_length += length;
1128 /* parse object identifier */
1129 ret = asn1_oid_decode (&asn1, &variable_oid,
1130 &variable_oid_length, &length);
1131 if (ret != ASN1_ERR_NOERROR) {
1132 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1133 "variable binding OID", ret);
1136 sequence_length += length;
1139 oid_string = format_oid(variable_oid,
1140 variable_oid_length);
1141 proto_tree_add_text(tree, tvb, offset, sequence_length,
1142 "Object identifier %d: %s", vb_index, oid_string);
1145 offset += sequence_length;
1146 variable_bindings_length -= sequence_length;
1148 /* Parse the variable's value */
1149 ret = snmp_variable_decode(tree, variable_oid,
1150 variable_oid_length, &asn1, offset, &length);
1151 if (ret != ASN1_ERR_NOERROR) {
1152 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1157 variable_bindings_length -= length;
1161 static const value_string qos_vals[] = {
1162 { 0x0, "No authentication or privacy" },
1163 { 0x1, "Authentication, no privacy" },
1164 { 0x2, "Authentication and privacy" },
1165 { 0x3, "Authentication and privacy" },
1170 dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
1171 guchar *parameters, int parameters_length)
1174 proto_tree *parameters_tree;
1175 proto_tree *qos_tree;
1180 item = proto_tree_add_text(tree, tvb, offset, length,
1182 parameters_tree = proto_item_add_subtree(item, ett_parameters);
1183 offset += length - parameters_length;
1185 if (parameters_length < 1)
1187 model = *parameters;
1188 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1189 "model: %u", model);
1192 parameters_length -= 1;
1194 /* Unknown model. */
1195 proto_tree_add_text(parameters_tree, tvb, offset,
1196 parameters_length, "parameters: %s",
1197 bytes_to_str(parameters, parameters_length));
1201 if (parameters_length < 1)
1204 item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
1206 qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
1207 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1208 decode_boolean_bitfield(qos, 0x04,
1209 8, "Generation of report PDU allowed",
1210 "Generation of report PDU not allowed"));
1211 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1212 decode_enumerated_bitfield(qos, 0x03,
1213 8, qos_vals, "%s"));
1216 parameters_length -= 1;
1218 if (parameters_length < 12)
1220 proto_tree_add_text(parameters_tree, tvb, offset, 12,
1221 "agentID: %s", bytes_to_str(parameters, 12));
1224 parameters_length -= 12;
1226 if (parameters_length < 4)
1228 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1229 "agentBoots: %u", pntohl(parameters));
1232 parameters_length -= 4;
1234 if (parameters_length < 4)
1236 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1237 "agentTime: %u", pntohl(parameters));
1240 parameters_length -= 4;
1242 if (parameters_length < 2)
1244 proto_tree_add_text(parameters_tree, tvb, offset, 2,
1245 "maxSize: %u", pntohs(parameters));
1248 parameters_length -= 2;
1250 if (parameters_length < 1)
1253 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1254 "userLen: %u", len);
1257 parameters_length -= 1;
1259 if (parameters_length < len)
1261 proto_tree_add_text(parameters_tree, tvb, offset, len,
1262 "userName: %.*s", len, parameters);
1265 parameters_length -= len;
1267 if (parameters_length < 1)
1270 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1271 "authLen: %u", len);
1274 parameters_length -= 1;
1276 if (parameters_length < len)
1278 proto_tree_add_text(parameters_tree, tvb, offset, len,
1279 "authDigest: %s", bytes_to_str(parameters, len));
1282 parameters_length -= len;
1284 if (parameters_length < 1)
1286 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
1287 "contextSelector: %s", bytes_to_str(parameters, parameters_length));
1291 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1292 proto_tree *tree, char *proto_name, int proto, gint ett)
1299 guint message_length;
1300 guint global_length;
1306 guint32 engineboots;
1319 int msgflags_length;
1320 int community_length;
1322 int cengineid_length;
1324 int cryptpdu_length;
1325 int aengineid_length;
1326 int username_length;
1333 proto_tree *snmp_tree = NULL;
1334 proto_tree *global_tree = NULL;
1335 proto_tree *flags_tree = NULL;
1336 proto_tree *secur_tree = NULL;
1337 proto_item *item = NULL;
1339 guint cls, con, tag;
1341 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1342 col_add_str(pinfo->cinfo, COL_PROTOCOL, proto_name);
1345 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
1346 snmp_tree = proto_item_add_subtree(item, ett);
1349 /* NOTE: we have to parse the message piece by piece, since the
1350 * capture length may be less than the message length: a 'global'
1351 * parsing is likely to fail.
1353 /* parse the SNMP header */
1354 asn1_open(&asn1, tvb, offset);
1355 ret = asn1_sequence_decode(&asn1, &message_length, &length);
1356 if (ret != ASN1_ERR_NOERROR) {
1357 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1358 "message header", ret);
1363 ret = asn1_uint32_decode (&asn1, &version, &length);
1364 if (ret != ASN1_ERR_NOERROR) {
1365 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1366 "version number", ret);
1370 proto_tree_add_text(snmp_tree, tvb, offset, length,
1372 val_to_str(version, versions, "Unknown version %#x"));
1378 case SNMP_VERSION_1:
1379 case SNMP_VERSION_2c:
1380 ret = asn1_octet_string_decode (&asn1, &community,
1381 &community_length, &length);
1382 if (ret != ASN1_ERR_NOERROR) {
1383 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1388 proto_tree_add_text(snmp_tree, tvb, offset, length,
1389 "Community: %.*s", community_length,
1390 SAFE_STRING(community));
1395 case SNMP_VERSION_2u:
1396 ret = asn1_octet_string_decode (&asn1, &community,
1397 &community_length, &length);
1399 dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
1400 community, community_length);
1405 case SNMP_VERSION_3:
1406 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1407 if (ret != ASN1_ERR_NOERROR) {
1408 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1409 "message global header", ret);
1413 item = proto_tree_add_text(snmp_tree, tvb, offset,
1414 global_length + length, "Message Global Header");
1415 global_tree = proto_item_add_subtree(item, ett_global);
1416 proto_tree_add_text(global_tree, tvb, offset,
1418 "Message Global Header Length: %d", global_length);
1421 ret = asn1_uint32_decode (&asn1, &msgid, &length);
1422 if (ret != ASN1_ERR_NOERROR) {
1423 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1428 proto_tree_add_text(global_tree, tvb, offset,
1429 length, "Message ID: %d", msgid);
1432 ret = asn1_uint32_decode (&asn1, &msgmax, &length);
1433 if (ret != ASN1_ERR_NOERROR) {
1434 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1435 "message max size", ret);
1439 proto_tree_add_text(global_tree, tvb, offset,
1440 length, "Message Max Size: %d", msgmax);
1443 ret = asn1_octet_string_decode (&asn1, &msgflags,
1444 &msgflags_length, &length);
1445 if (ret != ASN1_ERR_NOERROR) {
1446 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1447 "message flags", ret);
1450 if (msgflags_length != 1) {
1451 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1452 "message flags wrong length", ret);
1457 item = proto_tree_add_uint_format(global_tree,
1458 hf_snmpv3_flags, tvb, offset, length,
1459 msgflags[0], "Flags: 0x%02x", msgflags[0]);
1460 flags_tree = proto_item_add_subtree(item, ett_flags);
1461 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
1462 tvb, offset, length, msgflags[0]);
1463 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
1464 tvb, offset, length, msgflags[0]);
1465 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
1466 tvb, offset, length, msgflags[0]);
1468 encrypted = msgflags[0] & TH_CRYPT;
1471 ret = asn1_uint32_decode (&asn1, &msgsec, &length);
1472 if (ret != ASN1_ERR_NOERROR) {
1473 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1474 "message security model", ret);
1478 proto_tree_add_text(global_tree, tvb, offset,
1479 length, "Message Security Model: %s",
1480 val_to_str(msgsec, sec_models,
1481 "Unknown model %#x"));
1486 start = asn1.offset;
1487 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1488 &def, &secparm_length);
1489 length = asn1.offset - start;
1490 if (cls != ASN1_UNI && con != ASN1_PRI &&
1492 dissect_snmp_parse_error(tvb, offset, pinfo,
1493 snmp_tree, "Message Security Parameters",
1494 ASN1_ERR_WRONG_TYPE);
1498 item = proto_tree_add_text(snmp_tree, tvb,
1499 offset, secparm_length + length,
1500 "Message Security Parameters");
1501 secur_tree = proto_item_add_subtree(item,
1503 proto_tree_add_text(secur_tree, tvb, offset,
1505 "Message Security Parameters Length: %d",
1509 ret = asn1_sequence_decode(&asn1, &secparm_length,
1511 if (ret != ASN1_ERR_NOERROR) {
1512 dissect_snmp_parse_error(tvb, offset, pinfo,
1513 snmp_tree, "USM sequence header", ret);
1517 ret = asn1_octet_string_decode (&asn1, &aengineid,
1518 &aengineid_length, &length);
1519 if (ret != ASN1_ERR_NOERROR) {
1520 dissect_snmp_parse_error(tvb, offset, pinfo,
1521 snmp_tree, "authoritative engine id", ret);
1525 proto_tree_add_text(secur_tree, tvb, offset,
1526 length, "Authoritative Engine ID: %s",
1527 bytes_to_str(aengineid, aengineid_length));
1531 ret = asn1_uint32_decode (&asn1, &engineboots, &length);
1532 if (ret != ASN1_ERR_NOERROR) {
1533 dissect_snmp_parse_error(tvb, offset, pinfo,
1534 snmp_tree, "engine boots", ret);
1538 proto_tree_add_text(secur_tree, tvb,
1539 offset, length, "Engine Boots: %d",
1543 ret = asn1_uint32_decode (&asn1, &enginetime, &length);
1544 if (ret != ASN1_ERR_NOERROR) {
1545 dissect_snmp_parse_error(tvb, offset, pinfo,
1546 snmp_tree, "engine time", ret);
1550 proto_tree_add_text(secur_tree, tvb,
1551 offset, length, "Engine Time: %d",
1555 ret = asn1_octet_string_decode (&asn1, &username,
1556 &username_length, &length);
1557 if (ret != ASN1_ERR_NOERROR) {
1558 dissect_snmp_parse_error(tvb, offset, pinfo,
1559 snmp_tree, "user name", ret);
1563 proto_tree_add_text(secur_tree, tvb, offset,
1564 length, "User Name: %.*s",
1566 SAFE_STRING(username));
1570 ret = asn1_octet_string_decode (&asn1, &authpar,
1571 &authpar_length, &length);
1572 if (ret != ASN1_ERR_NOERROR) {
1573 dissect_snmp_parse_error(tvb, offset, pinfo,
1574 snmp_tree, "authentication parameter", ret);
1578 proto_tree_add_text(secur_tree, tvb, offset,
1579 length, "Authentication Parameter: %s",
1580 bytes_to_str(authpar, authpar_length));
1584 ret = asn1_octet_string_decode (&asn1, &privpar,
1585 &privpar_length, &length);
1586 if (ret != ASN1_ERR_NOERROR) {
1587 dissect_snmp_parse_error(tvb, offset, pinfo,
1588 snmp_tree, "privacy parameter", ret);
1592 proto_tree_add_text(secur_tree, tvb, offset,
1593 length, "Privacy Parameter: %s",
1594 bytes_to_str(privpar, privpar_length));
1600 ret = asn1_octet_string_decode (&asn1,
1601 &secparm, &secparm_length, &length);
1602 if (ret != ASN1_ERR_NOERROR) {
1603 dissect_snmp_parse_error(tvb, offset, pinfo,
1604 snmp_tree, "Message Security Parameters",
1609 proto_tree_add_text(snmp_tree, tvb, offset,
1611 "Message Security Parameters Data"
1612 " (%d bytes)", secparm_length);
1618 /* PDU starts here */
1620 ret = asn1_octet_string_decode (&asn1, &cryptpdu,
1621 &cryptpdu_length, &length);
1622 if (ret != ASN1_ERR_NOERROR) {
1623 dissect_snmp_parse_error(tvb, offset, pinfo,
1624 snmp_tree, "encrypted PDU header", ret);
1627 proto_tree_add_text(snmp_tree, tvb, offset, length,
1628 "Encrypted PDU (%d bytes)", length);
1630 if (check_col(pinfo->cinfo, COL_INFO))
1631 col_set_str(pinfo->cinfo, COL_INFO, "Encrypted PDU");
1634 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1635 if (ret != ASN1_ERR_NOERROR) {
1636 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1641 ret = asn1_octet_string_decode (&asn1, &cengineid,
1642 &cengineid_length, &length);
1643 if (ret != ASN1_ERR_NOERROR) {
1644 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1645 "context engine id", ret);
1649 proto_tree_add_text(snmp_tree, tvb, offset, length,
1650 "Context Engine ID: %s",
1651 bytes_to_str(cengineid, cengineid_length));
1655 ret = asn1_octet_string_decode (&asn1, &cname,
1656 &cname_length, &length);
1657 if (ret != ASN1_ERR_NOERROR) {
1658 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1659 "context name", ret);
1663 proto_tree_add_text(snmp_tree, tvb, offset, length,
1664 "Context Name: %.*s", cname_length,
1665 SAFE_STRING(cname));
1671 dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
1672 "PDU for unknown version of SNMP");
1676 start = asn1.offset;
1677 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1679 if (ret != ASN1_ERR_NOERROR) {
1680 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1684 if (cls != ASN1_CTX || con != ASN1_CON) {
1685 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1686 "PDU type", ASN1_ERR_WRONG_TYPE);
1689 dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
1693 dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1694 proto_tree *tree, int proto, gint ett)
1702 char *pdu_type_string;
1712 int password_length;
1714 guchar *application;
1715 int application_length;
1722 proto_tree *smux_tree = NULL;
1723 proto_item *item = NULL;
1727 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1728 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
1731 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
1732 smux_tree = proto_item_add_subtree(item, ett);
1735 /* NOTE: we have to parse the message piece by piece, since the
1736 * capture length may be less than the message length: a 'global'
1737 * parsing is likely to fail.
1739 /* parse the SNMP header */
1740 asn1_open(&asn1, tvb, offset);
1741 start = asn1.offset;
1742 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1744 if (ret != ASN1_ERR_NOERROR) {
1745 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1750 /* Dissect SMUX here */
1751 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
1752 pdu_type_string = val_to_str(pdu_type, smux_types,
1753 "Unknown PDU type %#x");
1754 if (check_col(pinfo->cinfo, COL_INFO))
1755 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1756 length = asn1.offset - start;
1758 proto_tree_add_text(smux_tree, tvb, offset, length,
1759 "PDU type: %s", pdu_type_string);
1762 ret = asn1_uint32_decode (&asn1, &version, &length);
1763 if (ret != ASN1_ERR_NOERROR) {
1764 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1769 proto_tree_add_text(smux_tree, tvb, offset, length,
1770 "Version: %d", version);
1774 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1775 if (ret != ASN1_ERR_NOERROR) {
1776 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1777 "registration OID", ret);
1781 oid_string = format_oid(regid, regid_length);
1782 proto_tree_add_text(smux_tree, tvb, offset, length,
1783 "Registration: %s", oid_string);
1789 ret = asn1_octet_string_decode (&asn1, &application,
1790 &application_length, &length);
1791 if (ret != ASN1_ERR_NOERROR) {
1792 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1793 "application", ret);
1797 proto_tree_add_text(smux_tree, tvb, offset, length,
1798 "Application: %.*s", application_length,
1799 SAFE_STRING(application));
1801 g_free(application);
1804 ret = asn1_octet_string_decode (&asn1, &password,
1805 &password_length, &length);
1806 if (ret != ASN1_ERR_NOERROR) {
1807 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1812 proto_tree_add_text(smux_tree, tvb, offset, length,
1813 "Password: %.*s", password_length,
1814 SAFE_STRING(password));
1820 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
1821 pdu_type_string = val_to_str(pdu_type, smux_types,
1822 "Unknown PDU type %#x");
1823 if (check_col(pinfo->cinfo, COL_INFO))
1824 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1825 length = asn1.offset - start;
1827 proto_tree_add_text(smux_tree, tvb, offset, length,
1828 "PDU type: %s", pdu_type_string);
1831 ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
1832 if (ret != ASN1_ERR_NOERROR) {
1833 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1838 proto_tree_add_text(smux_tree, tvb, offset,
1839 pdu_length, "Cause: %s",
1840 val_to_str(cause, smux_close,
1841 "Unknown cause %#x"));
1843 offset += pdu_length;
1846 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
1847 pdu_type_string = val_to_str(pdu_type, smux_types,
1848 "Unknown PDU type %#x");
1849 if (check_col(pinfo->cinfo, COL_INFO))
1850 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1851 length = asn1.offset - start;
1853 proto_tree_add_text(smux_tree, tvb, offset, length,
1854 "PDU type: %s", pdu_type_string);
1857 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1858 if (ret != ASN1_ERR_NOERROR) {
1859 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1860 "registration subtree", ret);
1864 oid_string = format_oid(regid, regid_length);
1865 proto_tree_add_text(smux_tree, tvb, offset, length,
1866 "Registration: %s", oid_string);
1872 ret = asn1_uint32_decode (&asn1, &priority, &length);
1873 if (ret != ASN1_ERR_NOERROR) {
1874 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1879 proto_tree_add_text(smux_tree, tvb, offset, length,
1880 "Priority: %d", priority);
1884 ret = asn1_uint32_decode (&asn1, &operation, &length);
1885 if (ret != ASN1_ERR_NOERROR) {
1886 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1891 proto_tree_add_text(smux_tree, tvb, offset, length,
1893 val_to_str(operation, smux_rreq,
1894 "Unknown operation %#x"));
1899 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
1900 pdu_type_string = val_to_str(pdu_type, smux_types,
1901 "Unknown PDU type %#x");
1902 if (check_col(pinfo->cinfo, COL_INFO))
1903 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1904 length = asn1.offset - start;
1906 proto_tree_add_text(smux_tree, tvb, offset, length,
1907 "PDU type: %s", pdu_type_string);
1910 ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
1911 if (ret != ASN1_ERR_NOERROR) {
1912 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1917 proto_tree_add_text(smux_tree, tvb, offset,
1919 val_to_str(priority, smux_prio,
1922 offset += pdu_length;
1925 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
1926 pdu_type_string = val_to_str(pdu_type, smux_types,
1927 "Unknown PDU type %#x");
1928 if (check_col(pinfo->cinfo, COL_INFO))
1929 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1930 length = asn1.offset - start;
1932 proto_tree_add_text(smux_tree, tvb, offset, length,
1933 "PDU type: %s", pdu_type_string);
1936 ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
1937 if (ret != ASN1_ERR_NOERROR) {
1938 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1943 proto_tree_add_text(smux_tree, tvb, offset,
1945 val_to_str(commit, smux_sout,
1946 "Unknown SOUT Value: %#x"));
1948 offset += pdu_length;
1951 if (cls != ASN1_CTX || con != ASN1_CON) {
1952 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1953 "PDU type", ASN1_ERR_WRONG_TYPE);
1956 dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
1960 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1962 conversation_t *conversation;
1965 * The first SNMP packet goes to the SNMP port; the second one
1966 * may come from some *other* port, but goes back to the same
1967 * IP address and port as the ones from which the first packet
1968 * came; all subsequent packets presumably go between those two
1969 * IP addresses and ports.
1971 * If this packet went to the SNMP port, we check to see if
1972 * there's already a conversation with one address/port pair
1973 * matching the source IP address and port of this packet,
1974 * the other address matching the destination IP address of this
1975 * packet, and any destination port.
1977 * If not, we create one, with its address 1/port 1 pair being
1978 * the source address/port of this packet, its address 2 being
1979 * the destination address of this packet, and its port 2 being
1980 * wildcarded, and give it the SNMP dissector as a dissector.
1982 if (pinfo->destport == UDP_PORT_SNMP) {
1983 conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
1984 pinfo->srcport, 0, NO_PORT_B);
1985 if (conversation == NULL) {
1986 conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
1987 pinfo->srcport, 0, NO_PORT2);
1988 conversation_set_dissector(conversation, snmp_handle);
1992 dissect_snmp_pdu(tvb, 0, pinfo, tree, "SNMP", proto_snmp, ett_snmp);
1996 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1998 dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
2002 proto_register_snmp(void)
2004 static hf_register_info hf[] = {
2006 { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
2008 { &hf_snmpv3_flags_auth,
2009 { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
2010 TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
2011 { &hf_snmpv3_flags_crypt,
2012 { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
2013 TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
2014 { &hf_snmpv3_flags_report,
2015 { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
2016 TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
2018 static gint *ett[] = {
2022 &ett_parameters_qos,
2028 #ifdef HAVE_UCD_SNMP
2030 * Suppress warnings about unknown tokens - we aren't initializing
2031 * UCD SNMP in its entirety, we're just initializing the
2032 * MIB-handling part because that's all we're using, which
2033 * means that entries in the configuration file for other
2034 * pars of the library will not be handled, and we don't want
2035 * the config file reading code to whine about that.
2037 ds_set_boolean(DS_LIBRARY_ID, DS_LIB_NO_TOKEN_WARNINGS, TRUE);
2038 ds_set_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY, 2);
2039 register_mib_handlers();
2040 read_premib_configs();
2043 #endif /* HAVE_UCD_SNMP */
2044 proto_snmp = proto_register_protocol("Simple Network Management Protocol",
2046 proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2048 proto_register_field_array(proto_snmp, hf, array_length(hf));
2049 proto_register_subtree_array(ett, array_length(ett));
2050 snmp_handle = create_dissector_handle(dissect_snmp, proto_snmp);
2054 proto_reg_handoff_snmp(void)
2056 dissector_handle_t smux_handle;
2058 dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
2059 dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
2060 smux_handle = create_dissector_handle(dissect_smux, proto_smux);
2061 dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);
2062 dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
2063 dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
2064 dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
2065 data_handle = find_dissector("data");