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.100 2002/10/24 07:08: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"
58 # include <net-snmp/net-snmp-config.h>
59 # include <net-snmp/mib_api.h>
60 # include <net-snmp/library/default_store.h>
61 # include <net-snmp/config_api.h>
62 #else /* HAVE_NET_SNMP */
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>
71 # define netsnmp_ds_set_boolean ds_set_boolean
72 # define netsnmp_ds_set_int ds_set_int
73 # define NETSNMP_DS_LIBRARY_ID DS_LIBRARY_ID
74 # define NETSNMP_DS_LIB_NO_TOKEN_WARNINGS DS_LIB_NO_TOKEN_WARNINGS
75 # define NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY DS_LIB_PRINT_SUFFIX_ONLY
76 #endif /* HAVE_NET_SNMP */
79 * Define values "sprint_realloc_value()" expects.
81 # define VALTYPE_INTEGER ASN_INTEGER
82 # define VALTYPE_COUNTER ASN_COUNTER
83 # define VALTYPE_GAUGE ASN_GAUGE
84 # define VALTYPE_TIMETICKS ASN_TIMETICKS
85 # define VALTYPE_STRING ASN_OCTET_STR
86 # define VALTYPE_IPADDR ASN_IPADDRESS
87 # define VALTYPE_OPAQUE ASN_OPAQUE
88 # define VALTYPE_NSAP ASN_NSAP
89 # define VALTYPE_OBJECTID ASN_OBJECT_ID
90 # define VALTYPE_BITSTR ASN_BIT_STR
91 # define VALTYPE_COUNTER64 ASN_COUNTER64
93 #endif /* HAVE_SOME_SNMP */
97 #include "packet-snmp.h"
98 #include "format-oid.h"
100 /* Null string of type "guchar[]". */
101 static const guchar nullstring[] = "";
103 /* Take a pointer that may be null and return a pointer that's not null
104 by turning null pointers into pointers to the above null string. */
105 #define SAFE_STRING(s) (((s) != NULL) ? (s) : nullstring)
107 static int proto_snmp = -1;
108 static int proto_smux = -1;
110 static gint ett_snmp = -1;
111 static gint ett_smux = -1;
112 static gint ett_parameters = -1;
113 static gint ett_parameters_qos = -1;
114 static gint ett_global = -1;
115 static gint ett_flags = -1;
116 static gint ett_secur = -1;
118 static int hf_snmpv3_flags = -1;
119 static int hf_snmpv3_flags_auth = -1;
120 static int hf_snmpv3_flags_crypt = -1;
121 static int hf_snmpv3_flags_report = -1;
123 static dissector_handle_t snmp_handle;
124 static dissector_handle_t data_handle;
127 #define TH_CRYPT 0x02
128 #define TH_REPORT 0x04
130 #define UDP_PORT_SNMP 161
131 #define UDP_PORT_SNMP_TRAP 162
132 #define TCP_PORT_SMUX 199
134 /* Protocol version numbers */
135 #define SNMP_VERSION_1 0
136 #define SNMP_VERSION_2c 1
137 #define SNMP_VERSION_2u 2
138 #define SNMP_VERSION_3 3
140 static const value_string versions[] = {
141 { SNMP_VERSION_1, "1" },
142 { SNMP_VERSION_2c, "2C" },
143 { SNMP_VERSION_2u, "2U" },
144 { SNMP_VERSION_3, "3" },
149 #define SNMP_MSG_GET 0
150 #define SNMP_MSG_GETNEXT 1
151 #define SNMP_MSG_RESPONSE 2
152 #define SNMP_MSG_SET 3
153 #define SNMP_MSG_TRAP 4
155 #define SNMP_MSG_GETBULK 5
156 #define SNMP_MSG_INFORM 6
157 #define SNMP_MSG_TRAP2 7
158 #define SNMP_MSG_REPORT 8
160 static const value_string pdu_types[] = {
161 { SNMP_MSG_GET, "GET" },
162 { SNMP_MSG_GETNEXT, "GET-NEXT" },
163 { SNMP_MSG_SET, "SET" },
164 { SNMP_MSG_RESPONSE, "RESPONSE" },
165 { SNMP_MSG_TRAP, "TRAP-V1" },
166 { SNMP_MSG_GETBULK, "GETBULK" },
167 { SNMP_MSG_INFORM, "INFORM" },
168 { SNMP_MSG_TRAP2, "TRAP-V2" },
169 { SNMP_MSG_REPORT, "REPORT" },
174 #define SMUX_MSG_OPEN 0
175 #define SMUX_MSG_CLOSE 1
176 #define SMUX_MSG_RREQ 2
177 #define SMUX_MSG_RRSP 3
178 #define SMUX_MSG_SOUT 4
180 static const value_string smux_types[] = {
181 { SMUX_MSG_OPEN, "Open" },
182 { SMUX_MSG_CLOSE, "Close" },
183 { SMUX_MSG_RREQ, "Registration Request" },
184 { SMUX_MSG_RRSP, "Registration Response" },
185 { SMUX_MSG_SOUT, "Commit Or Rollback" },
189 /* SMUX Closing causes */
190 #define SMUX_CLOSE_DOWN 0
191 #define SMUX_CLOSE_VERSION 1
192 #define SMUX_CLOSE_PACKET 2
193 #define SMUX_CLOSE_PROTOCOL 3
194 #define SMUX_CLOSE_INTERNAL 4
195 #define SMUX_CLOSE_NOAUTH 5
197 static const value_string smux_close[] = {
198 { SMUX_CLOSE_DOWN, "Going down" },
199 { SMUX_CLOSE_VERSION, "Unsupported Version" },
200 { SMUX_CLOSE_PACKET, "Packet Format Error" },
201 { SMUX_CLOSE_PROTOCOL, "Protocol Error" },
202 { SMUX_CLOSE_INTERNAL, "Internal Error" },
203 { SMUX_CLOSE_NOAUTH, "Unauthorized" },
207 /* SMUX Request codes */
208 #define SMUX_RREQ_DELETE 0
209 #define SMUX_RREQ_READONLY 1
210 #define SMUX_RREQ_READWRITE 2
212 static const value_string smux_rreq[] = {
213 { SMUX_RREQ_DELETE, "Delete" },
214 { SMUX_RREQ_READONLY, "Read Only" },
215 { SMUX_RREQ_READWRITE, "Read Write" },
219 static const value_string smux_prio[] = {
224 /* SMUX SOut codes */
225 #define SMUX_SOUT_COMMIT 0
226 #define SMUX_SOUT_ROLLBACK 1
228 static const value_string smux_sout[] = {
229 { SMUX_SOUT_COMMIT, "Commit" },
230 { SMUX_SOUT_ROLLBACK, "Rollback" },
234 /* Error status values */
235 #define SNMP_ERR_NOERROR 0
236 #define SNMP_ERR_TOOBIG 1
237 #define SNMP_ERR_NOSUCHNAME 2
238 #define SNMP_ERR_BADVALUE 3
239 #define SNMP_ERR_READONLY 4
240 #define SNMP_ERR_GENERROR 5
242 #define SNMP_ERR_NOACCESS 6
243 #define SNMP_ERR_WRONGTYPE 7
244 #define SNMP_ERR_WRONGLENGTH 8
245 #define SNMP_ERR_WRONGENCODING 9
246 #define SNMP_ERR_WRONGVALUE 10
247 #define SNMP_ERR_NOCREATION 11
248 #define SNMP_ERR_INCONSISTENTVALUE 12
249 #define SNMP_ERR_RESOURCEUNAVAILABLE 13
250 #define SNMP_ERR_COMMITFAILED 14
251 #define SNMP_ERR_UNDOFAILED 15
252 #define SNMP_ERR_AUTHORIZATIONERROR 16
253 #define SNMP_ERR_NOTWRITABLE 17
254 #define SNMP_ERR_INCONSISTENTNAME 18
256 static const value_string error_statuses[] = {
257 { SNMP_ERR_NOERROR, "NO ERROR" },
258 { SNMP_ERR_TOOBIG, "TOOBIG" },
259 { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" },
260 { SNMP_ERR_BADVALUE, "BAD VALUE" },
261 { SNMP_ERR_READONLY, "READ ONLY" },
262 { SNMP_ERR_GENERROR, "GENERIC ERROR" },
263 { SNMP_ERR_NOACCESS, "NO ACCESS" },
264 { SNMP_ERR_WRONGTYPE, "WRONG TYPE" },
265 { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" },
266 { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" },
267 { SNMP_ERR_WRONGVALUE, "WRONG VALUE" },
268 { SNMP_ERR_NOCREATION, "NO CREATION" },
269 { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" },
270 { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" },
271 { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" },
272 { SNMP_ERR_UNDOFAILED, "UNDO FAILED" },
273 { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" },
274 { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" },
275 { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" },
279 /* General SNMP V1 Traps */
281 #define SNMP_TRAP_COLDSTART 0
282 #define SNMP_TRAP_WARMSTART 1
283 #define SNMP_TRAP_LINKDOWN 2
284 #define SNMP_TRAP_LINKUP 3
285 #define SNMP_TRAP_AUTHFAIL 4
286 #define SNMP_TRAP_EGPNEIGHBORLOSS 5
287 #define SNMP_TRAP_ENTERPRISESPECIFIC 6
289 static const value_string trap_types[] = {
290 { SNMP_TRAP_COLDSTART, "COLD START" },
291 { SNMP_TRAP_WARMSTART, "WARM START" },
292 { SNMP_TRAP_LINKDOWN, "LINK DOWN" },
293 { SNMP_TRAP_LINKUP, "LINK UP" },
294 { SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
295 { SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
296 { SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
300 /* Security Models */
302 #define SNMP_SEC_ANY 0
303 #define SNMP_SEC_V1 1
304 #define SNMP_SEC_V2C 2
305 #define SNMP_SEC_USM 3
307 static const value_string sec_models[] = {
308 { SNMP_SEC_ANY, "Any" },
309 { SNMP_SEC_V1, "V1" },
310 { SNMP_SEC_V2C, "V2C" },
311 { SNMP_SEC_USM, "USM" },
317 #define SNMP_IPA 0 /* IP Address */
318 #define SNMP_CNT 1 /* Counter (Counter32) */
319 #define SNMP_GGE 2 /* Gauge (Gauge32) */
320 #define SNMP_TIT 3 /* TimeTicks */
321 #define SNMP_OPQ 4 /* Opaque */
322 #define SNMP_NSP 5 /* NsapAddress */
323 #define SNMP_C64 6 /* Counter64 */
324 #define SNMP_U32 7 /* Uinteger32 */
333 #define SNMP_INTEGER 1 /* l */
334 #define SNMP_OCTETSTR 2 /* c */
335 #define SNMP_DISPLAYSTR 2 /* c */
336 #define SNMP_OBJECTID 3 /* ul */
337 #define SNMP_IPADDR 4 /* uc */
338 #define SNMP_COUNTER 5 /* ul */
339 #define SNMP_GAUGE 6 /* ul */
340 #define SNMP_TIMETICKS 7 /* ul */
341 #define SNMP_OPAQUE 8 /* c */
343 /* additional SNMPv2 Types */
345 #define SNMP_UINTEGER 5 /* ul */
346 #define SNMP_BITSTR 9 /* uc */
347 #define SNMP_NSAP 10 /* uc */
348 #define SNMP_COUNTER64 11 /* ul */
349 #define SNMP_NOSUCHOBJECT 12
350 #define SNMP_NOSUCHINSTANCE 13
351 #define SNMP_ENDOFMIBVIEW 14
353 typedef struct _SNMP_CNV SNMP_CNV;
363 static SNMP_CNV SnmpCnv [] =
365 {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"},
366 {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"},
367 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"},
368 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"},
369 {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"},
370 {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */
371 {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */
372 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"},
373 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"},
375 /* SNMPv2 data types and errors */
377 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"},
378 {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"},
379 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"},
380 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"},
381 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"},
386 * NAME: g_snmp_tag_cls2syntax
387 * SYNOPSIS: gboolean g_snmp_tag_cls2syntax
393 * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name.
394 * See SnmpCnv for conversion.
395 * RETURNS: name on success, NULL on failure
399 snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
404 while (cnv->syntax != -1)
406 if (cnv->tag == tag && cnv->class == cls)
408 *syntax = cnv->syntax;
417 dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
418 proto_tree *tree, const char *field_name, int ret)
422 errstr = asn1_err_to_str(ret);
424 if (check_col(pinfo->cinfo, COL_INFO)) {
425 col_add_fstr(pinfo->cinfo, COL_INFO,
426 "ERROR: Couldn't parse %s: %s", field_name, errstr);
429 proto_tree_add_text(tree, tvb, offset, 0,
430 "ERROR: Couldn't parse %s: %s", field_name, errstr);
431 call_dissector(data_handle,
432 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
437 dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
438 proto_tree *tree, const char *message)
440 if (check_col(pinfo->cinfo, COL_INFO))
441 col_add_str(pinfo->cinfo, COL_INFO, message);
444 proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
445 call_dissector(data_handle,
446 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
451 format_oid(subid_t *oid, guint oid_length)
458 #ifdef HAVE_SOME_SNMP
460 size_t oid_string_len;
464 result_len = oid_length * 22;
466 #ifdef HAVE_SOME_SNMP
468 * Get the decoded form of the OID, and add its length to the
469 * length of the result string.
471 * XXX - check for "malloc" and "sprint_realloc_objid()" failure.
473 oid_string_len = 256;
474 oid_string = malloc(oid_string_len);
477 sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
479 result_len += strlen(oid_string) + 3;
482 result = g_malloc(result_len + 1);
484 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
486 for (i = 1; i < oid_length;i++) {
487 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
491 #ifdef HAVE_SOME_SNMP
493 * Append the decoded form of the OID.
495 sprintf(buf, " (%s)", oid_string);
502 #ifdef HAVE_SOME_SNMP
504 check_var_length(guint vb_length, guint required_length)
507 static const char badlen_fmt[] = "Length is %u, should be %u";
509 if (vb_length != required_length) {
510 /* Enough room for the largest "Length is XXX,
511 should be XXX" message - 10 digits for each
513 buf = malloc(sizeof badlen_fmt + 10 + 10);
514 sprintf(buf, badlen_fmt, vb_length, required_length);
517 return NULL; /* length is OK */
521 format_var(struct variable_list *variable, subid_t *variable_oid,
522 guint variable_oid_length, gushort vb_type, guint val_len)
531 /* Length has to be 4 bytes. */
532 buf = check_var_length(val_len, 4);
534 return buf; /* it's not 4 bytes */
538 /* Length has to be 8 bytes. */
539 buf = check_var_length(val_len, 8);
541 return buf; /* it's not 8 bytes */
548 variable->next_variable = NULL;
549 variable->name = variable_oid;
550 variable->name_length = variable_oid_length;
554 variable->type = VALTYPE_INTEGER;
558 variable->type = VALTYPE_COUNTER;
562 variable->type = VALTYPE_GAUGE;
566 variable->type = VALTYPE_TIMETICKS;
570 variable->type = VALTYPE_STRING;
574 variable->type = VALTYPE_IPADDR;
578 variable->type = VALTYPE_OPAQUE;
582 variable->type = VALTYPE_NSAP;
586 variable->type = VALTYPE_OBJECTID;
590 variable->type = VALTYPE_BITSTR;
594 variable->type = VALTYPE_COUNTER64;
597 variable->val_len = val_len;
600 * XXX - check for "malloc" and "sprint_realloc_objid()" failure.
603 buf = malloc(buf_len);
606 sprint_realloc_value(&buf, &buf_len, &out_len, 1, variable_oid,
607 variable_oid_length, variable);
613 snmp_variable_decode(proto_tree *snmp_tree,
614 subid_t *variable_oid
615 #ifndef HAVE_SOME_SNMP
619 guint variable_oid_length
620 #ifndef HAVE_SOME_SNMP
624 ASN1_SCK *asn1, int offset, guint *lengthp)
635 gint32 vb_integer_value;
636 guint32 vb_uinteger_value;
638 guint8 *vb_octet_string;
643 gchar *vb_display_string;
645 #ifdef HAVE_SOME_SNMP
646 struct variable_list variable;
648 #else /* HAVE_SOME_SNMP */
652 #endif /* HAVE_SOME_SNMP */
654 /* parse the type of the object */
655 start = asn1->offset;
656 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
657 if (ret != ASN1_ERR_NOERROR)
660 return ASN1_ERR_LENGTH_NOT_DEFINITE;
662 /* Convert the class, constructed flag, and tag to a type. */
663 vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
664 if (vb_type_name == NULL) {
667 * Dissect the value as an opaque string of octets.
669 vb_type_name = "unsupported type";
670 vb_type = SNMP_OPAQUE;
673 /* parse the value */
677 ret = asn1_int32_value_decode(asn1, vb_length,
679 if (ret != ASN1_ERR_NOERROR)
681 length = asn1->offset - start;
683 #ifdef HAVE_SOME_SNMP
684 value = vb_integer_value;
685 variable.val.integer = &value;
686 vb_display_string = format_var(&variable,
687 variable_oid, variable_oid_length, vb_type,
689 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
691 "Value: %s", vb_display_string);
692 free(vb_display_string);
693 #else /* HAVE_SOME_SNMP */
694 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
696 "Value: %s: %d (%#x)", vb_type_name,
697 vb_integer_value, vb_integer_value);
698 #endif /* HAVE_SOME_SNMP */
705 ret = asn1_uint32_value_decode(asn1, vb_length,
707 if (ret != ASN1_ERR_NOERROR)
709 length = asn1->offset - start;
711 #ifdef HAVE_SOME_SNMP
712 value = vb_uinteger_value;
713 variable.val.integer = &value;
714 vb_display_string = format_var(&variable,
715 variable_oid, variable_oid_length, vb_type,
717 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
719 "Value: %s", vb_display_string);
720 free(vb_display_string);
721 #else /* HAVE_SOME_SNMP */
722 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
724 "Value: %s: %u (%#x)", vb_type_name,
725 vb_uinteger_value, vb_uinteger_value);
726 #endif /* HAVE_SOME_SNMP */
736 ret = asn1_string_value_decode (asn1, vb_length,
738 if (ret != ASN1_ERR_NOERROR)
740 length = asn1->offset - start;
742 #ifdef HAVE_SOME_SNMP
743 variable.val.string = vb_octet_string;
744 vb_display_string = format_var(&variable,
745 variable_oid, variable_oid_length, vb_type,
747 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
749 "Value: %s", vb_display_string);
750 free(vb_display_string);
751 #else /* HAVE_SOME_SNMP */
753 * If some characters are not printable, display
754 * the string as bytes.
756 for (i = 0; i < vb_length; i++) {
757 if (!(isprint(vb_octet_string[i])
758 || isspace(vb_octet_string[i])))
763 * We stopped, due to a non-printable
764 * character, before we got to the end
767 vb_display_string = g_malloc(4*vb_length);
768 buf = &vb_display_string[0];
769 len = sprintf(buf, "%03u", vb_octet_string[0]);
771 for (i = 1; i < vb_length; i++) {
772 len = sprintf(buf, ".%03u",
776 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
778 "Value: %s: %s", vb_type_name,
780 g_free(vb_display_string);
782 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
784 "Value: %s: %.*s", vb_type_name,
786 SAFE_STRING(vb_octet_string));
788 #endif /* HAVE_SOME_SNMP */
790 g_free(vb_octet_string);
794 ret = asn1_null_decode (asn1, vb_length);
795 if (ret != ASN1_ERR_NOERROR)
797 length = asn1->offset - start;
799 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
800 "Value: %s", vb_type_name);
805 ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
807 if (ret != ASN1_ERR_NOERROR)
809 length = asn1->offset - start;
811 #ifdef HAVE_SOME_SNMP
812 variable.val.objid = vb_oid;
813 vb_display_string = format_var(&variable,
814 variable_oid, variable_oid_length, vb_type,
815 vb_oid_length * sizeof (subid_t));
816 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
818 "Value: %s", vb_display_string);
819 free(vb_display_string);
820 #else /* HAVE_SOME_SNMP */
821 vb_display_string = format_oid(vb_oid, vb_oid_length);
822 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
824 "Value: %s: %s", vb_type_name, vb_display_string);
825 g_free(vb_display_string);
826 #endif /* HAVE_SOME_SNMP */
831 case SNMP_NOSUCHOBJECT:
832 length = asn1->offset - start;
834 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
835 "Value: %s: no such object", vb_type_name);
839 case SNMP_NOSUCHINSTANCE:
840 length = asn1->offset - start;
842 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
843 "Value: %s: no such instance", vb_type_name);
847 case SNMP_ENDOFMIBVIEW:
848 length = asn1->offset - start;
850 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
851 "Value: %s: end of mib view", vb_type_name);
856 g_assert_not_reached();
857 return ASN1_ERR_WRONG_TYPE;
860 return ASN1_ERR_NOERROR;
864 dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
865 proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
869 guint sequence_length;
873 guint32 error_status;
877 char *pdu_type_string;
880 guint enterprise_length;
882 guint8 *agent_address;
883 guint agent_address_length;
887 guint32 specific_type;
890 guint timestamp_length;
894 guint variable_bindings_length;
897 guint variable_length;
898 subid_t *variable_oid;
899 guint variable_oid_length;
904 pdu_type_string = val_to_str(pdu_type, pdu_types,
905 "Unknown PDU type %#x");
906 if (check_col(pinfo->cinfo, COL_INFO))
907 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
908 length = asn1.offset - start;
910 proto_tree_add_text(tree, tvb, offset, length,
911 "PDU type: %s", pdu_type_string);
915 /* get the fields in the PDU preceeding the variable-bindings sequence */
919 case SNMP_MSG_GETNEXT:
920 case SNMP_MSG_RESPONSE:
922 case SNMP_MSG_GETBULK:
923 case SNMP_MSG_INFORM:
925 case SNMP_MSG_REPORT:
927 ret = asn1_uint32_decode (&asn1, &request_id, &length);
928 if (ret != ASN1_ERR_NOERROR) {
929 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
934 proto_tree_add_text(tree, tvb, offset, length,
935 "Request Id: %#x", request_id);
939 /* error status, or getbulk non-repeaters */
940 ret = asn1_uint32_decode (&asn1, &error_status, &length);
941 if (ret != ASN1_ERR_NOERROR) {
942 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
943 (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
949 if (pdu_type == SNMP_MSG_GETBULK) {
950 proto_tree_add_text(tree, tvb, offset,
951 length, "Non-repeaters: %u", error_status);
953 proto_tree_add_text(tree, tvb, offset,
954 length, "Error Status: %s",
955 val_to_str(error_status, error_statuses,
961 /* error index, or getbulk max-repetitions */
962 ret = asn1_uint32_decode (&asn1, &error_index, &length);
963 if (ret != ASN1_ERR_NOERROR) {
964 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
965 (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
971 if (pdu_type == SNMP_MSG_GETBULK) {
972 proto_tree_add_text(tree, tvb, offset,
973 length, "Max repetitions: %u", error_index);
975 proto_tree_add_text(tree, tvb, offset,
976 length, "Error Index: %u", error_index);
984 ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
986 if (ret != ASN1_ERR_NOERROR) {
987 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
988 "enterprise OID", ret);
992 oid_string = format_oid(enterprise, enterprise_length);
993 proto_tree_add_text(tree, tvb, offset, length,
994 "Enterprise: %s", oid_string);
1001 start = asn1.offset;
1002 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1003 &def, &agent_address_length);
1004 if (ret != ASN1_ERR_NOERROR) {
1005 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1006 "agent address", ret);
1009 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
1010 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
1011 /* GXSNMP 0.0.15 says the latter is "needed for
1013 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1014 "agent_address", ASN1_ERR_WRONG_TYPE);
1017 if (agent_address_length != 4) {
1018 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1019 "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
1022 ret = asn1_string_value_decode (&asn1,
1023 agent_address_length, &agent_address);
1024 if (ret != ASN1_ERR_NOERROR) {
1025 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1026 "agent address", ret);
1029 length = asn1.offset - start;
1031 if (agent_address_length != 4) {
1032 proto_tree_add_text(tree, tvb, offset,
1034 "Agent address: <length is %u, not 4>",
1035 agent_address_length);
1037 proto_tree_add_text(tree, tvb, offset,
1039 "Agent address: %s",
1040 ip_to_str(agent_address));
1043 g_free(agent_address);
1046 /* generic trap type */
1047 ret = asn1_uint32_decode (&asn1, &trap_type, &length);
1048 if (ret != ASN1_ERR_NOERROR) {
1049 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1050 "generic trap type", ret);
1054 proto_tree_add_text(tree, tvb, offset, length,
1056 val_to_str(trap_type, trap_types, "Unknown (%u)"));
1060 /* specific trap type */
1061 ret = asn1_uint32_decode (&asn1, &specific_type, &length);
1062 if (ret != ASN1_ERR_NOERROR) {
1063 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1064 "specific trap type", ret);
1068 proto_tree_add_text(tree, tvb, offset, length,
1069 "Specific trap type: %u (%#x)",
1070 specific_type, specific_type);
1075 start = asn1.offset;
1076 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1077 &def, ×tamp_length);
1078 if (ret != ASN1_ERR_NOERROR) {
1079 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1083 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
1084 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
1085 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1086 "timestamp", ASN1_ERR_WRONG_TYPE);
1089 ret = asn1_uint32_value_decode(&asn1, timestamp_length,
1091 if (ret != ASN1_ERR_NOERROR) {
1092 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1096 length = asn1.offset - start;
1098 proto_tree_add_text(tree, tvb, offset, length,
1099 "Timestamp: %u", timestamp);
1105 /* variable bindings */
1106 /* get header for variable-bindings sequence */
1107 ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
1108 if (ret != ASN1_ERR_NOERROR) {
1109 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1110 "variable bindings header", ret);
1115 /* loop on variable bindings */
1117 while (variable_bindings_length > 0) {
1119 sequence_length = 0;
1122 ret = asn1_sequence_decode(&asn1, &variable_length, &length);
1123 if (ret != ASN1_ERR_NOERROR) {
1124 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1125 "variable binding header", ret);
1128 sequence_length += length;
1130 /* parse object identifier */
1131 ret = asn1_oid_decode (&asn1, &variable_oid,
1132 &variable_oid_length, &length);
1133 if (ret != ASN1_ERR_NOERROR) {
1134 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1135 "variable binding OID", ret);
1138 sequence_length += length;
1141 oid_string = format_oid(variable_oid,
1142 variable_oid_length);
1143 proto_tree_add_text(tree, tvb, offset, sequence_length,
1144 "Object identifier %d: %s", vb_index, oid_string);
1147 offset += sequence_length;
1148 variable_bindings_length -= sequence_length;
1150 /* Parse the variable's value */
1151 ret = snmp_variable_decode(tree, variable_oid,
1152 variable_oid_length, &asn1, offset, &length);
1153 if (ret != ASN1_ERR_NOERROR) {
1154 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1159 variable_bindings_length -= length;
1163 static const value_string qos_vals[] = {
1164 { 0x0, "No authentication or privacy" },
1165 { 0x1, "Authentication, no privacy" },
1166 { 0x2, "Authentication and privacy" },
1167 { 0x3, "Authentication and privacy" },
1172 dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
1173 guchar *parameters, int parameters_length)
1176 proto_tree *parameters_tree;
1177 proto_tree *qos_tree;
1182 item = proto_tree_add_text(tree, tvb, offset, length,
1184 parameters_tree = proto_item_add_subtree(item, ett_parameters);
1185 offset += length - parameters_length;
1187 if (parameters_length < 1)
1189 model = *parameters;
1190 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1191 "model: %u", model);
1194 parameters_length -= 1;
1196 /* Unknown model. */
1197 proto_tree_add_text(parameters_tree, tvb, offset,
1198 parameters_length, "parameters: %s",
1199 bytes_to_str(parameters, parameters_length));
1203 if (parameters_length < 1)
1206 item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
1208 qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
1209 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1210 decode_boolean_bitfield(qos, 0x04,
1211 8, "Generation of report PDU allowed",
1212 "Generation of report PDU not allowed"));
1213 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1214 decode_enumerated_bitfield(qos, 0x03,
1215 8, qos_vals, "%s"));
1218 parameters_length -= 1;
1220 if (parameters_length < 12)
1222 proto_tree_add_text(parameters_tree, tvb, offset, 12,
1223 "agentID: %s", bytes_to_str(parameters, 12));
1226 parameters_length -= 12;
1228 if (parameters_length < 4)
1230 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1231 "agentBoots: %u", pntohl(parameters));
1234 parameters_length -= 4;
1236 if (parameters_length < 4)
1238 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1239 "agentTime: %u", pntohl(parameters));
1242 parameters_length -= 4;
1244 if (parameters_length < 2)
1246 proto_tree_add_text(parameters_tree, tvb, offset, 2,
1247 "maxSize: %u", pntohs(parameters));
1250 parameters_length -= 2;
1252 if (parameters_length < 1)
1255 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1256 "userLen: %u", len);
1259 parameters_length -= 1;
1261 if (parameters_length < len)
1263 proto_tree_add_text(parameters_tree, tvb, offset, len,
1264 "userName: %.*s", len, parameters);
1267 parameters_length -= len;
1269 if (parameters_length < 1)
1272 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1273 "authLen: %u", len);
1276 parameters_length -= 1;
1278 if (parameters_length < len)
1280 proto_tree_add_text(parameters_tree, tvb, offset, len,
1281 "authDigest: %s", bytes_to_str(parameters, len));
1284 parameters_length -= len;
1286 if (parameters_length < 1)
1288 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
1289 "contextSelector: %s", bytes_to_str(parameters, parameters_length));
1293 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1294 proto_tree *tree, char *proto_name, int proto, gint ett)
1301 guint message_length;
1302 guint global_length;
1308 guint32 engineboots;
1321 int msgflags_length;
1322 int community_length;
1324 int cengineid_length;
1326 int cryptpdu_length;
1327 int aengineid_length;
1328 int username_length;
1335 proto_tree *snmp_tree = NULL;
1336 proto_tree *global_tree = NULL;
1337 proto_tree *flags_tree = NULL;
1338 proto_tree *secur_tree = NULL;
1339 proto_item *item = NULL;
1341 guint cls, con, tag;
1343 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1344 col_add_str(pinfo->cinfo, COL_PROTOCOL, proto_name);
1347 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
1348 snmp_tree = proto_item_add_subtree(item, ett);
1351 /* NOTE: we have to parse the message piece by piece, since the
1352 * capture length may be less than the message length: a 'global'
1353 * parsing is likely to fail.
1355 /* parse the SNMP header */
1356 asn1_open(&asn1, tvb, offset);
1357 ret = asn1_sequence_decode(&asn1, &message_length, &length);
1358 if (ret != ASN1_ERR_NOERROR) {
1359 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1360 "message header", ret);
1365 ret = asn1_uint32_decode (&asn1, &version, &length);
1366 if (ret != ASN1_ERR_NOERROR) {
1367 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1368 "version number", ret);
1372 proto_tree_add_text(snmp_tree, tvb, offset, length,
1374 val_to_str(version, versions, "Unknown version %#x"));
1380 case SNMP_VERSION_1:
1381 case SNMP_VERSION_2c:
1382 ret = asn1_octet_string_decode (&asn1, &community,
1383 &community_length, &length);
1384 if (ret != ASN1_ERR_NOERROR) {
1385 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1390 proto_tree_add_text(snmp_tree, tvb, offset, length,
1391 "Community: %.*s", community_length,
1392 SAFE_STRING(community));
1397 case SNMP_VERSION_2u:
1398 ret = asn1_octet_string_decode (&asn1, &community,
1399 &community_length, &length);
1401 dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
1402 community, community_length);
1407 case SNMP_VERSION_3:
1408 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1409 if (ret != ASN1_ERR_NOERROR) {
1410 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1411 "message global header", ret);
1415 item = proto_tree_add_text(snmp_tree, tvb, offset,
1416 global_length + length, "Message Global Header");
1417 global_tree = proto_item_add_subtree(item, ett_global);
1418 proto_tree_add_text(global_tree, tvb, offset,
1420 "Message Global Header Length: %d", global_length);
1423 ret = asn1_uint32_decode (&asn1, &msgid, &length);
1424 if (ret != ASN1_ERR_NOERROR) {
1425 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1430 proto_tree_add_text(global_tree, tvb, offset,
1431 length, "Message ID: %d", msgid);
1434 ret = asn1_uint32_decode (&asn1, &msgmax, &length);
1435 if (ret != ASN1_ERR_NOERROR) {
1436 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1437 "message max size", ret);
1441 proto_tree_add_text(global_tree, tvb, offset,
1442 length, "Message Max Size: %d", msgmax);
1445 ret = asn1_octet_string_decode (&asn1, &msgflags,
1446 &msgflags_length, &length);
1447 if (ret != ASN1_ERR_NOERROR) {
1448 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1449 "message flags", ret);
1452 if (msgflags_length != 1) {
1453 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1454 "message flags wrong length", ret);
1459 item = proto_tree_add_uint_format(global_tree,
1460 hf_snmpv3_flags, tvb, offset, length,
1461 msgflags[0], "Flags: 0x%02x", msgflags[0]);
1462 flags_tree = proto_item_add_subtree(item, ett_flags);
1463 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
1464 tvb, offset, length, msgflags[0]);
1465 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
1466 tvb, offset, length, msgflags[0]);
1467 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
1468 tvb, offset, length, msgflags[0]);
1470 encrypted = msgflags[0] & TH_CRYPT;
1473 ret = asn1_uint32_decode (&asn1, &msgsec, &length);
1474 if (ret != ASN1_ERR_NOERROR) {
1475 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1476 "message security model", ret);
1480 proto_tree_add_text(global_tree, tvb, offset,
1481 length, "Message Security Model: %s",
1482 val_to_str(msgsec, sec_models,
1483 "Unknown model %#x"));
1488 start = asn1.offset;
1489 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1490 &def, &secparm_length);
1491 length = asn1.offset - start;
1492 if (cls != ASN1_UNI && con != ASN1_PRI &&
1494 dissect_snmp_parse_error(tvb, offset, pinfo,
1495 snmp_tree, "Message Security Parameters",
1496 ASN1_ERR_WRONG_TYPE);
1500 item = proto_tree_add_text(snmp_tree, tvb,
1501 offset, secparm_length + length,
1502 "Message Security Parameters");
1503 secur_tree = proto_item_add_subtree(item,
1505 proto_tree_add_text(secur_tree, tvb, offset,
1507 "Message Security Parameters Length: %d",
1511 ret = asn1_sequence_decode(&asn1, &secparm_length,
1513 if (ret != ASN1_ERR_NOERROR) {
1514 dissect_snmp_parse_error(tvb, offset, pinfo,
1515 snmp_tree, "USM sequence header", ret);
1519 ret = asn1_octet_string_decode (&asn1, &aengineid,
1520 &aengineid_length, &length);
1521 if (ret != ASN1_ERR_NOERROR) {
1522 dissect_snmp_parse_error(tvb, offset, pinfo,
1523 snmp_tree, "authoritative engine id", ret);
1527 proto_tree_add_text(secur_tree, tvb, offset,
1528 length, "Authoritative Engine ID: %s",
1529 bytes_to_str(aengineid, aengineid_length));
1533 ret = asn1_uint32_decode (&asn1, &engineboots, &length);
1534 if (ret != ASN1_ERR_NOERROR) {
1535 dissect_snmp_parse_error(tvb, offset, pinfo,
1536 snmp_tree, "engine boots", ret);
1540 proto_tree_add_text(secur_tree, tvb,
1541 offset, length, "Engine Boots: %d",
1545 ret = asn1_uint32_decode (&asn1, &enginetime, &length);
1546 if (ret != ASN1_ERR_NOERROR) {
1547 dissect_snmp_parse_error(tvb, offset, pinfo,
1548 snmp_tree, "engine time", ret);
1552 proto_tree_add_text(secur_tree, tvb,
1553 offset, length, "Engine Time: %d",
1557 ret = asn1_octet_string_decode (&asn1, &username,
1558 &username_length, &length);
1559 if (ret != ASN1_ERR_NOERROR) {
1560 dissect_snmp_parse_error(tvb, offset, pinfo,
1561 snmp_tree, "user name", ret);
1565 proto_tree_add_text(secur_tree, tvb, offset,
1566 length, "User Name: %.*s",
1568 SAFE_STRING(username));
1572 ret = asn1_octet_string_decode (&asn1, &authpar,
1573 &authpar_length, &length);
1574 if (ret != ASN1_ERR_NOERROR) {
1575 dissect_snmp_parse_error(tvb, offset, pinfo,
1576 snmp_tree, "authentication parameter", ret);
1580 proto_tree_add_text(secur_tree, tvb, offset,
1581 length, "Authentication Parameter: %s",
1582 bytes_to_str(authpar, authpar_length));
1586 ret = asn1_octet_string_decode (&asn1, &privpar,
1587 &privpar_length, &length);
1588 if (ret != ASN1_ERR_NOERROR) {
1589 dissect_snmp_parse_error(tvb, offset, pinfo,
1590 snmp_tree, "privacy parameter", ret);
1594 proto_tree_add_text(secur_tree, tvb, offset,
1595 length, "Privacy Parameter: %s",
1596 bytes_to_str(privpar, privpar_length));
1602 ret = asn1_octet_string_decode (&asn1,
1603 &secparm, &secparm_length, &length);
1604 if (ret != ASN1_ERR_NOERROR) {
1605 dissect_snmp_parse_error(tvb, offset, pinfo,
1606 snmp_tree, "Message Security Parameters",
1611 proto_tree_add_text(snmp_tree, tvb, offset,
1613 "Message Security Parameters Data"
1614 " (%d bytes)", secparm_length);
1620 /* PDU starts here */
1622 ret = asn1_octet_string_decode (&asn1, &cryptpdu,
1623 &cryptpdu_length, &length);
1624 if (ret != ASN1_ERR_NOERROR) {
1625 dissect_snmp_parse_error(tvb, offset, pinfo,
1626 snmp_tree, "encrypted PDU header", ret);
1629 proto_tree_add_text(snmp_tree, tvb, offset, length,
1630 "Encrypted PDU (%d bytes)", length);
1632 if (check_col(pinfo->cinfo, COL_INFO))
1633 col_set_str(pinfo->cinfo, COL_INFO, "Encrypted PDU");
1636 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1637 if (ret != ASN1_ERR_NOERROR) {
1638 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1643 ret = asn1_octet_string_decode (&asn1, &cengineid,
1644 &cengineid_length, &length);
1645 if (ret != ASN1_ERR_NOERROR) {
1646 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1647 "context engine id", ret);
1651 proto_tree_add_text(snmp_tree, tvb, offset, length,
1652 "Context Engine ID: %s",
1653 bytes_to_str(cengineid, cengineid_length));
1657 ret = asn1_octet_string_decode (&asn1, &cname,
1658 &cname_length, &length);
1659 if (ret != ASN1_ERR_NOERROR) {
1660 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1661 "context name", ret);
1665 proto_tree_add_text(snmp_tree, tvb, offset, length,
1666 "Context Name: %.*s", cname_length,
1667 SAFE_STRING(cname));
1673 dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
1674 "PDU for unknown version of SNMP");
1678 start = asn1.offset;
1679 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1681 if (ret != ASN1_ERR_NOERROR) {
1682 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1686 if (cls != ASN1_CTX || con != ASN1_CON) {
1687 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1688 "PDU type", ASN1_ERR_WRONG_TYPE);
1691 dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
1695 dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1696 proto_tree *tree, int proto, gint ett)
1704 char *pdu_type_string;
1714 int password_length;
1716 guchar *application;
1717 int application_length;
1724 proto_tree *smux_tree = NULL;
1725 proto_item *item = NULL;
1729 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1730 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
1733 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
1734 smux_tree = proto_item_add_subtree(item, ett);
1737 /* NOTE: we have to parse the message piece by piece, since the
1738 * capture length may be less than the message length: a 'global'
1739 * parsing is likely to fail.
1741 /* parse the SNMP header */
1742 asn1_open(&asn1, tvb, offset);
1743 start = asn1.offset;
1744 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1746 if (ret != ASN1_ERR_NOERROR) {
1747 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1752 /* Dissect SMUX here */
1753 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
1754 pdu_type_string = val_to_str(pdu_type, smux_types,
1755 "Unknown PDU type %#x");
1756 if (check_col(pinfo->cinfo, COL_INFO))
1757 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1758 length = asn1.offset - start;
1760 proto_tree_add_text(smux_tree, tvb, offset, length,
1761 "PDU type: %s", pdu_type_string);
1764 ret = asn1_uint32_decode (&asn1, &version, &length);
1765 if (ret != ASN1_ERR_NOERROR) {
1766 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1771 proto_tree_add_text(smux_tree, tvb, offset, length,
1772 "Version: %d", version);
1776 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1777 if (ret != ASN1_ERR_NOERROR) {
1778 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1779 "registration OID", ret);
1783 oid_string = format_oid(regid, regid_length);
1784 proto_tree_add_text(smux_tree, tvb, offset, length,
1785 "Registration: %s", oid_string);
1791 ret = asn1_octet_string_decode (&asn1, &application,
1792 &application_length, &length);
1793 if (ret != ASN1_ERR_NOERROR) {
1794 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1795 "application", ret);
1799 proto_tree_add_text(smux_tree, tvb, offset, length,
1800 "Application: %.*s", application_length,
1801 SAFE_STRING(application));
1803 g_free(application);
1806 ret = asn1_octet_string_decode (&asn1, &password,
1807 &password_length, &length);
1808 if (ret != ASN1_ERR_NOERROR) {
1809 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1814 proto_tree_add_text(smux_tree, tvb, offset, length,
1815 "Password: %.*s", password_length,
1816 SAFE_STRING(password));
1822 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
1823 pdu_type_string = val_to_str(pdu_type, smux_types,
1824 "Unknown PDU type %#x");
1825 if (check_col(pinfo->cinfo, COL_INFO))
1826 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1827 length = asn1.offset - start;
1829 proto_tree_add_text(smux_tree, tvb, offset, length,
1830 "PDU type: %s", pdu_type_string);
1833 ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
1834 if (ret != ASN1_ERR_NOERROR) {
1835 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1840 proto_tree_add_text(smux_tree, tvb, offset,
1841 pdu_length, "Cause: %s",
1842 val_to_str(cause, smux_close,
1843 "Unknown cause %#x"));
1845 offset += pdu_length;
1848 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
1849 pdu_type_string = val_to_str(pdu_type, smux_types,
1850 "Unknown PDU type %#x");
1851 if (check_col(pinfo->cinfo, COL_INFO))
1852 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1853 length = asn1.offset - start;
1855 proto_tree_add_text(smux_tree, tvb, offset, length,
1856 "PDU type: %s", pdu_type_string);
1859 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1860 if (ret != ASN1_ERR_NOERROR) {
1861 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1862 "registration subtree", ret);
1866 oid_string = format_oid(regid, regid_length);
1867 proto_tree_add_text(smux_tree, tvb, offset, length,
1868 "Registration: %s", oid_string);
1874 ret = asn1_uint32_decode (&asn1, &priority, &length);
1875 if (ret != ASN1_ERR_NOERROR) {
1876 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1881 proto_tree_add_text(smux_tree, tvb, offset, length,
1882 "Priority: %d", priority);
1886 ret = asn1_uint32_decode (&asn1, &operation, &length);
1887 if (ret != ASN1_ERR_NOERROR) {
1888 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1893 proto_tree_add_text(smux_tree, tvb, offset, length,
1895 val_to_str(operation, smux_rreq,
1896 "Unknown operation %#x"));
1901 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
1902 pdu_type_string = val_to_str(pdu_type, smux_types,
1903 "Unknown PDU type %#x");
1904 if (check_col(pinfo->cinfo, COL_INFO))
1905 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1906 length = asn1.offset - start;
1908 proto_tree_add_text(smux_tree, tvb, offset, length,
1909 "PDU type: %s", pdu_type_string);
1912 ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
1913 if (ret != ASN1_ERR_NOERROR) {
1914 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1919 proto_tree_add_text(smux_tree, tvb, offset,
1921 val_to_str(priority, smux_prio,
1924 offset += pdu_length;
1927 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
1928 pdu_type_string = val_to_str(pdu_type, smux_types,
1929 "Unknown PDU type %#x");
1930 if (check_col(pinfo->cinfo, COL_INFO))
1931 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1932 length = asn1.offset - start;
1934 proto_tree_add_text(smux_tree, tvb, offset, length,
1935 "PDU type: %s", pdu_type_string);
1938 ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
1939 if (ret != ASN1_ERR_NOERROR) {
1940 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1945 proto_tree_add_text(smux_tree, tvb, offset,
1947 val_to_str(commit, smux_sout,
1948 "Unknown SOUT Value: %#x"));
1950 offset += pdu_length;
1953 if (cls != ASN1_CTX || con != ASN1_CON) {
1954 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1955 "PDU type", ASN1_ERR_WRONG_TYPE);
1958 dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
1962 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1964 conversation_t *conversation;
1967 * The first SNMP packet goes to the SNMP port; the second one
1968 * may come from some *other* port, but goes back to the same
1969 * IP address and port as the ones from which the first packet
1970 * came; all subsequent packets presumably go between those two
1971 * IP addresses and ports.
1973 * If this packet went to the SNMP port, we check to see if
1974 * there's already a conversation with one address/port pair
1975 * matching the source IP address and port of this packet,
1976 * the other address matching the destination IP address of this
1977 * packet, and any destination port.
1979 * If not, we create one, with its address 1/port 1 pair being
1980 * the source address/port of this packet, its address 2 being
1981 * the destination address of this packet, and its port 2 being
1982 * wildcarded, and give it the SNMP dissector as a dissector.
1984 if (pinfo->destport == UDP_PORT_SNMP) {
1985 conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
1986 pinfo->srcport, 0, NO_PORT_B);
1987 if (conversation == NULL) {
1988 conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
1989 pinfo->srcport, 0, NO_PORT2);
1990 conversation_set_dissector(conversation, snmp_handle);
1994 dissect_snmp_pdu(tvb, 0, pinfo, tree, "SNMP", proto_snmp, ett_snmp);
1998 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2000 dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
2004 proto_register_snmp(void)
2006 static hf_register_info hf[] = {
2008 { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
2010 { &hf_snmpv3_flags_auth,
2011 { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
2012 TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
2013 { &hf_snmpv3_flags_crypt,
2014 { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
2015 TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
2016 { &hf_snmpv3_flags_report,
2017 { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
2018 TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
2020 static gint *ett[] = {
2024 &ett_parameters_qos,
2030 #ifdef HAVE_SOME_SNMP
2032 * Suppress warnings about unknown tokens - we aren't initializing
2033 * UCD SNMP in its entirety, we're just initializing the
2034 * MIB-handling part because that's all we're using, which
2035 * means that entries in the configuration file for other
2036 * pars of the library will not be handled, and we don't want
2037 * the config file reading code to whine about that.
2039 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
2040 NETSNMP_DS_LIB_NO_TOKEN_WARNINGS, TRUE);
2041 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
2042 NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 2);
2043 register_mib_handlers();
2044 read_premib_configs();
2047 #endif /* HAVE_SOME_SNMP */
2048 proto_snmp = proto_register_protocol("Simple Network Management Protocol",
2050 proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2052 proto_register_field_array(proto_snmp, hf, array_length(hf));
2053 proto_register_subtree_array(ett, array_length(ett));
2054 snmp_handle = create_dissector_handle(dissect_snmp, proto_snmp);
2058 proto_reg_handoff_snmp(void)
2060 dissector_handle_t smux_handle;
2062 dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
2063 dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
2064 smux_handle = create_dissector_handle(dissect_smux, proto_smux);
2065 dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);
2066 dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
2067 dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
2068 dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
2069 data_handle = find_dissector("data");