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.102 2002/11/11 17:34:22 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>
54 #include "packet-ipx.h"
59 # include <net-snmp/net-snmp-config.h>
60 # include <net-snmp/mib_api.h>
61 # include <net-snmp/library/default_store.h>
62 # include <net-snmp/config_api.h>
63 #else /* HAVE_NET_SNMP */
64 # include <ucd-snmp/ucd-snmp-config.h>
65 # include <ucd-snmp/asn1.h>
66 # include <ucd-snmp/snmp_api.h>
67 # include <ucd-snmp/snmp_impl.h>
68 # include <ucd-snmp/mib.h>
69 # include <ucd-snmp/default_store.h>
70 # include <ucd-snmp/read_config.h>
71 # include <ucd-snmp/tools.h>
72 # define netsnmp_ds_set_boolean ds_set_boolean
73 # define netsnmp_ds_set_int ds_set_int
74 # define NETSNMP_DS_LIBRARY_ID DS_LIBRARY_ID
75 # define NETSNMP_DS_LIB_NO_TOKEN_WARNINGS DS_LIB_NO_TOKEN_WARNINGS
76 # define NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY DS_LIB_PRINT_SUFFIX_ONLY
77 #endif /* HAVE_NET_SNMP */
80 # include <epan/filesystem.h>
84 * Define values "sprint_realloc_value()" expects.
86 # define VALTYPE_INTEGER ASN_INTEGER
87 # define VALTYPE_COUNTER ASN_COUNTER
88 # define VALTYPE_GAUGE ASN_GAUGE
89 # define VALTYPE_TIMETICKS ASN_TIMETICKS
90 # define VALTYPE_STRING ASN_OCTET_STR
91 # define VALTYPE_IPADDR ASN_IPADDRESS
92 # define VALTYPE_OPAQUE ASN_OPAQUE
93 # define VALTYPE_NSAP ASN_NSAP
94 # define VALTYPE_OBJECTID ASN_OBJECT_ID
95 # define VALTYPE_BITSTR ASN_BIT_STR
96 # define VALTYPE_COUNTER64 ASN_COUNTER64
98 #endif /* HAVE_SOME_SNMP */
102 #include "packet-snmp.h"
103 #include "format-oid.h"
105 /* Null string of type "guchar[]". */
106 static const guchar nullstring[] = "";
108 /* Take a pointer that may be null and return a pointer that's not null
109 by turning null pointers into pointers to the above null string. */
110 #define SAFE_STRING(s) (((s) != NULL) ? (s) : nullstring)
112 static int proto_snmp = -1;
113 static int proto_smux = -1;
115 static gint ett_snmp = -1;
116 static gint ett_smux = -1;
117 static gint ett_parameters = -1;
118 static gint ett_parameters_qos = -1;
119 static gint ett_global = -1;
120 static gint ett_flags = -1;
121 static gint ett_secur = -1;
123 static int hf_snmpv3_flags = -1;
124 static int hf_snmpv3_flags_auth = -1;
125 static int hf_snmpv3_flags_crypt = -1;
126 static int hf_snmpv3_flags_report = -1;
128 static dissector_handle_t snmp_handle;
129 static dissector_handle_t data_handle;
132 #define TH_CRYPT 0x02
133 #define TH_REPORT 0x04
135 #define UDP_PORT_SNMP 161
136 #define UDP_PORT_SNMP_TRAP 162
137 #define TCP_PORT_SMUX 199
139 /* Protocol version numbers */
140 #define SNMP_VERSION_1 0
141 #define SNMP_VERSION_2c 1
142 #define SNMP_VERSION_2u 2
143 #define SNMP_VERSION_3 3
145 static const value_string versions[] = {
146 { SNMP_VERSION_1, "1" },
147 { SNMP_VERSION_2c, "2C" },
148 { SNMP_VERSION_2u, "2U" },
149 { SNMP_VERSION_3, "3" },
154 #define SNMP_MSG_GET 0
155 #define SNMP_MSG_GETNEXT 1
156 #define SNMP_MSG_RESPONSE 2
157 #define SNMP_MSG_SET 3
158 #define SNMP_MSG_TRAP 4
160 #define SNMP_MSG_GETBULK 5
161 #define SNMP_MSG_INFORM 6
162 #define SNMP_MSG_TRAP2 7
163 #define SNMP_MSG_REPORT 8
165 static const value_string pdu_types[] = {
166 { SNMP_MSG_GET, "GET" },
167 { SNMP_MSG_GETNEXT, "GET-NEXT" },
168 { SNMP_MSG_SET, "SET" },
169 { SNMP_MSG_RESPONSE, "RESPONSE" },
170 { SNMP_MSG_TRAP, "TRAP-V1" },
171 { SNMP_MSG_GETBULK, "GETBULK" },
172 { SNMP_MSG_INFORM, "INFORM" },
173 { SNMP_MSG_TRAP2, "TRAP-V2" },
174 { SNMP_MSG_REPORT, "REPORT" },
179 #define SMUX_MSG_OPEN 0
180 #define SMUX_MSG_CLOSE 1
181 #define SMUX_MSG_RREQ 2
182 #define SMUX_MSG_RRSP 3
183 #define SMUX_MSG_SOUT 4
185 static const value_string smux_types[] = {
186 { SMUX_MSG_OPEN, "Open" },
187 { SMUX_MSG_CLOSE, "Close" },
188 { SMUX_MSG_RREQ, "Registration Request" },
189 { SMUX_MSG_RRSP, "Registration Response" },
190 { SMUX_MSG_SOUT, "Commit Or Rollback" },
194 /* SMUX Closing causes */
195 #define SMUX_CLOSE_DOWN 0
196 #define SMUX_CLOSE_VERSION 1
197 #define SMUX_CLOSE_PACKET 2
198 #define SMUX_CLOSE_PROTOCOL 3
199 #define SMUX_CLOSE_INTERNAL 4
200 #define SMUX_CLOSE_NOAUTH 5
202 static const value_string smux_close[] = {
203 { SMUX_CLOSE_DOWN, "Going down" },
204 { SMUX_CLOSE_VERSION, "Unsupported Version" },
205 { SMUX_CLOSE_PACKET, "Packet Format Error" },
206 { SMUX_CLOSE_PROTOCOL, "Protocol Error" },
207 { SMUX_CLOSE_INTERNAL, "Internal Error" },
208 { SMUX_CLOSE_NOAUTH, "Unauthorized" },
212 /* SMUX Request codes */
213 #define SMUX_RREQ_DELETE 0
214 #define SMUX_RREQ_READONLY 1
215 #define SMUX_RREQ_READWRITE 2
217 static const value_string smux_rreq[] = {
218 { SMUX_RREQ_DELETE, "Delete" },
219 { SMUX_RREQ_READONLY, "Read Only" },
220 { SMUX_RREQ_READWRITE, "Read Write" },
224 static const value_string smux_prio[] = {
229 /* SMUX SOut codes */
230 #define SMUX_SOUT_COMMIT 0
231 #define SMUX_SOUT_ROLLBACK 1
233 static const value_string smux_sout[] = {
234 { SMUX_SOUT_COMMIT, "Commit" },
235 { SMUX_SOUT_ROLLBACK, "Rollback" },
239 /* Error status values */
240 #define SNMP_ERR_NOERROR 0
241 #define SNMP_ERR_TOOBIG 1
242 #define SNMP_ERR_NOSUCHNAME 2
243 #define SNMP_ERR_BADVALUE 3
244 #define SNMP_ERR_READONLY 4
245 #define SNMP_ERR_GENERROR 5
247 #define SNMP_ERR_NOACCESS 6
248 #define SNMP_ERR_WRONGTYPE 7
249 #define SNMP_ERR_WRONGLENGTH 8
250 #define SNMP_ERR_WRONGENCODING 9
251 #define SNMP_ERR_WRONGVALUE 10
252 #define SNMP_ERR_NOCREATION 11
253 #define SNMP_ERR_INCONSISTENTVALUE 12
254 #define SNMP_ERR_RESOURCEUNAVAILABLE 13
255 #define SNMP_ERR_COMMITFAILED 14
256 #define SNMP_ERR_UNDOFAILED 15
257 #define SNMP_ERR_AUTHORIZATIONERROR 16
258 #define SNMP_ERR_NOTWRITABLE 17
259 #define SNMP_ERR_INCONSISTENTNAME 18
261 static const value_string error_statuses[] = {
262 { SNMP_ERR_NOERROR, "NO ERROR" },
263 { SNMP_ERR_TOOBIG, "TOOBIG" },
264 { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" },
265 { SNMP_ERR_BADVALUE, "BAD VALUE" },
266 { SNMP_ERR_READONLY, "READ ONLY" },
267 { SNMP_ERR_GENERROR, "GENERIC ERROR" },
268 { SNMP_ERR_NOACCESS, "NO ACCESS" },
269 { SNMP_ERR_WRONGTYPE, "WRONG TYPE" },
270 { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" },
271 { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" },
272 { SNMP_ERR_WRONGVALUE, "WRONG VALUE" },
273 { SNMP_ERR_NOCREATION, "NO CREATION" },
274 { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" },
275 { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" },
276 { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" },
277 { SNMP_ERR_UNDOFAILED, "UNDO FAILED" },
278 { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" },
279 { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" },
280 { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" },
284 /* General SNMP V1 Traps */
286 #define SNMP_TRAP_COLDSTART 0
287 #define SNMP_TRAP_WARMSTART 1
288 #define SNMP_TRAP_LINKDOWN 2
289 #define SNMP_TRAP_LINKUP 3
290 #define SNMP_TRAP_AUTHFAIL 4
291 #define SNMP_TRAP_EGPNEIGHBORLOSS 5
292 #define SNMP_TRAP_ENTERPRISESPECIFIC 6
294 static const value_string trap_types[] = {
295 { SNMP_TRAP_COLDSTART, "COLD START" },
296 { SNMP_TRAP_WARMSTART, "WARM START" },
297 { SNMP_TRAP_LINKDOWN, "LINK DOWN" },
298 { SNMP_TRAP_LINKUP, "LINK UP" },
299 { SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
300 { SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
301 { SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
305 /* Security Models */
307 #define SNMP_SEC_ANY 0
308 #define SNMP_SEC_V1 1
309 #define SNMP_SEC_V2C 2
310 #define SNMP_SEC_USM 3
312 static const value_string sec_models[] = {
313 { SNMP_SEC_ANY, "Any" },
314 { SNMP_SEC_V1, "V1" },
315 { SNMP_SEC_V2C, "V2C" },
316 { SNMP_SEC_USM, "USM" },
322 #define SNMP_IPA 0 /* IP Address */
323 #define SNMP_CNT 1 /* Counter (Counter32) */
324 #define SNMP_GGE 2 /* Gauge (Gauge32) */
325 #define SNMP_TIT 3 /* TimeTicks */
326 #define SNMP_OPQ 4 /* Opaque */
327 #define SNMP_NSP 5 /* NsapAddress */
328 #define SNMP_C64 6 /* Counter64 */
329 #define SNMP_U32 7 /* Uinteger32 */
338 #define SNMP_INTEGER 1 /* l */
339 #define SNMP_OCTETSTR 2 /* c */
340 #define SNMP_DISPLAYSTR 2 /* c */
341 #define SNMP_OBJECTID 3 /* ul */
342 #define SNMP_IPADDR 4 /* uc */
343 #define SNMP_COUNTER 5 /* ul */
344 #define SNMP_GAUGE 6 /* ul */
345 #define SNMP_TIMETICKS 7 /* ul */
346 #define SNMP_OPAQUE 8 /* c */
348 /* additional SNMPv2 Types */
350 #define SNMP_UINTEGER 5 /* ul */
351 #define SNMP_BITSTR 9 /* uc */
352 #define SNMP_NSAP 10 /* uc */
353 #define SNMP_COUNTER64 11 /* ul */
354 #define SNMP_NOSUCHOBJECT 12
355 #define SNMP_NOSUCHINSTANCE 13
356 #define SNMP_ENDOFMIBVIEW 14
358 typedef struct _SNMP_CNV SNMP_CNV;
368 static SNMP_CNV SnmpCnv [] =
370 {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"},
371 {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"},
372 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"},
373 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"},
374 {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"},
375 {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */
376 {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */
377 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"},
378 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"},
380 /* SNMPv2 data types and errors */
382 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"},
383 {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"},
384 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"},
385 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"},
386 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"},
391 * NAME: g_snmp_tag_cls2syntax
392 * SYNOPSIS: gboolean g_snmp_tag_cls2syntax
398 * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name.
399 * See SnmpCnv for conversion.
400 * RETURNS: name on success, NULL on failure
404 snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
409 while (cnv->syntax != -1)
411 if (cnv->tag == tag && cnv->class == cls)
413 *syntax = cnv->syntax;
422 dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
423 proto_tree *tree, const char *field_name, int ret)
427 errstr = asn1_err_to_str(ret);
429 if (check_col(pinfo->cinfo, COL_INFO)) {
430 col_add_fstr(pinfo->cinfo, COL_INFO,
431 "ERROR: Couldn't parse %s: %s", field_name, errstr);
434 proto_tree_add_text(tree, tvb, offset, 0,
435 "ERROR: Couldn't parse %s: %s", field_name, errstr);
436 call_dissector(data_handle,
437 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
442 dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
443 proto_tree *tree, const char *message)
445 if (check_col(pinfo->cinfo, COL_INFO))
446 col_add_str(pinfo->cinfo, COL_INFO, message);
449 proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
450 call_dissector(data_handle,
451 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
456 format_oid(subid_t *oid, guint oid_length)
463 #ifdef HAVE_SOME_SNMP
465 size_t oid_string_len;
469 result_len = oid_length * 22;
471 #ifdef HAVE_SOME_SNMP
473 * Get the decoded form of the OID, and add its length to the
474 * length of the result string.
476 * XXX - check for "malloc" and "sprint_realloc_objid()" failure.
478 oid_string_len = 256;
479 oid_string = malloc(oid_string_len);
482 sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
484 result_len += strlen(oid_string) + 3;
487 result = g_malloc(result_len + 1);
489 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
491 for (i = 1; i < oid_length;i++) {
492 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
496 #ifdef HAVE_SOME_SNMP
498 * Append the decoded form of the OID.
500 sprintf(buf, " (%s)", oid_string);
507 #ifdef HAVE_SOME_SNMP
509 check_var_length(guint vb_length, guint required_length)
512 static const char badlen_fmt[] = "Length is %u, should be %u";
514 if (vb_length != required_length) {
515 /* Enough room for the largest "Length is XXX,
516 should be XXX" message - 10 digits for each
518 buf = malloc(sizeof badlen_fmt + 10 + 10);
519 sprintf(buf, badlen_fmt, vb_length, required_length);
522 return NULL; /* length is OK */
526 format_var(struct variable_list *variable, subid_t *variable_oid,
527 guint variable_oid_length, gushort vb_type, guint val_len)
536 /* Length has to be 4 bytes. */
537 buf = check_var_length(val_len, 4);
539 return buf; /* it's not 4 bytes */
543 /* Length has to be 8 bytes. */
544 buf = check_var_length(val_len, 8);
546 return buf; /* it's not 8 bytes */
553 variable->next_variable = NULL;
554 variable->name = variable_oid;
555 variable->name_length = variable_oid_length;
559 variable->type = VALTYPE_INTEGER;
563 variable->type = VALTYPE_COUNTER;
567 variable->type = VALTYPE_GAUGE;
571 variable->type = VALTYPE_TIMETICKS;
575 variable->type = VALTYPE_STRING;
579 variable->type = VALTYPE_IPADDR;
583 variable->type = VALTYPE_OPAQUE;
587 variable->type = VALTYPE_NSAP;
591 variable->type = VALTYPE_OBJECTID;
595 variable->type = VALTYPE_BITSTR;
599 variable->type = VALTYPE_COUNTER64;
602 variable->val_len = val_len;
605 * XXX - check for "malloc" and "sprint_realloc_objid()" failure.
608 buf = malloc(buf_len);
611 sprint_realloc_value(&buf, &buf_len, &out_len, 1, variable_oid,
612 variable_oid_length, variable);
618 snmp_variable_decode(proto_tree *snmp_tree,
619 subid_t *variable_oid
620 #ifndef HAVE_SOME_SNMP
624 guint variable_oid_length
625 #ifndef HAVE_SOME_SNMP
629 ASN1_SCK *asn1, int offset, guint *lengthp)
640 gint32 vb_integer_value;
641 guint32 vb_uinteger_value;
643 guint8 *vb_octet_string;
648 gchar *vb_display_string;
650 #ifdef HAVE_SOME_SNMP
651 struct variable_list variable;
653 #else /* HAVE_SOME_SNMP */
657 #endif /* HAVE_SOME_SNMP */
659 /* parse the type of the object */
660 start = asn1->offset;
661 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
662 if (ret != ASN1_ERR_NOERROR)
665 return ASN1_ERR_LENGTH_NOT_DEFINITE;
667 /* Convert the class, constructed flag, and tag to a type. */
668 vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
669 if (vb_type_name == NULL) {
672 * Dissect the value as an opaque string of octets.
674 vb_type_name = "unsupported type";
675 vb_type = SNMP_OPAQUE;
678 /* parse the value */
682 ret = asn1_int32_value_decode(asn1, vb_length,
684 if (ret != ASN1_ERR_NOERROR)
686 length = asn1->offset - start;
688 #ifdef HAVE_SOME_SNMP
689 value = vb_integer_value;
690 variable.val.integer = &value;
691 vb_display_string = format_var(&variable,
692 variable_oid, variable_oid_length, vb_type,
694 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
696 "Value: %s", vb_display_string);
697 free(vb_display_string);
698 #else /* HAVE_SOME_SNMP */
699 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
701 "Value: %s: %d (%#x)", vb_type_name,
702 vb_integer_value, vb_integer_value);
703 #endif /* HAVE_SOME_SNMP */
710 ret = asn1_uint32_value_decode(asn1, vb_length,
712 if (ret != ASN1_ERR_NOERROR)
714 length = asn1->offset - start;
716 #ifdef HAVE_SOME_SNMP
717 value = vb_uinteger_value;
718 variable.val.integer = &value;
719 vb_display_string = format_var(&variable,
720 variable_oid, variable_oid_length, vb_type,
722 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
724 "Value: %s", vb_display_string);
725 free(vb_display_string);
726 #else /* HAVE_SOME_SNMP */
727 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
729 "Value: %s: %u (%#x)", vb_type_name,
730 vb_uinteger_value, vb_uinteger_value);
731 #endif /* HAVE_SOME_SNMP */
741 ret = asn1_string_value_decode (asn1, vb_length,
743 if (ret != ASN1_ERR_NOERROR)
745 length = asn1->offset - start;
747 #ifdef HAVE_SOME_SNMP
748 variable.val.string = vb_octet_string;
749 vb_display_string = format_var(&variable,
750 variable_oid, variable_oid_length, vb_type,
752 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
754 "Value: %s", vb_display_string);
755 free(vb_display_string);
756 #else /* HAVE_SOME_SNMP */
758 * If some characters are not printable, display
759 * the string as bytes.
761 for (i = 0; i < vb_length; i++) {
762 if (!(isprint(vb_octet_string[i])
763 || isspace(vb_octet_string[i])))
768 * We stopped, due to a non-printable
769 * character, before we got to the end
772 vb_display_string = g_malloc(4*vb_length);
773 buf = &vb_display_string[0];
774 len = sprintf(buf, "%03u", vb_octet_string[0]);
776 for (i = 1; i < vb_length; i++) {
777 len = sprintf(buf, ".%03u",
781 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
783 "Value: %s: %s", vb_type_name,
785 g_free(vb_display_string);
787 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
789 "Value: %s: %.*s", vb_type_name,
791 SAFE_STRING(vb_octet_string));
793 #endif /* HAVE_SOME_SNMP */
795 g_free(vb_octet_string);
799 ret = asn1_null_decode (asn1, vb_length);
800 if (ret != ASN1_ERR_NOERROR)
802 length = asn1->offset - start;
804 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
805 "Value: %s", vb_type_name);
810 ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
812 if (ret != ASN1_ERR_NOERROR)
814 length = asn1->offset - start;
816 #ifdef HAVE_SOME_SNMP
817 variable.val.objid = vb_oid;
818 vb_display_string = format_var(&variable,
819 variable_oid, variable_oid_length, vb_type,
820 vb_oid_length * sizeof (subid_t));
821 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
823 "Value: %s", vb_display_string);
824 free(vb_display_string);
825 #else /* HAVE_SOME_SNMP */
826 vb_display_string = format_oid(vb_oid, vb_oid_length);
827 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
829 "Value: %s: %s", vb_type_name, vb_display_string);
830 g_free(vb_display_string);
831 #endif /* HAVE_SOME_SNMP */
836 case SNMP_NOSUCHOBJECT:
837 length = asn1->offset - start;
839 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
840 "Value: %s: no such object", vb_type_name);
844 case SNMP_NOSUCHINSTANCE:
845 length = asn1->offset - start;
847 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
848 "Value: %s: no such instance", vb_type_name);
852 case SNMP_ENDOFMIBVIEW:
853 length = asn1->offset - start;
855 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
856 "Value: %s: end of mib view", vb_type_name);
861 g_assert_not_reached();
862 return ASN1_ERR_WRONG_TYPE;
865 return ASN1_ERR_NOERROR;
869 dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
870 proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
874 guint sequence_length;
878 guint32 error_status;
882 char *pdu_type_string;
885 guint enterprise_length;
887 guint8 *agent_address;
888 guint agent_address_length;
892 guint32 specific_type;
895 guint timestamp_length;
899 guint variable_bindings_length;
902 guint variable_length;
903 subid_t *variable_oid;
904 guint variable_oid_length;
909 pdu_type_string = val_to_str(pdu_type, pdu_types,
910 "Unknown PDU type %#x");
911 if (check_col(pinfo->cinfo, COL_INFO))
912 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
913 length = asn1.offset - start;
915 proto_tree_add_text(tree, tvb, offset, length,
916 "PDU type: %s", pdu_type_string);
920 /* get the fields in the PDU preceeding the variable-bindings sequence */
924 case SNMP_MSG_GETNEXT:
925 case SNMP_MSG_RESPONSE:
927 case SNMP_MSG_GETBULK:
928 case SNMP_MSG_INFORM:
930 case SNMP_MSG_REPORT:
932 ret = asn1_uint32_decode (&asn1, &request_id, &length);
933 if (ret != ASN1_ERR_NOERROR) {
934 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
939 proto_tree_add_text(tree, tvb, offset, length,
940 "Request Id: %#x", request_id);
944 /* error status, or getbulk non-repeaters */
945 ret = asn1_uint32_decode (&asn1, &error_status, &length);
946 if (ret != ASN1_ERR_NOERROR) {
947 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
948 (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
954 if (pdu_type == SNMP_MSG_GETBULK) {
955 proto_tree_add_text(tree, tvb, offset,
956 length, "Non-repeaters: %u", error_status);
958 proto_tree_add_text(tree, tvb, offset,
959 length, "Error Status: %s",
960 val_to_str(error_status, error_statuses,
966 /* error index, or getbulk max-repetitions */
967 ret = asn1_uint32_decode (&asn1, &error_index, &length);
968 if (ret != ASN1_ERR_NOERROR) {
969 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
970 (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
976 if (pdu_type == SNMP_MSG_GETBULK) {
977 proto_tree_add_text(tree, tvb, offset,
978 length, "Max repetitions: %u", error_index);
980 proto_tree_add_text(tree, tvb, offset,
981 length, "Error Index: %u", error_index);
989 ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
991 if (ret != ASN1_ERR_NOERROR) {
992 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
993 "enterprise OID", ret);
997 oid_string = format_oid(enterprise, enterprise_length);
998 proto_tree_add_text(tree, tvb, offset, length,
999 "Enterprise: %s", oid_string);
1006 start = asn1.offset;
1007 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1008 &def, &agent_address_length);
1009 if (ret != ASN1_ERR_NOERROR) {
1010 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1011 "agent address", ret);
1014 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
1015 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
1016 /* GXSNMP 0.0.15 says the latter is "needed for
1018 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1019 "agent_address", ASN1_ERR_WRONG_TYPE);
1022 if (agent_address_length != 4) {
1023 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1024 "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
1027 ret = asn1_string_value_decode (&asn1,
1028 agent_address_length, &agent_address);
1029 if (ret != ASN1_ERR_NOERROR) {
1030 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1031 "agent address", ret);
1034 length = asn1.offset - start;
1036 if (agent_address_length != 4) {
1037 proto_tree_add_text(tree, tvb, offset,
1039 "Agent address: <length is %u, not 4>",
1040 agent_address_length);
1042 proto_tree_add_text(tree, tvb, offset,
1044 "Agent address: %s",
1045 ip_to_str(agent_address));
1048 g_free(agent_address);
1051 /* generic trap type */
1052 ret = asn1_uint32_decode (&asn1, &trap_type, &length);
1053 if (ret != ASN1_ERR_NOERROR) {
1054 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1055 "generic trap type", ret);
1059 proto_tree_add_text(tree, tvb, offset, length,
1061 val_to_str(trap_type, trap_types, "Unknown (%u)"));
1065 /* specific trap type */
1066 ret = asn1_uint32_decode (&asn1, &specific_type, &length);
1067 if (ret != ASN1_ERR_NOERROR) {
1068 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1069 "specific trap type", ret);
1073 proto_tree_add_text(tree, tvb, offset, length,
1074 "Specific trap type: %u (%#x)",
1075 specific_type, specific_type);
1080 start = asn1.offset;
1081 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1082 &def, ×tamp_length);
1083 if (ret != ASN1_ERR_NOERROR) {
1084 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1088 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
1089 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
1090 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1091 "timestamp", ASN1_ERR_WRONG_TYPE);
1094 ret = asn1_uint32_value_decode(&asn1, timestamp_length,
1096 if (ret != ASN1_ERR_NOERROR) {
1097 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1101 length = asn1.offset - start;
1103 proto_tree_add_text(tree, tvb, offset, length,
1104 "Timestamp: %u", timestamp);
1110 /* variable bindings */
1111 /* get header for variable-bindings sequence */
1112 ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
1113 if (ret != ASN1_ERR_NOERROR) {
1114 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1115 "variable bindings header", ret);
1120 /* loop on variable bindings */
1122 while (variable_bindings_length > 0) {
1124 sequence_length = 0;
1127 ret = asn1_sequence_decode(&asn1, &variable_length, &length);
1128 if (ret != ASN1_ERR_NOERROR) {
1129 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1130 "variable binding header", ret);
1133 sequence_length += length;
1135 /* parse object identifier */
1136 ret = asn1_oid_decode (&asn1, &variable_oid,
1137 &variable_oid_length, &length);
1138 if (ret != ASN1_ERR_NOERROR) {
1139 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1140 "variable binding OID", ret);
1143 sequence_length += length;
1146 oid_string = format_oid(variable_oid,
1147 variable_oid_length);
1148 proto_tree_add_text(tree, tvb, offset, sequence_length,
1149 "Object identifier %d: %s", vb_index, oid_string);
1152 offset += sequence_length;
1153 variable_bindings_length -= sequence_length;
1155 /* Parse the variable's value */
1156 ret = snmp_variable_decode(tree, variable_oid,
1157 variable_oid_length, &asn1, offset, &length);
1158 if (ret != ASN1_ERR_NOERROR) {
1159 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1164 variable_bindings_length -= length;
1168 static const value_string qos_vals[] = {
1169 { 0x0, "No authentication or privacy" },
1170 { 0x1, "Authentication, no privacy" },
1171 { 0x2, "Authentication and privacy" },
1172 { 0x3, "Authentication and privacy" },
1177 dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
1178 guchar *parameters, int parameters_length)
1181 proto_tree *parameters_tree;
1182 proto_tree *qos_tree;
1187 item = proto_tree_add_text(tree, tvb, offset, length,
1189 parameters_tree = proto_item_add_subtree(item, ett_parameters);
1190 offset += length - parameters_length;
1192 if (parameters_length < 1)
1194 model = *parameters;
1195 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1196 "model: %u", model);
1199 parameters_length -= 1;
1201 /* Unknown model. */
1202 proto_tree_add_text(parameters_tree, tvb, offset,
1203 parameters_length, "parameters: %s",
1204 bytes_to_str(parameters, parameters_length));
1208 if (parameters_length < 1)
1211 item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
1213 qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
1214 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1215 decode_boolean_bitfield(qos, 0x04,
1216 8, "Generation of report PDU allowed",
1217 "Generation of report PDU not allowed"));
1218 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1219 decode_enumerated_bitfield(qos, 0x03,
1220 8, qos_vals, "%s"));
1223 parameters_length -= 1;
1225 if (parameters_length < 12)
1227 proto_tree_add_text(parameters_tree, tvb, offset, 12,
1228 "agentID: %s", bytes_to_str(parameters, 12));
1231 parameters_length -= 12;
1233 if (parameters_length < 4)
1235 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1236 "agentBoots: %u", pntohl(parameters));
1239 parameters_length -= 4;
1241 if (parameters_length < 4)
1243 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1244 "agentTime: %u", pntohl(parameters));
1247 parameters_length -= 4;
1249 if (parameters_length < 2)
1251 proto_tree_add_text(parameters_tree, tvb, offset, 2,
1252 "maxSize: %u", pntohs(parameters));
1255 parameters_length -= 2;
1257 if (parameters_length < 1)
1260 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1261 "userLen: %u", len);
1264 parameters_length -= 1;
1266 if (parameters_length < len)
1268 proto_tree_add_text(parameters_tree, tvb, offset, len,
1269 "userName: %.*s", len, parameters);
1272 parameters_length -= len;
1274 if (parameters_length < 1)
1277 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1278 "authLen: %u", len);
1281 parameters_length -= 1;
1283 if (parameters_length < len)
1285 proto_tree_add_text(parameters_tree, tvb, offset, len,
1286 "authDigest: %s", bytes_to_str(parameters, len));
1289 parameters_length -= len;
1291 if (parameters_length < 1)
1293 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
1294 "contextSelector: %s", bytes_to_str(parameters, parameters_length));
1298 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1299 proto_tree *tree, char *proto_name, int proto, gint ett)
1306 guint message_length;
1307 guint global_length;
1313 guint32 engineboots;
1326 int msgflags_length;
1327 int community_length;
1329 int cengineid_length;
1331 int cryptpdu_length;
1332 int aengineid_length;
1333 int username_length;
1340 proto_tree *snmp_tree = NULL;
1341 proto_tree *global_tree = NULL;
1342 proto_tree *flags_tree = NULL;
1343 proto_tree *secur_tree = NULL;
1344 proto_item *item = NULL;
1346 guint cls, con, tag;
1348 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1349 col_add_str(pinfo->cinfo, COL_PROTOCOL, proto_name);
1352 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
1353 snmp_tree = proto_item_add_subtree(item, ett);
1356 /* NOTE: we have to parse the message piece by piece, since the
1357 * capture length may be less than the message length: a 'global'
1358 * parsing is likely to fail.
1360 /* parse the SNMP header */
1361 asn1_open(&asn1, tvb, offset);
1362 ret = asn1_sequence_decode(&asn1, &message_length, &length);
1363 if (ret != ASN1_ERR_NOERROR) {
1364 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1365 "message header", ret);
1370 ret = asn1_uint32_decode (&asn1, &version, &length);
1371 if (ret != ASN1_ERR_NOERROR) {
1372 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1373 "version number", ret);
1377 proto_tree_add_text(snmp_tree, tvb, offset, length,
1379 val_to_str(version, versions, "Unknown version %#x"));
1385 case SNMP_VERSION_1:
1386 case SNMP_VERSION_2c:
1387 ret = asn1_octet_string_decode (&asn1, &community,
1388 &community_length, &length);
1389 if (ret != ASN1_ERR_NOERROR) {
1390 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1395 proto_tree_add_text(snmp_tree, tvb, offset, length,
1396 "Community: %.*s", community_length,
1397 SAFE_STRING(community));
1402 case SNMP_VERSION_2u:
1403 ret = asn1_octet_string_decode (&asn1, &community,
1404 &community_length, &length);
1406 dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
1407 community, community_length);
1412 case SNMP_VERSION_3:
1413 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1414 if (ret != ASN1_ERR_NOERROR) {
1415 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1416 "message global header", ret);
1420 item = proto_tree_add_text(snmp_tree, tvb, offset,
1421 global_length + length, "Message Global Header");
1422 global_tree = proto_item_add_subtree(item, ett_global);
1423 proto_tree_add_text(global_tree, tvb, offset,
1425 "Message Global Header Length: %d", global_length);
1428 ret = asn1_uint32_decode (&asn1, &msgid, &length);
1429 if (ret != ASN1_ERR_NOERROR) {
1430 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1435 proto_tree_add_text(global_tree, tvb, offset,
1436 length, "Message ID: %d", msgid);
1439 ret = asn1_uint32_decode (&asn1, &msgmax, &length);
1440 if (ret != ASN1_ERR_NOERROR) {
1441 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1442 "message max size", ret);
1446 proto_tree_add_text(global_tree, tvb, offset,
1447 length, "Message Max Size: %d", msgmax);
1450 ret = asn1_octet_string_decode (&asn1, &msgflags,
1451 &msgflags_length, &length);
1452 if (ret != ASN1_ERR_NOERROR) {
1453 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1454 "message flags", ret);
1457 if (msgflags_length != 1) {
1458 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1459 "message flags wrong length", ret);
1464 item = proto_tree_add_uint_format(global_tree,
1465 hf_snmpv3_flags, tvb, offset, length,
1466 msgflags[0], "Flags: 0x%02x", msgflags[0]);
1467 flags_tree = proto_item_add_subtree(item, ett_flags);
1468 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
1469 tvb, offset, length, msgflags[0]);
1470 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
1471 tvb, offset, length, msgflags[0]);
1472 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
1473 tvb, offset, length, msgflags[0]);
1475 encrypted = msgflags[0] & TH_CRYPT;
1478 ret = asn1_uint32_decode (&asn1, &msgsec, &length);
1479 if (ret != ASN1_ERR_NOERROR) {
1480 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1481 "message security model", ret);
1485 proto_tree_add_text(global_tree, tvb, offset,
1486 length, "Message Security Model: %s",
1487 val_to_str(msgsec, sec_models,
1488 "Unknown model %#x"));
1493 start = asn1.offset;
1494 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1495 &def, &secparm_length);
1496 length = asn1.offset - start;
1497 if (cls != ASN1_UNI && con != ASN1_PRI &&
1499 dissect_snmp_parse_error(tvb, offset, pinfo,
1500 snmp_tree, "Message Security Parameters",
1501 ASN1_ERR_WRONG_TYPE);
1505 item = proto_tree_add_text(snmp_tree, tvb,
1506 offset, secparm_length + length,
1507 "Message Security Parameters");
1508 secur_tree = proto_item_add_subtree(item,
1510 proto_tree_add_text(secur_tree, tvb, offset,
1512 "Message Security Parameters Length: %d",
1516 ret = asn1_sequence_decode(&asn1, &secparm_length,
1518 if (ret != ASN1_ERR_NOERROR) {
1519 dissect_snmp_parse_error(tvb, offset, pinfo,
1520 snmp_tree, "USM sequence header", ret);
1524 ret = asn1_octet_string_decode (&asn1, &aengineid,
1525 &aengineid_length, &length);
1526 if (ret != ASN1_ERR_NOERROR) {
1527 dissect_snmp_parse_error(tvb, offset, pinfo,
1528 snmp_tree, "authoritative engine id", ret);
1532 proto_tree_add_text(secur_tree, tvb, offset,
1533 length, "Authoritative Engine ID: %s",
1534 bytes_to_str(aengineid, aengineid_length));
1538 ret = asn1_uint32_decode (&asn1, &engineboots, &length);
1539 if (ret != ASN1_ERR_NOERROR) {
1540 dissect_snmp_parse_error(tvb, offset, pinfo,
1541 snmp_tree, "engine boots", ret);
1545 proto_tree_add_text(secur_tree, tvb,
1546 offset, length, "Engine Boots: %d",
1550 ret = asn1_uint32_decode (&asn1, &enginetime, &length);
1551 if (ret != ASN1_ERR_NOERROR) {
1552 dissect_snmp_parse_error(tvb, offset, pinfo,
1553 snmp_tree, "engine time", ret);
1557 proto_tree_add_text(secur_tree, tvb,
1558 offset, length, "Engine Time: %d",
1562 ret = asn1_octet_string_decode (&asn1, &username,
1563 &username_length, &length);
1564 if (ret != ASN1_ERR_NOERROR) {
1565 dissect_snmp_parse_error(tvb, offset, pinfo,
1566 snmp_tree, "user name", ret);
1570 proto_tree_add_text(secur_tree, tvb, offset,
1571 length, "User Name: %.*s",
1573 SAFE_STRING(username));
1577 ret = asn1_octet_string_decode (&asn1, &authpar,
1578 &authpar_length, &length);
1579 if (ret != ASN1_ERR_NOERROR) {
1580 dissect_snmp_parse_error(tvb, offset, pinfo,
1581 snmp_tree, "authentication parameter", ret);
1585 proto_tree_add_text(secur_tree, tvb, offset,
1586 length, "Authentication Parameter: %s",
1587 bytes_to_str(authpar, authpar_length));
1591 ret = asn1_octet_string_decode (&asn1, &privpar,
1592 &privpar_length, &length);
1593 if (ret != ASN1_ERR_NOERROR) {
1594 dissect_snmp_parse_error(tvb, offset, pinfo,
1595 snmp_tree, "privacy parameter", ret);
1599 proto_tree_add_text(secur_tree, tvb, offset,
1600 length, "Privacy Parameter: %s",
1601 bytes_to_str(privpar, privpar_length));
1607 ret = asn1_octet_string_decode (&asn1,
1608 &secparm, &secparm_length, &length);
1609 if (ret != ASN1_ERR_NOERROR) {
1610 dissect_snmp_parse_error(tvb, offset, pinfo,
1611 snmp_tree, "Message Security Parameters",
1616 proto_tree_add_text(snmp_tree, tvb, offset,
1618 "Message Security Parameters Data"
1619 " (%d bytes)", secparm_length);
1625 /* PDU starts here */
1627 ret = asn1_octet_string_decode (&asn1, &cryptpdu,
1628 &cryptpdu_length, &length);
1629 if (ret != ASN1_ERR_NOERROR) {
1630 dissect_snmp_parse_error(tvb, offset, pinfo,
1631 snmp_tree, "encrypted PDU header", ret);
1634 proto_tree_add_text(snmp_tree, tvb, offset, length,
1635 "Encrypted PDU (%d bytes)", length);
1637 if (check_col(pinfo->cinfo, COL_INFO))
1638 col_set_str(pinfo->cinfo, COL_INFO, "Encrypted PDU");
1641 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1642 if (ret != ASN1_ERR_NOERROR) {
1643 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1648 ret = asn1_octet_string_decode (&asn1, &cengineid,
1649 &cengineid_length, &length);
1650 if (ret != ASN1_ERR_NOERROR) {
1651 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1652 "context engine id", ret);
1656 proto_tree_add_text(snmp_tree, tvb, offset, length,
1657 "Context Engine ID: %s",
1658 bytes_to_str(cengineid, cengineid_length));
1662 ret = asn1_octet_string_decode (&asn1, &cname,
1663 &cname_length, &length);
1664 if (ret != ASN1_ERR_NOERROR) {
1665 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1666 "context name", ret);
1670 proto_tree_add_text(snmp_tree, tvb, offset, length,
1671 "Context Name: %.*s", cname_length,
1672 SAFE_STRING(cname));
1678 dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
1679 "PDU for unknown version of SNMP");
1683 start = asn1.offset;
1684 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1686 if (ret != ASN1_ERR_NOERROR) {
1687 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1691 if (cls != ASN1_CTX || con != ASN1_CON) {
1692 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1693 "PDU type", ASN1_ERR_WRONG_TYPE);
1696 dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
1700 dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1701 proto_tree *tree, int proto, gint ett)
1709 char *pdu_type_string;
1719 int password_length;
1721 guchar *application;
1722 int application_length;
1729 proto_tree *smux_tree = NULL;
1730 proto_item *item = NULL;
1734 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1735 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
1738 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
1739 smux_tree = proto_item_add_subtree(item, ett);
1742 /* NOTE: we have to parse the message piece by piece, since the
1743 * capture length may be less than the message length: a 'global'
1744 * parsing is likely to fail.
1746 /* parse the SNMP header */
1747 asn1_open(&asn1, tvb, offset);
1748 start = asn1.offset;
1749 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1751 if (ret != ASN1_ERR_NOERROR) {
1752 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1757 /* Dissect SMUX here */
1758 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
1759 pdu_type_string = val_to_str(pdu_type, smux_types,
1760 "Unknown PDU type %#x");
1761 if (check_col(pinfo->cinfo, COL_INFO))
1762 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1763 length = asn1.offset - start;
1765 proto_tree_add_text(smux_tree, tvb, offset, length,
1766 "PDU type: %s", pdu_type_string);
1769 ret = asn1_uint32_decode (&asn1, &version, &length);
1770 if (ret != ASN1_ERR_NOERROR) {
1771 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1776 proto_tree_add_text(smux_tree, tvb, offset, length,
1777 "Version: %d", version);
1781 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1782 if (ret != ASN1_ERR_NOERROR) {
1783 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1784 "registration OID", ret);
1788 oid_string = format_oid(regid, regid_length);
1789 proto_tree_add_text(smux_tree, tvb, offset, length,
1790 "Registration: %s", oid_string);
1796 ret = asn1_octet_string_decode (&asn1, &application,
1797 &application_length, &length);
1798 if (ret != ASN1_ERR_NOERROR) {
1799 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1800 "application", ret);
1804 proto_tree_add_text(smux_tree, tvb, offset, length,
1805 "Application: %.*s", application_length,
1806 SAFE_STRING(application));
1808 g_free(application);
1811 ret = asn1_octet_string_decode (&asn1, &password,
1812 &password_length, &length);
1813 if (ret != ASN1_ERR_NOERROR) {
1814 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1819 proto_tree_add_text(smux_tree, tvb, offset, length,
1820 "Password: %.*s", password_length,
1821 SAFE_STRING(password));
1827 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
1828 pdu_type_string = val_to_str(pdu_type, smux_types,
1829 "Unknown PDU type %#x");
1830 if (check_col(pinfo->cinfo, COL_INFO))
1831 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1832 length = asn1.offset - start;
1834 proto_tree_add_text(smux_tree, tvb, offset, length,
1835 "PDU type: %s", pdu_type_string);
1838 ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
1839 if (ret != ASN1_ERR_NOERROR) {
1840 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1845 proto_tree_add_text(smux_tree, tvb, offset,
1846 pdu_length, "Cause: %s",
1847 val_to_str(cause, smux_close,
1848 "Unknown cause %#x"));
1850 offset += pdu_length;
1853 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
1854 pdu_type_string = val_to_str(pdu_type, smux_types,
1855 "Unknown PDU type %#x");
1856 if (check_col(pinfo->cinfo, COL_INFO))
1857 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1858 length = asn1.offset - start;
1860 proto_tree_add_text(smux_tree, tvb, offset, length,
1861 "PDU type: %s", pdu_type_string);
1864 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1865 if (ret != ASN1_ERR_NOERROR) {
1866 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1867 "registration subtree", ret);
1871 oid_string = format_oid(regid, regid_length);
1872 proto_tree_add_text(smux_tree, tvb, offset, length,
1873 "Registration: %s", oid_string);
1879 ret = asn1_uint32_decode (&asn1, &priority, &length);
1880 if (ret != ASN1_ERR_NOERROR) {
1881 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1886 proto_tree_add_text(smux_tree, tvb, offset, length,
1887 "Priority: %d", priority);
1891 ret = asn1_uint32_decode (&asn1, &operation, &length);
1892 if (ret != ASN1_ERR_NOERROR) {
1893 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1898 proto_tree_add_text(smux_tree, tvb, offset, length,
1900 val_to_str(operation, smux_rreq,
1901 "Unknown operation %#x"));
1906 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
1907 pdu_type_string = val_to_str(pdu_type, smux_types,
1908 "Unknown PDU type %#x");
1909 if (check_col(pinfo->cinfo, COL_INFO))
1910 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1911 length = asn1.offset - start;
1913 proto_tree_add_text(smux_tree, tvb, offset, length,
1914 "PDU type: %s", pdu_type_string);
1917 ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
1918 if (ret != ASN1_ERR_NOERROR) {
1919 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1924 proto_tree_add_text(smux_tree, tvb, offset,
1926 val_to_str(priority, smux_prio,
1929 offset += pdu_length;
1932 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
1933 pdu_type_string = val_to_str(pdu_type, smux_types,
1934 "Unknown PDU type %#x");
1935 if (check_col(pinfo->cinfo, COL_INFO))
1936 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1937 length = asn1.offset - start;
1939 proto_tree_add_text(smux_tree, tvb, offset, length,
1940 "PDU type: %s", pdu_type_string);
1943 ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
1944 if (ret != ASN1_ERR_NOERROR) {
1945 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1950 proto_tree_add_text(smux_tree, tvb, offset,
1952 val_to_str(commit, smux_sout,
1953 "Unknown SOUT Value: %#x"));
1955 offset += pdu_length;
1958 if (cls != ASN1_CTX || con != ASN1_CON) {
1959 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1960 "PDU type", ASN1_ERR_WRONG_TYPE);
1963 dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
1967 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1969 conversation_t *conversation;
1972 * The first SNMP packet goes to the SNMP port; the second one
1973 * may come from some *other* port, but goes back to the same
1974 * IP address and port as the ones from which the first packet
1975 * came; all subsequent packets presumably go between those two
1976 * IP addresses and ports.
1978 * If this packet went to the SNMP port, we check to see if
1979 * there's already a conversation with one address/port pair
1980 * matching the source IP address and port of this packet,
1981 * the other address matching the destination IP address of this
1982 * packet, and any destination port.
1984 * If not, we create one, with its address 1/port 1 pair being
1985 * the source address/port of this packet, its address 2 being
1986 * the destination address of this packet, and its port 2 being
1987 * wildcarded, and give it the SNMP dissector as a dissector.
1989 if (pinfo->destport == UDP_PORT_SNMP) {
1990 conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
1991 pinfo->srcport, 0, NO_PORT_B);
1992 if (conversation == NULL) {
1993 conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
1994 pinfo->srcport, 0, NO_PORT2);
1995 conversation_set_dissector(conversation, snmp_handle);
1999 dissect_snmp_pdu(tvb, 0, pinfo, tree, "SNMP", proto_snmp, ett_snmp);
2003 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2005 dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
2009 proto_register_snmp(void)
2011 #if defined(WIN32) && defined(HAVE_SOME_SNMP)
2013 #define MIB_PATH_APPEND "snmp\\mibs"
2016 static hf_register_info hf[] = {
2018 { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
2020 { &hf_snmpv3_flags_auth,
2021 { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
2022 TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
2023 { &hf_snmpv3_flags_crypt,
2024 { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
2025 TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
2026 { &hf_snmpv3_flags_report,
2027 { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
2028 TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
2030 static gint *ett[] = {
2034 &ett_parameters_qos,
2040 #ifdef HAVE_SOME_SNMP
2043 /* Set MIBDIRS so that the SNMP library can find its mibs. */
2044 /* XXX - Should we set MIBS or MIBFILES as well? */
2046 mib_path = g_malloc (strlen(get_datafile_dir()) + strlen(MIB_PATH_APPEND) + 20);
2047 sprintf (mib_path, "MIBDIRS=%s\\%s", get_datafile_dir(), MIB_PATH_APPEND);
2048 /* Amazingly enough, Windows does not provide setenv(). */
2049 if (getenv("MIBDIRS") == NULL)
2056 * Suppress warnings about unknown tokens - we aren't initializing
2057 * UCD SNMP in its entirety, we're just initializing the
2058 * MIB-handling part because that's all we're using, which
2059 * means that entries in the configuration file for other
2060 * pars of the library will not be handled, and we don't want
2061 * the config file reading code to whine about that.
2063 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
2064 NETSNMP_DS_LIB_NO_TOKEN_WARNINGS, TRUE);
2065 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
2066 NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 2);
2067 register_mib_handlers();
2068 read_premib_configs();
2071 #endif /* HAVE_SOME_SNMP */
2072 proto_snmp = proto_register_protocol("Simple Network Management Protocol",
2074 proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2076 proto_register_field_array(proto_snmp, hf, array_length(hf));
2077 proto_register_subtree_array(ett, array_length(ett));
2078 snmp_handle = create_dissector_handle(dissect_snmp, proto_snmp);
2082 proto_reg_handoff_snmp(void)
2084 dissector_handle_t smux_handle;
2086 dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
2087 dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
2088 smux_handle = create_dissector_handle(dissect_smux, proto_smux);
2089 dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);
2090 dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
2091 dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
2092 dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
2093 data_handle = find_dissector("data");