2 * Routines for SNMP (simple network management protocol)
3 * Copyright (C) 1998 Didier Jorand
5 * See RFC 1157 for SNMPv1.
7 * See RFCs 1901, 1905, and 1906 for SNMPv2c.
9 * See RFCs 1905, 1906, 1909, and 1910 for SNMPv2u.
11 * $Id: packet-snmp.c,v 1.75 2001/12/03 03:59:39 guy Exp $
13 * Ethereal - Network traffic analyzer
14 * By Gerald Combs <gerald@ethereal.com>
15 * Copyright 1998 Gerald Combs
19 * GXSNMP -- An snmp mangament application
20 * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
21 * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version 2
26 * of the License, or (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #ifdef HAVE_SYS_TYPES_H
47 # include <sys/types.h>
50 #ifdef HAVE_NETINET_IN_H
51 # include <netinet/in.h>
54 #define MAX_STRING_LEN 2048 /* TBC */
64 #include "conversation.h"
66 #include "packet-ipx.h"
68 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
72 # if defined(HAVE_UCD_SNMP_SNMP_H)
76 # include <ucd-snmp/asn1.h>
77 # include <ucd-snmp/snmp_api.h>
78 # include <ucd-snmp/snmp_impl.h>
79 # include <ucd-snmp/mib.h>
82 * Sigh. UCD SNMP 4.1.1 makes "snmp_set_suffix_only()" a macro
83 * that calls "ds_set_int()" with the first two arguments
84 * being DS_LIBRARY_ID and DS_LIB_PRINT_SUFFIX_ONLY; this means that,
85 * when building with 4.1.1, we need to arrange that
86 * <ucd-snmp/default_store.h> is included, to define those two values
87 * and to declare "ds_int()".
91 * 1) we can't include it on earlier versions (at least not 3.6.2),
92 * as it doesn't exist in those versions;
94 * 2) we don't want to include <ucd-snmp/ucd-snmp-includes.h>,
95 * as that includes <ucd-snmp/snmp.h>, and that defines a whole
96 * bunch of values that we also define ourselves.
98 * So we only include it if "snmp_set_suffix_only" is defined as
101 # ifdef snmp_set_suffix_only
102 # include <ucd-snmp/default_store.h>
106 * XXX - for now, we assume all versions of UCD SNMP have it.
108 # define HAVE_SPRINT_VALUE
111 * Define values "sprint_value()" expects.
113 # define VALTYPE_INTEGER ASN_INTEGER
114 # define VALTYPE_COUNTER ASN_COUNTER
115 # define VALTYPE_GAUGE ASN_GAUGE
116 # define VALTYPE_TIMETICKS ASN_TIMETICKS
117 # define VALTYPE_STRING ASN_OCTET_STR
118 # define VALTYPE_IPADDR ASN_IPADDRESS
119 # define VALTYPE_OPAQUE ASN_OPAQUE
120 # define VALTYPE_NSAP ASN_NSAP
121 # define VALTYPE_OBJECTID ASN_OBJECT_ID
122 # define VALTYPE_BITSTR ASN_BIT_STR
123 # define VALTYPE_COUNTER64 ASN_COUNTER64
124 # elif defined(HAVE_SNMP_SNMP_H)
128 # include <snmp/snmp.h>
131 * Some older versions of CMU SNMP may lack these values (e.g., the
132 * "libsnmp3.6" package for Debian, which is based on some old
133 * CMU SNMP, perhaps 1.0); for now, we assume they also lack
137 # define HAVE_SPRINT_VALUE
139 * Define values "sprint_value()" expects.
141 # define VALTYPE_INTEGER SMI_INTEGER
142 # define VALTYPE_COUNTER SMI_COUNTER32
143 # define VALTYPE_GAUGE SMI_GAUGE32
144 # define VALTYPE_TIMETICKS SMI_TIMETICKS
145 # define VALTYPE_STRING SMI_STRING
146 # define VALTYPE_IPADDR SMI_IPADDRESS
147 # define VALTYPE_OPAQUE SMI_OPAQUE
148 # define VALTYPE_NSAP SMI_STRING
149 # define VALTYPE_OBJECTID SMI_OBJID
150 # define VALTYPE_BITSTR ASN_BIT_STR
151 # define VALTYPE_COUNTER64 SMI_COUNTER64
154 * Now undo all the definitions they "helpfully" gave us, so we don't get
155 * complaints about redefining them.
157 * Why, oh why, is there no library that provides code to
161 * 2) translate object IDs into names;
163 * 3) let you find out, for a given object ID, what the type, enum
164 * values, display hint, etc. are;
166 * in a *simple* fashion, without assuming that your code is part of an
167 * SNMP agent or client that wants a pile of definitions of PDU types,
168 * etc.? Is it just that 99 44/100% of the code that uses an SNMP library
169 * *is* part of an agent or client, and really *does* need that stuff,
170 * and *doesn't* need the interfaces we want?
172 # undef SNMP_ERR_NOERROR
173 # undef SNMP_ERR_TOOBIG
174 # undef SNMP_ERR_NOSUCHNAME
175 # undef SNMP_ERR_BADVALUE
176 # undef SNMP_ERR_READONLY
177 # undef SNMP_ERR_NOACCESS
178 # undef SNMP_ERR_WRONGTYPE
179 # undef SNMP_ERR_WRONGLENGTH
180 # undef SNMP_ERR_WRONGENCODING
181 # undef SNMP_ERR_WRONGVALUE
182 # undef SNMP_ERR_NOCREATION
183 # undef SNMP_ERR_INCONSISTENTVALUE
184 # undef SNMP_ERR_RESOURCEUNAVAILABLE
185 # undef SNMP_ERR_COMMITFAILED
186 # undef SNMP_ERR_UNDOFAILED
187 # undef SNMP_ERR_AUTHORIZATIONERROR
188 # undef SNMP_ERR_NOTWRITABLE
189 # undef SNMP_ERR_INCONSISTENTNAME
190 # undef SNMP_TRAP_COLDSTART
191 # undef SNMP_TRAP_WARMSTART
192 # undef SNMP_TRAP_LINKDOWN
193 # undef SNMP_TRAP_LINKUP
194 # undef SNMP_TRAP_EGPNEIGHBORLOSS
195 # undef SNMP_TRAP_ENTERPRISESPECIFIC
201 #include "packet-snmp.h"
203 /* Null string of type "guchar[]". */
204 static const guchar nullstring[] = "";
206 /* Take a pointer that may be null and return a pointer that's not null
207 by turning null pointers into pointers to the above null string. */
208 #define SAFE_STRING(s) (((s) != NULL) ? (s) : nullstring)
210 static int proto_snmp = -1;
211 static int proto_smux = -1;
213 static gint ett_snmp = -1;
214 static gint ett_smux = -1;
215 static gint ett_parameters = -1;
216 static gint ett_parameters_qos = -1;
217 static gint ett_global = -1;
218 static gint ett_flags = -1;
219 static gint ett_secur = -1;
221 static int hf_snmpv3_flags = -1;
222 static int hf_snmpv3_flags_auth = -1;
223 static int hf_snmpv3_flags_crypt = -1;
224 static int hf_snmpv3_flags_report = -1;
226 static dissector_handle_t snmp_handle;
227 static dissector_handle_t data_handle;
230 #define TH_CRYPT 0x02
231 #define TH_REPORT 0x04
233 static const true_false_string flags_set_truth = {
238 #define UDP_PORT_SNMP 161
239 #define UDP_PORT_SNMP_TRAP 162
240 #define TCP_PORT_SMUX 199
242 /* Protocol version numbers */
243 #define SNMP_VERSION_1 0
244 #define SNMP_VERSION_2c 1
245 #define SNMP_VERSION_2u 2
246 #define SNMP_VERSION_3 3
248 static const value_string versions[] = {
249 { SNMP_VERSION_1, "1" },
250 { SNMP_VERSION_2c, "2C" },
251 { SNMP_VERSION_2u, "2U" },
252 { SNMP_VERSION_3, "3" },
257 #define SNMP_MSG_GET 0
258 #define SNMP_MSG_GETNEXT 1
259 #define SNMP_MSG_RESPONSE 2
260 #define SNMP_MSG_SET 3
261 #define SNMP_MSG_TRAP 4
263 #define SNMP_MSG_GETBULK 5
264 #define SNMP_MSG_INFORM 6
265 #define SNMP_MSG_TRAP2 7
266 #define SNMP_MSG_REPORT 8
268 static const value_string pdu_types[] = {
269 { SNMP_MSG_GET, "GET" },
270 { SNMP_MSG_GETNEXT, "GET-NEXT" },
271 { SNMP_MSG_SET, "SET" },
272 { SNMP_MSG_RESPONSE, "RESPONSE" },
273 { SNMP_MSG_TRAP, "TRAP-V1" },
274 { SNMP_MSG_GETBULK, "GETBULK" },
275 { SNMP_MSG_INFORM, "INFORM" },
276 { SNMP_MSG_TRAP2, "TRAP-V2" },
277 { SNMP_MSG_REPORT, "REPORT" },
282 #define SMUX_MSG_OPEN 0
283 #define SMUX_MSG_CLOSE 1
284 #define SMUX_MSG_RREQ 2
285 #define SMUX_MSG_RRSP 3
286 #define SMUX_MSG_SOUT 4
288 static const value_string smux_types[] = {
289 { SMUX_MSG_OPEN, "Open" },
290 { SMUX_MSG_CLOSE, "Close" },
291 { SMUX_MSG_RREQ, "Registration Request" },
292 { SMUX_MSG_RRSP, "Registration Response" },
293 { SMUX_MSG_SOUT, "Commit Or Rollback" },
297 /* SMUX Closing causes */
298 #define SMUX_CLOSE_DOWN 0
299 #define SMUX_CLOSE_VERSION 1
300 #define SMUX_CLOSE_PACKET 2
301 #define SMUX_CLOSE_PROTOCOL 3
302 #define SMUX_CLOSE_INTERNAL 4
303 #define SMUX_CLOSE_NOAUTH 5
305 static const value_string smux_close[] = {
306 { SMUX_CLOSE_DOWN, "Going down" },
307 { SMUX_CLOSE_VERSION, "Unsupported Version" },
308 { SMUX_CLOSE_PACKET, "Packet Format Error" },
309 { SMUX_CLOSE_PROTOCOL, "Protocol Error" },
310 { SMUX_CLOSE_INTERNAL, "Internal Error" },
311 { SMUX_CLOSE_NOAUTH, "Unauthorized" },
315 /* SMUX Request codes */
316 #define SMUX_RREQ_DELETE 0
317 #define SMUX_RREQ_READONLY 1
318 #define SMUX_RREQ_READWRITE 2
320 static const value_string smux_rreq[] = {
321 { SMUX_RREQ_DELETE, "Delete" },
322 { SMUX_RREQ_READONLY, "Read Only" },
323 { SMUX_RREQ_READWRITE, "Read Write" },
327 static const value_string smux_prio[] = {
332 /* SMUX SOut codes */
333 #define SMUX_SOUT_COMMIT 0
334 #define SMUX_SOUT_ROLLBACK 1
336 static const value_string smux_sout[] = {
337 { SMUX_SOUT_COMMIT, "Commit" },
338 { SMUX_SOUT_ROLLBACK, "Rollback" },
342 /* Error status values */
343 #define SNMP_ERR_NOERROR 0
344 #define SNMP_ERR_TOOBIG 1
345 #define SNMP_ERR_NOSUCHNAME 2
346 #define SNMP_ERR_BADVALUE 3
347 #define SNMP_ERR_READONLY 4
348 #define SNMP_ERR_GENERROR 5
350 #define SNMP_ERR_NOACCESS 6
351 #define SNMP_ERR_WRONGTYPE 7
352 #define SNMP_ERR_WRONGLENGTH 8
353 #define SNMP_ERR_WRONGENCODING 9
354 #define SNMP_ERR_WRONGVALUE 10
355 #define SNMP_ERR_NOCREATION 11
356 #define SNMP_ERR_INCONSISTENTVALUE 12
357 #define SNMP_ERR_RESOURCEUNAVAILABLE 13
358 #define SNMP_ERR_COMMITFAILED 14
359 #define SNMP_ERR_UNDOFAILED 15
360 #define SNMP_ERR_AUTHORIZATIONERROR 16
361 #define SNMP_ERR_NOTWRITABLE 17
362 #define SNMP_ERR_INCONSISTENTNAME 18
364 static const value_string error_statuses[] = {
365 { SNMP_ERR_NOERROR, "NO ERROR" },
366 { SNMP_ERR_TOOBIG, "TOOBIG" },
367 { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" },
368 { SNMP_ERR_BADVALUE, "BAD VALUE" },
369 { SNMP_ERR_READONLY, "READ ONLY" },
370 { SNMP_ERR_GENERROR, "GENERIC ERROR" },
371 { SNMP_ERR_NOACCESS, "NO ACCESS" },
372 { SNMP_ERR_WRONGTYPE, "WRONG TYPE" },
373 { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" },
374 { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" },
375 { SNMP_ERR_WRONGVALUE, "WRONG VALUE" },
376 { SNMP_ERR_NOCREATION, "NO CREATION" },
377 { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" },
378 { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" },
379 { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" },
380 { SNMP_ERR_UNDOFAILED, "UNDO FAILED" },
381 { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" },
382 { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" },
383 { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" },
387 /* General SNMP V1 Traps */
389 #define SNMP_TRAP_COLDSTART 0
390 #define SNMP_TRAP_WARMSTART 1
391 #define SNMP_TRAP_LINKDOWN 2
392 #define SNMP_TRAP_LINKUP 3
393 #define SNMP_TRAP_AUTHFAIL 4
394 #define SNMP_TRAP_EGPNEIGHBORLOSS 5
395 #define SNMP_TRAP_ENTERPRISESPECIFIC 6
397 static const value_string trap_types[] = {
398 { SNMP_TRAP_COLDSTART, "COLD START" },
399 { SNMP_TRAP_WARMSTART, "WARM START" },
400 { SNMP_TRAP_LINKDOWN, "LINK DOWN" },
401 { SNMP_TRAP_LINKUP, "LINK UP" },
402 { SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
403 { SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
404 { SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
408 /* Security Models */
410 #define SNMP_SEC_ANY 0
411 #define SNMP_SEC_V1 1
412 #define SNMP_SEC_V2C 2
413 #define SNMP_SEC_USM 3
415 static const value_string sec_models[] = {
416 { SNMP_SEC_ANY, "Any" },
417 { SNMP_SEC_V1, "V1" },
418 { SNMP_SEC_V2C, "V2C" },
419 { SNMP_SEC_USM, "USM" },
425 #define SNMP_IPA 0 /* IP Address */
426 #define SNMP_CNT 1 /* Counter (Counter32) */
427 #define SNMP_GGE 2 /* Gauge (Gauge32) */
428 #define SNMP_TIT 3 /* TimeTicks */
429 #define SNMP_OPQ 4 /* Opaque */
430 #define SNMP_NSP 5 /* NsapAddress */
431 #define SNMP_C64 6 /* Counter64 */
432 #define SNMP_U32 7 /* Uinteger32 */
441 #define SNMP_INTEGER 1 /* l */
442 #define SNMP_OCTETSTR 2 /* c */
443 #define SNMP_DISPLAYSTR 2 /* c */
444 #define SNMP_OBJECTID 3 /* ul */
445 #define SNMP_IPADDR 4 /* uc */
446 #define SNMP_COUNTER 5 /* ul */
447 #define SNMP_GAUGE 6 /* ul */
448 #define SNMP_TIMETICKS 7 /* ul */
449 #define SNMP_OPAQUE 8 /* c */
451 /* additional SNMPv2 Types */
453 #define SNMP_UINTEGER 5 /* ul */
454 #define SNMP_BITSTR 9 /* uc */
455 #define SNMP_NSAP 10 /* uc */
456 #define SNMP_COUNTER64 11 /* ul */
457 #define SNMP_NOSUCHOBJECT 12
458 #define SNMP_NOSUCHINSTANCE 13
459 #define SNMP_ENDOFMIBVIEW 14
461 typedef struct _SNMP_CNV SNMP_CNV;
471 static SNMP_CNV SnmpCnv [] =
473 {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"},
474 {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"},
475 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"},
476 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"},
477 {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"},
478 {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */
479 {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */
480 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"},
481 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"},
483 /* SNMPv2 data types and errors */
485 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"},
486 {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"},
487 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"},
488 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"},
489 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"},
494 * NAME: g_snmp_tag_cls2syntax
495 * SYNOPSIS: gboolean g_snmp_tag_cls2syntax
501 * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name.
502 * See SnmpCnv for conversion.
503 * RETURNS: name on success, NULL on failure
507 snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
512 while (cnv->syntax != -1)
514 if (cnv->tag == tag && cnv->class == cls)
516 *syntax = cnv->syntax;
525 dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
526 proto_tree *tree, const char *field_name, int ret)
532 case ASN1_ERR_EOC_MISMATCH:
533 errstr = "EOC mismatch";
536 case ASN1_ERR_WRONG_TYPE:
537 errstr = "Wrong type for that item";
540 case ASN1_ERR_LENGTH_NOT_DEFINITE:
541 errstr = "Length was indefinite";
544 case ASN1_ERR_LENGTH_MISMATCH:
545 errstr = "Length mismatch";
548 case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
549 errstr = "Wrong length for that item's type";
553 errstr = "Unknown error";
557 if (check_col(pinfo->fd, COL_INFO)) {
558 col_add_fstr(pinfo->fd, COL_INFO,
559 "ERROR: Couldn't parse %s: %s", field_name, errstr);
562 proto_tree_add_text(tree, tvb, offset, 0,
563 "ERROR: Couldn't parse %s: %s", field_name, errstr);
564 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, tree);
569 dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
570 proto_tree *tree, const char *message)
572 if (check_col(pinfo->fd, COL_INFO))
573 col_add_str(pinfo->fd, COL_INFO, message);
576 proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
577 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, tree);
582 format_oid(subid_t *oid, guint oid_length)
590 result_len = oid_length * 22;
591 result = g_malloc(result_len + 1);
593 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
595 for (i = 1; i < oid_length;i++) {
596 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
602 #ifdef HAVE_SPRINT_VALUE
604 format_var(struct variable_list *variable, subid_t *variable_oid,
605 guint variable_oid_length, gushort vb_type, guint vb_length)
615 /* We don't know how long this will be, but let's guess it
616 fits within 128 characters; that should be enough for an
617 integral value plus some sort of type indication. */
627 /* We don't know how long this will be, but let's guess it
628 fits within 128 characters plus 4 characters per octet. */
629 buf = g_malloc(128 + 4*vb_length);
633 /* We don't know how long this will be, but let's guess it
634 fits within 128 characters plus 32 characters per subid
635 (10 digits plus period, or a subid name). */
636 buf = g_malloc(1024 + 32*vb_length);
640 /* Should not happen. */
641 g_assert_not_reached();
646 variable->next_variable = NULL;
647 variable->name = variable_oid;
648 variable->name_length = variable_oid_length;
652 variable->type = VALTYPE_INTEGER;
656 variable->type = VALTYPE_COUNTER;
660 variable->type = VALTYPE_GAUGE;
664 variable->type = VALTYPE_TIMETICKS;
668 variable->type = VALTYPE_STRING;
672 variable->type = VALTYPE_IPADDR;
676 variable->type = VALTYPE_OPAQUE;
680 variable->type = VALTYPE_NSAP;
684 variable->type = VALTYPE_OBJECTID;
685 vb_length *= sizeof (subid_t); /* XXX - necessary? */
689 variable->type = VALTYPE_BITSTR;
693 variable->type = VALTYPE_COUNTER64;
696 variable->val_len = vb_length;
698 sprint_value(buf, variable_oid, variable_oid_length, variable);
704 snmp_variable_decode(proto_tree *snmp_tree, subid_t *variable_oid,
705 guint variable_oid_length, ASN1_SCK *asn1, int offset, guint *lengthp,
717 gint32 vb_integer_value;
718 guint32 vb_uinteger_value;
720 guint8 *vb_octet_string;
725 gchar *vb_display_string;
727 #ifdef HAVE_SPRINT_VALUE
728 struct variable_list variable;
729 #if defined(HAVE_UCD_SNMP_SNMP_H)
732 #endif /* HAVE_SPRINT_VALUE */
737 /* parse the type of the object */
738 start = asn1->offset;
739 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
740 if (ret != ASN1_ERR_NOERROR)
743 return ASN1_ERR_LENGTH_NOT_DEFINITE;
745 /* Convert the class, constructed flag, and tag to a type. */
746 vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
747 if (vb_type_name == NULL) {
750 * Dissect the value as an opaque string of octets.
752 vb_type_name = "unsupported type";
753 vb_type = SNMP_OPAQUE;
756 /* parse the value */
760 ret = asn1_int32_value_decode(asn1, vb_length,
762 if (ret != ASN1_ERR_NOERROR)
764 length = asn1->offset - start;
766 #ifdef HAVE_SPRINT_VALUE
768 #if defined(HAVE_UCD_SNMP_SNMP_H)
769 value = vb_integer_value;
770 variable.val.integer = &value;
771 #elif defined(HAVE_SNMP_SNMP_H)
772 variable.val.integer = &vb_integer_value;
774 vb_display_string = format_var(&variable,
775 variable_oid, variable_oid_length, vb_type,
777 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
779 "Value: %s", vb_display_string);
780 g_free(vb_display_string);
781 break; /* we added formatted version to the tree */
783 #endif /* HAVE_SPRINT_VALUE */
784 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
785 "Value: %s: %d (%#x)", vb_type_name,
786 vb_integer_value, vb_integer_value);
793 ret = asn1_uint32_value_decode(asn1, vb_length,
795 if (ret != ASN1_ERR_NOERROR)
797 length = asn1->offset - start;
799 #ifdef HAVE_SPRINT_VALUE
801 #if defined(HAVE_UCD_SNMP_SNMP_H)
802 value = vb_uinteger_value;
803 variable.val.integer = &value;
804 #elif defined(HAVE_SNMP_SNMP_H)
805 variable.val.integer = &vb_uinteger_value;
807 vb_display_string = format_var(&variable,
808 variable_oid, variable_oid_length, vb_type,
810 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
812 "Value: %s", vb_display_string);
813 g_free(vb_display_string);
814 break; /* we added formatted version to the tree */
816 #endif /* HAVE_SPRINT_VALUE */
817 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
818 "Value: %s: %u (%#x)", vb_type_name,
819 vb_uinteger_value, vb_uinteger_value);
829 ret = asn1_string_value_decode (asn1, vb_length,
831 if (ret != ASN1_ERR_NOERROR)
833 length = asn1->offset - start;
835 #ifdef HAVE_SPRINT_VALUE
837 variable.val.string = vb_octet_string;
838 vb_display_string = format_var(&variable,
839 variable_oid, variable_oid_length, vb_type,
841 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
843 "Value: %s", vb_display_string);
844 g_free(vb_display_string);
845 break; /* we added formatted version to the tree */
847 #endif /* HAVE_SPRINT_VALUE */
849 * If some characters are not printable, display
850 * the string as bytes.
852 for (i = 0; i < vb_length; i++) {
853 if (!(isprint(vb_octet_string[i])
854 || isspace(vb_octet_string[i])))
859 * We stopped, due to a non-printable
860 * character, before we got to the end
863 vb_display_string = g_malloc(4*vb_length);
864 buf = &vb_display_string[0];
865 len = sprintf(buf, "%03u", vb_octet_string[0]);
867 for (i = 1; i < vb_length; i++) {
868 len = sprintf(buf, ".%03u",
872 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
873 "Value: %s: %s", vb_type_name,
875 g_free(vb_display_string);
877 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
878 "Value: %s: %.*s", vb_type_name,
880 SAFE_STRING(vb_octet_string));
883 g_free(vb_octet_string);
887 ret = asn1_null_decode (asn1, vb_length);
888 if (ret != ASN1_ERR_NOERROR)
890 length = asn1->offset - start;
892 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
893 "Value: %s", vb_type_name);
898 ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
900 if (ret != ASN1_ERR_NOERROR)
902 length = asn1->offset - start;
904 #ifdef HAVE_SPRINT_VALUE
906 variable.val.objid = vb_oid;
907 vb_display_string = format_var(&variable,
908 variable_oid, variable_oid_length, vb_type,
910 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
912 "Value: %s", vb_display_string);
913 break; /* we added formatted version to the tree */
915 #endif /* HAVE_SPRINT_VALUE */
916 vb_display_string = format_oid(vb_oid, vb_oid_length);
917 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
918 "Value: %s: %s", vb_type_name, vb_display_string);
919 g_free(vb_display_string);
924 case SNMP_NOSUCHOBJECT:
925 length = asn1->offset - start;
927 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
928 "Value: %s: no such object", vb_type_name);
932 case SNMP_NOSUCHINSTANCE:
933 length = asn1->offset - start;
935 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
936 "Value: %s: no such instance", vb_type_name);
940 case SNMP_ENDOFMIBVIEW:
941 length = asn1->offset - start;
943 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
944 "Value: %s: end of mib view", vb_type_name);
949 g_assert_not_reached();
950 return ASN1_ERR_WRONG_TYPE;
953 return ASN1_ERR_NOERROR;
957 dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
958 proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
962 guint sequence_length;
966 guint32 error_status;
970 char *pdu_type_string;
973 guint enterprise_length;
975 guint8 *agent_address;
976 guint agent_address_length;
980 guint32 specific_type;
983 guint timestamp_length;
987 guint variable_bindings_length;
990 guint variable_length;
991 subid_t *variable_oid;
992 guint variable_oid_length;
993 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
994 gchar vb_oid_string[MAX_STRING_LEN]; /* TBC */
1001 pdu_type_string = val_to_str(pdu_type, pdu_types,
1002 "Unknown PDU type %#x");
1003 if (check_col(pinfo->fd, COL_INFO))
1004 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1005 length = asn1.offset - start;
1007 proto_tree_add_text(tree, tvb, offset, length,
1008 "PDU type: %s", pdu_type_string);
1012 /* get the fields in the PDU preceeding the variable-bindings sequence */
1016 case SNMP_MSG_GETNEXT:
1017 case SNMP_MSG_RESPONSE:
1019 case SNMP_MSG_GETBULK:
1020 case SNMP_MSG_INFORM:
1021 case SNMP_MSG_TRAP2:
1022 case SNMP_MSG_REPORT:
1024 ret = asn1_uint32_decode (&asn1, &request_id, &length);
1025 if (ret != ASN1_ERR_NOERROR) {
1026 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1031 proto_tree_add_text(tree, tvb, offset, length,
1032 "Request Id: %#x", request_id);
1036 /* error status, or getbulk non-repeaters */
1037 ret = asn1_uint32_decode (&asn1, &error_status, &length);
1038 if (ret != ASN1_ERR_NOERROR) {
1039 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1040 (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
1046 if (pdu_type == SNMP_MSG_GETBULK) {
1047 proto_tree_add_text(tree, tvb, offset,
1048 length, "Non-repeaters: %u", error_status);
1050 proto_tree_add_text(tree, tvb, offset,
1051 length, "Error Status: %s",
1052 val_to_str(error_status, error_statuses,
1058 /* error index, or getbulk max-repetitions */
1059 ret = asn1_uint32_decode (&asn1, &error_index, &length);
1060 if (ret != ASN1_ERR_NOERROR) {
1061 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1062 (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
1068 if (pdu_type == SNMP_MSG_GETBULK) {
1069 proto_tree_add_text(tree, tvb, offset,
1070 length, "Max repetitions: %u", error_index);
1072 proto_tree_add_text(tree, tvb, offset,
1073 length, "Error Index: %u", error_index);
1081 ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
1083 if (ret != ASN1_ERR_NOERROR) {
1084 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1085 "enterprise OID", ret);
1089 oid_string = format_oid(enterprise, enterprise_length);
1090 proto_tree_add_text(tree, tvb, offset, length,
1091 "Enterprise: %s", oid_string);
1098 start = asn1.offset;
1099 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1100 &def, &agent_address_length);
1101 if (ret != ASN1_ERR_NOERROR) {
1102 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1103 "agent address", ret);
1106 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
1107 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
1108 /* GXSNMP 0.0.15 says the latter is "needed for
1110 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1111 "agent_address", ASN1_ERR_WRONG_TYPE);
1114 if (agent_address_length != 4) {
1115 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1116 "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
1119 ret = asn1_string_value_decode (&asn1,
1120 agent_address_length, &agent_address);
1121 if (ret != ASN1_ERR_NOERROR) {
1122 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1123 "agent address", ret);
1126 length = asn1.offset - start;
1128 if (agent_address_length != 4) {
1129 proto_tree_add_text(tree, tvb, offset,
1131 "Agent address: <length is %u, not 4>",
1132 agent_address_length);
1134 proto_tree_add_text(tree, tvb, offset,
1136 "Agent address: %s",
1137 ip_to_str(agent_address));
1140 g_free(agent_address);
1143 /* generic trap type */
1144 ret = asn1_uint32_decode (&asn1, &trap_type, &length);
1145 if (ret != ASN1_ERR_NOERROR) {
1146 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1147 "generic trap type", ret);
1151 proto_tree_add_text(tree, tvb, offset, length,
1153 val_to_str(trap_type, trap_types, "Unknown (%u)"));
1157 /* specific trap type */
1158 ret = asn1_uint32_decode (&asn1, &specific_type, &length);
1159 if (ret != ASN1_ERR_NOERROR) {
1160 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1161 "specific trap type", ret);
1165 proto_tree_add_text(tree, tvb, offset, length,
1166 "Specific trap type: %u (%#x)",
1167 specific_type, specific_type);
1172 start = asn1.offset;
1173 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1174 &def, ×tamp_length);
1175 if (ret != ASN1_ERR_NOERROR) {
1176 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1180 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
1181 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
1182 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1183 "timestamp", ASN1_ERR_WRONG_TYPE);
1186 ret = asn1_uint32_value_decode(&asn1, timestamp_length,
1188 if (ret != ASN1_ERR_NOERROR) {
1189 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1193 length = asn1.offset - start;
1195 proto_tree_add_text(tree, tvb, offset, length,
1196 "Timestamp: %u", timestamp);
1202 /* variable bindings */
1203 /* get header for variable-bindings sequence */
1204 ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
1205 if (ret != ASN1_ERR_NOERROR) {
1206 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1207 "variable bindings header", ret);
1212 /* loop on variable bindings */
1214 while (variable_bindings_length > 0) {
1216 sequence_length = 0;
1219 ret = asn1_sequence_decode(&asn1, &variable_length, &length);
1220 if (ret != ASN1_ERR_NOERROR) {
1221 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1222 "variable binding header", ret);
1225 sequence_length += length;
1227 /* parse object identifier */
1228 ret = asn1_oid_decode (&asn1, &variable_oid,
1229 &variable_oid_length, &length);
1230 if (ret != ASN1_ERR_NOERROR) {
1231 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1232 "variable binding OID", ret);
1235 sequence_length += length;
1239 oid_string = format_oid(variable_oid,
1240 variable_oid_length);
1242 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
1243 sprint_objid(vb_oid_string, variable_oid,
1244 variable_oid_length);
1245 proto_tree_add_text(tree, tvb, offset, sequence_length,
1246 "Object identifier %d: %s (%s)", vb_index,
1247 oid_string, vb_oid_string);
1248 #ifdef HAVE_SNMP_SNMP_H
1250 * CMU SNMP has a bug wherein "sprint_value()"
1251 * calls "get_symbol()", passing it the
1252 * OID supplied, to get an information about the
1253 * variable, and blithely assumes that it will
1254 * never get a null pointer back and dereferences
1255 * the resulting pointer.
1257 * Not true. If there's nothing in the MIB
1258 * about *any* of the components of the OID,
1259 * it'll return a null pointer.
1261 * So we have to check for that, and pass
1262 * down to "snmp_variable_decode" a flag
1263 * saying "don't pass this to 'sprint_value()'.
1265 * We check for that by looking for a decoded
1266 * OID string beginning with "." followed by a
1267 * digit, meaning it couldn't even find any
1268 * symbolic representation for the very
1269 * beginning of the OID string.
1271 if (vb_oid_string[0] == '.' &&
1272 isdigit((guchar)vb_oid_string[1]))
1274 #endif /* HAVE_SNMP_SNMP_H */
1275 #else /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
1276 proto_tree_add_text(tree, tvb, offset, sequence_length,
1277 "Object identifier %d: %s", vb_index,
1279 #endif /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
1282 offset += sequence_length;
1283 variable_bindings_length -= sequence_length;
1285 /* Parse the variable's value */
1286 ret = snmp_variable_decode(tree, variable_oid,
1287 variable_oid_length, &asn1, offset, &length,
1289 if (ret != ASN1_ERR_NOERROR) {
1290 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1295 variable_bindings_length -= length;
1299 static const value_string qos_vals[] = {
1300 { 0x0, "No authentication or privacy" },
1301 { 0x1, "Authentication, no privacy" },
1302 { 0x2, "Authentication and privacy" },
1303 { 0x3, "Authentication and privacy" },
1308 dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
1309 guchar *parameters, int parameters_length)
1312 proto_tree *parameters_tree;
1313 proto_tree *qos_tree;
1318 item = proto_tree_add_text(tree, tvb, offset, length,
1320 parameters_tree = proto_item_add_subtree(item, ett_parameters);
1321 offset += length - parameters_length;
1323 if (parameters_length < 1)
1325 model = *parameters;
1326 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1327 "model: %u", model);
1330 parameters_length -= 1;
1332 /* Unknown model. */
1333 proto_tree_add_text(parameters_tree, tvb, offset,
1334 parameters_length, "parameters: %s",
1335 bytes_to_str(parameters, parameters_length));
1339 if (parameters_length < 1)
1342 item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
1344 qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
1345 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1346 decode_boolean_bitfield(qos, 0x04,
1347 8, "Generation of report PDU allowed",
1348 "Generation of report PDU not allowed"));
1349 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1350 decode_enumerated_bitfield(qos, 0x03,
1351 8, qos_vals, "%s"));
1354 parameters_length -= 1;
1356 if (parameters_length < 12)
1358 proto_tree_add_text(parameters_tree, tvb, offset, 12,
1359 "agentID: %s", bytes_to_str(parameters, 12));
1362 parameters_length -= 12;
1364 if (parameters_length < 4)
1366 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1367 "agentBoots: %u", pntohl(parameters));
1370 parameters_length -= 4;
1372 if (parameters_length < 4)
1374 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1375 "agentTime: %u", pntohl(parameters));
1378 parameters_length -= 4;
1380 if (parameters_length < 2)
1382 proto_tree_add_text(parameters_tree, tvb, offset, 2,
1383 "maxSize: %u", pntohs(parameters));
1386 parameters_length -= 2;
1388 if (parameters_length < 1)
1391 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1392 "userLen: %u", len);
1395 parameters_length -= 1;
1397 if (parameters_length < len)
1399 proto_tree_add_text(parameters_tree, tvb, offset, len,
1400 "userName: %.*s", len, parameters);
1403 parameters_length -= len;
1405 if (parameters_length < 1)
1408 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1409 "authLen: %u", len);
1412 parameters_length -= 1;
1414 if (parameters_length < len)
1416 proto_tree_add_text(parameters_tree, tvb, offset, len,
1417 "authDigest: %s", bytes_to_str(parameters, len));
1420 parameters_length -= len;
1422 if (parameters_length < 1)
1424 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
1425 "contextSelector: %s", bytes_to_str(parameters, parameters_length));
1429 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1430 proto_tree *tree, char *proto_name, int proto, gint ett)
1437 guint message_length;
1438 guint global_length;
1444 guint32 engineboots;
1457 int msgflags_length;
1458 int community_length;
1460 int cengineid_length;
1462 int cryptpdu_length;
1463 int aengineid_length;
1464 int username_length;
1471 proto_tree *snmp_tree = NULL;
1472 proto_tree *global_tree = NULL;
1473 proto_tree *flags_tree = NULL;
1474 proto_tree *secur_tree = NULL;
1475 proto_item *item = NULL;
1477 guint cls, con, tag;
1479 if (check_col(pinfo->fd, COL_PROTOCOL))
1480 col_add_str(pinfo->fd, COL_PROTOCOL, proto_name);
1483 item = proto_tree_add_item(tree, proto, tvb, offset,
1484 tvb_length_remaining(tvb, offset), FALSE);
1485 snmp_tree = proto_item_add_subtree(item, ett);
1488 /* NOTE: we have to parse the message piece by piece, since the
1489 * capture length may be less than the message length: a 'global'
1490 * parsing is likely to fail.
1492 /* parse the SNMP header */
1493 asn1_open(&asn1, tvb, offset);
1494 ret = asn1_sequence_decode(&asn1, &message_length, &length);
1495 if (ret != ASN1_ERR_NOERROR) {
1496 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1497 "message header", ret);
1502 ret = asn1_uint32_decode (&asn1, &version, &length);
1503 if (ret != ASN1_ERR_NOERROR) {
1504 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1505 "version number", ret);
1509 proto_tree_add_text(snmp_tree, tvb, offset, length,
1511 val_to_str(version, versions, "Unknown version %#x"));
1517 case SNMP_VERSION_1:
1518 case SNMP_VERSION_2c:
1519 ret = asn1_octet_string_decode (&asn1, &community,
1520 &community_length, &length);
1521 if (ret != ASN1_ERR_NOERROR) {
1522 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1527 proto_tree_add_text(snmp_tree, tvb, offset, length,
1528 "Community: %.*s", community_length,
1529 SAFE_STRING(community));
1534 case SNMP_VERSION_2u:
1535 ret = asn1_octet_string_decode (&asn1, &community,
1536 &community_length, &length);
1538 dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
1539 community, community_length);
1544 case SNMP_VERSION_3:
1545 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1546 if (ret != ASN1_ERR_NOERROR) {
1547 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1548 "message global header", ret);
1552 item = proto_tree_add_text(snmp_tree, tvb, offset,
1553 global_length + length, "Message Global Header");
1554 global_tree = proto_item_add_subtree(item, ett_global);
1555 proto_tree_add_text(global_tree, tvb, offset,
1557 "Message Global Header Length: %d", global_length);
1560 ret = asn1_uint32_decode (&asn1, &msgid, &length);
1561 if (ret != ASN1_ERR_NOERROR) {
1562 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1567 proto_tree_add_text(global_tree, tvb, offset,
1568 length, "Message ID: %d", msgid);
1571 ret = asn1_uint32_decode (&asn1, &msgmax, &length);
1572 if (ret != ASN1_ERR_NOERROR) {
1573 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1574 "message max size", ret);
1578 proto_tree_add_text(global_tree, tvb, offset,
1579 length, "Message Max Size: %d", msgmax);
1582 ret = asn1_octet_string_decode (&asn1, &msgflags,
1583 &msgflags_length, &length);
1584 if (ret != ASN1_ERR_NOERROR) {
1585 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1586 "message flags", ret);
1589 if (msgflags_length != 1) {
1590 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1591 "message flags wrong length", ret);
1596 item = proto_tree_add_uint_format(global_tree,
1597 hf_snmpv3_flags, tvb, offset, length,
1598 msgflags[0], "Flags: 0x%02x", msgflags[0]);
1599 flags_tree = proto_item_add_subtree(item, ett_flags);
1600 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
1601 tvb, offset, length, msgflags[0]);
1602 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
1603 tvb, offset, length, msgflags[0]);
1604 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
1605 tvb, offset, length, msgflags[0]);
1607 encrypted = msgflags[0] & TH_CRYPT;
1610 ret = asn1_uint32_decode (&asn1, &msgsec, &length);
1611 if (ret != ASN1_ERR_NOERROR) {
1612 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1613 "message security model", ret);
1617 proto_tree_add_text(global_tree, tvb, offset,
1618 length, "Message Security Model: %s",
1619 val_to_str(msgsec, sec_models,
1620 "Unknown model %#x"));
1625 start = asn1.offset;
1626 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1627 &def, &secparm_length);
1628 length = asn1.offset - start;
1629 if (cls != ASN1_UNI && con != ASN1_PRI &&
1631 dissect_snmp_parse_error(tvb, offset, pinfo,
1632 snmp_tree, "Message Security Parameters",
1633 ASN1_ERR_WRONG_TYPE);
1637 item = proto_tree_add_text(snmp_tree, tvb,
1638 offset, secparm_length + length,
1639 "Message Security Parameters");
1640 secur_tree = proto_item_add_subtree(item,
1642 proto_tree_add_text(secur_tree, tvb, offset,
1644 "Message Security Parameters Length: %d",
1648 ret = asn1_sequence_decode(&asn1, &secparm_length,
1650 if (ret != ASN1_ERR_NOERROR) {
1651 dissect_snmp_parse_error(tvb, offset, pinfo,
1652 snmp_tree, "USM sequence header", ret);
1656 ret = asn1_octet_string_decode (&asn1, &aengineid,
1657 &aengineid_length, &length);
1658 if (ret != ASN1_ERR_NOERROR) {
1659 dissect_snmp_parse_error(tvb, offset, pinfo,
1660 snmp_tree, "authoritative engine id", ret);
1664 proto_tree_add_text(secur_tree, tvb, offset,
1665 length, "Authoritative Engine ID: %s",
1666 bytes_to_str(aengineid, aengineid_length));
1670 ret = asn1_uint32_decode (&asn1, &engineboots, &length);
1671 if (ret != ASN1_ERR_NOERROR) {
1672 dissect_snmp_parse_error(tvb, offset, pinfo,
1673 snmp_tree, "engine boots", ret);
1677 proto_tree_add_text(secur_tree, tvb,
1678 offset, length, "Engine Boots: %d",
1682 ret = asn1_uint32_decode (&asn1, &enginetime, &length);
1683 if (ret != ASN1_ERR_NOERROR) {
1684 dissect_snmp_parse_error(tvb, offset, pinfo,
1685 snmp_tree, "engine time", ret);
1689 proto_tree_add_text(secur_tree, tvb,
1690 offset, length, "Engine Time: %d",
1694 ret = asn1_octet_string_decode (&asn1, &username,
1695 &username_length, &length);
1696 if (ret != ASN1_ERR_NOERROR) {
1697 dissect_snmp_parse_error(tvb, offset, pinfo,
1698 snmp_tree, "user name", ret);
1702 proto_tree_add_text(secur_tree, tvb, offset,
1703 length, "User Name: %.*s",
1705 SAFE_STRING(username));
1709 ret = asn1_octet_string_decode (&asn1, &authpar,
1710 &authpar_length, &length);
1711 if (ret != ASN1_ERR_NOERROR) {
1712 dissect_snmp_parse_error(tvb, offset, pinfo,
1713 snmp_tree, "authentication parameter", ret);
1717 proto_tree_add_text(secur_tree, tvb, offset,
1718 length, "Authentication Parameter: %s",
1719 bytes_to_str(authpar, authpar_length));
1723 ret = asn1_octet_string_decode (&asn1, &privpar,
1724 &privpar_length, &length);
1725 if (ret != ASN1_ERR_NOERROR) {
1726 dissect_snmp_parse_error(tvb, offset, pinfo,
1727 snmp_tree, "privacy parameter", ret);
1731 proto_tree_add_text(secur_tree, tvb, offset,
1732 length, "Privacy Parameter: %s",
1733 bytes_to_str(privpar, privpar_length));
1739 ret = asn1_octet_string_decode (&asn1,
1740 &secparm, &secparm_length, &length);
1741 if (ret != ASN1_ERR_NOERROR) {
1742 dissect_snmp_parse_error(tvb, offset, pinfo,
1743 snmp_tree, "Message Security Parameters",
1748 proto_tree_add_text(snmp_tree, tvb, offset,
1750 "Message Security Parameters Data"
1751 " (%d bytes)", secparm_length);
1757 /* PDU starts here */
1759 ret = asn1_octet_string_decode (&asn1, &cryptpdu,
1760 &cryptpdu_length, &length);
1761 if (ret != ASN1_ERR_NOERROR) {
1762 dissect_snmp_parse_error(tvb, offset, pinfo,
1763 snmp_tree, "encrypted PDU header", ret);
1766 proto_tree_add_text(snmp_tree, tvb, offset, length,
1767 "Encrypted PDU (%d bytes)", length);
1769 if (check_col(pinfo->fd, COL_INFO))
1770 col_set_str(pinfo->fd, COL_INFO, "Encrypted PDU");
1773 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1774 if (ret != ASN1_ERR_NOERROR) {
1775 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1780 ret = asn1_octet_string_decode (&asn1, &cengineid,
1781 &cengineid_length, &length);
1782 if (ret != ASN1_ERR_NOERROR) {
1783 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1784 "context engine id", ret);
1788 proto_tree_add_text(snmp_tree, tvb, offset, length,
1789 "Context Engine ID: %s",
1790 bytes_to_str(cengineid, cengineid_length));
1794 ret = asn1_octet_string_decode (&asn1, &cname,
1795 &cname_length, &length);
1796 if (ret != ASN1_ERR_NOERROR) {
1797 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1798 "context name", ret);
1802 proto_tree_add_text(snmp_tree, tvb, offset, length,
1803 "Context Name: %.*s", cname_length,
1804 SAFE_STRING(cname));
1810 dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
1811 "PDU for unknown version of SNMP");
1815 start = asn1.offset;
1816 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1818 if (ret != ASN1_ERR_NOERROR) {
1819 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1823 if (cls != ASN1_CTX || con != ASN1_CON) {
1824 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1825 "PDU type", ASN1_ERR_WRONG_TYPE);
1828 dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
1832 dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1833 proto_tree *tree, int proto, gint ett)
1841 char *pdu_type_string;
1851 int password_length;
1853 guchar *application;
1854 int application_length;
1861 proto_tree *smux_tree = NULL;
1862 proto_item *item = NULL;
1866 if (check_col(pinfo->fd, COL_PROTOCOL))
1867 col_set_str(pinfo->fd, COL_PROTOCOL, "SMUX");
1870 item = proto_tree_add_item(tree, proto, tvb, offset,
1871 tvb_length_remaining(tvb, offset), FALSE);
1872 smux_tree = proto_item_add_subtree(item, ett);
1875 /* NOTE: we have to parse the message piece by piece, since the
1876 * capture length may be less than the message length: a 'global'
1877 * parsing is likely to fail.
1879 /* parse the SNMP header */
1880 asn1_open(&asn1, tvb, offset);
1881 start = asn1.offset;
1882 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1884 if (ret != ASN1_ERR_NOERROR) {
1885 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1890 /* Dissect SMUX here */
1891 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
1892 pdu_type_string = val_to_str(pdu_type, smux_types,
1893 "Unknown PDU type %#x");
1894 if (check_col(pinfo->fd, COL_INFO))
1895 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1896 length = asn1.offset - start;
1898 proto_tree_add_text(smux_tree, tvb, offset, length,
1899 "PDU type: %s", pdu_type_string);
1902 ret = asn1_uint32_decode (&asn1, &version, &length);
1903 if (ret != ASN1_ERR_NOERROR) {
1904 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1909 proto_tree_add_text(smux_tree, tvb, offset, length,
1910 "Version: %d", version);
1914 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1915 if (ret != ASN1_ERR_NOERROR) {
1916 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1917 "registration OID", ret);
1921 oid_string = format_oid(regid, regid_length);
1922 proto_tree_add_text(smux_tree, tvb, offset, length,
1923 "Registration: %s", oid_string);
1929 ret = asn1_octet_string_decode (&asn1, &application,
1930 &application_length, &length);
1931 if (ret != ASN1_ERR_NOERROR) {
1932 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1933 "application", ret);
1937 proto_tree_add_text(smux_tree, tvb, offset, length,
1938 "Application: %.*s", application_length,
1939 SAFE_STRING(application));
1941 g_free(application);
1944 ret = asn1_octet_string_decode (&asn1, &password,
1945 &password_length, &length);
1946 if (ret != ASN1_ERR_NOERROR) {
1947 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1952 proto_tree_add_text(smux_tree, tvb, offset, length,
1953 "Password: %.*s", password_length,
1954 SAFE_STRING(password));
1960 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
1961 pdu_type_string = val_to_str(pdu_type, smux_types,
1962 "Unknown PDU type %#x");
1963 if (check_col(pinfo->fd, COL_INFO))
1964 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1965 length = asn1.offset - start;
1967 proto_tree_add_text(smux_tree, tvb, offset, length,
1968 "PDU type: %s", pdu_type_string);
1971 ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
1972 if (ret != ASN1_ERR_NOERROR) {
1973 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1978 proto_tree_add_text(smux_tree, tvb, offset,
1979 pdu_length, "Cause: %s",
1980 val_to_str(cause, smux_close,
1981 "Unknown cause %#x"));
1983 offset += pdu_length;
1986 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
1987 pdu_type_string = val_to_str(pdu_type, smux_types,
1988 "Unknown PDU type %#x");
1989 if (check_col(pinfo->fd, COL_INFO))
1990 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1991 length = asn1.offset - start;
1993 proto_tree_add_text(smux_tree, tvb, offset, length,
1994 "PDU type: %s", pdu_type_string);
1997 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1998 if (ret != ASN1_ERR_NOERROR) {
1999 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2000 "registration subtree", ret);
2004 oid_string = format_oid(regid, regid_length);
2005 proto_tree_add_text(smux_tree, tvb, offset, length,
2006 "Registration: %s", oid_string);
2012 ret = asn1_uint32_decode (&asn1, &priority, &length);
2013 if (ret != ASN1_ERR_NOERROR) {
2014 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2019 proto_tree_add_text(smux_tree, tvb, offset, length,
2020 "Priority: %d", priority);
2024 ret = asn1_uint32_decode (&asn1, &operation, &length);
2025 if (ret != ASN1_ERR_NOERROR) {
2026 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2031 proto_tree_add_text(smux_tree, tvb, offset, length,
2033 val_to_str(operation, smux_rreq,
2034 "Unknown operation %#x"));
2039 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
2040 pdu_type_string = val_to_str(pdu_type, smux_types,
2041 "Unknown PDU type %#x");
2042 if (check_col(pinfo->fd, COL_INFO))
2043 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
2044 length = asn1.offset - start;
2046 proto_tree_add_text(smux_tree, tvb, offset, length,
2047 "PDU type: %s", pdu_type_string);
2050 ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
2051 if (ret != ASN1_ERR_NOERROR) {
2052 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2057 proto_tree_add_text(smux_tree, tvb, offset,
2059 val_to_str(priority, smux_prio,
2062 offset += pdu_length;
2065 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
2066 pdu_type_string = val_to_str(pdu_type, smux_types,
2067 "Unknown PDU type %#x");
2068 if (check_col(pinfo->fd, COL_INFO))
2069 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
2070 length = asn1.offset - start;
2072 proto_tree_add_text(smux_tree, tvb, offset, length,
2073 "PDU type: %s", pdu_type_string);
2076 ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
2077 if (ret != ASN1_ERR_NOERROR) {
2078 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2083 proto_tree_add_text(smux_tree, tvb, offset,
2085 val_to_str(commit, smux_sout,
2086 "Unknown SOUT Value: %#x"));
2088 offset += pdu_length;
2091 if (cls != ASN1_CTX || con != ASN1_CON) {
2092 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2093 "PDU type", ASN1_ERR_WRONG_TYPE);
2096 dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
2100 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2102 conversation_t *conversation;
2105 * The first SNMP packet goes to the SNMP port; the second one
2106 * may come from some *other* port, but goes back to the same
2107 * IP address and port as the ones from which the first packet
2108 * came; all subsequent packets presumably go between those two
2109 * IP addresses and ports.
2111 * If this packet went to the SNMP port, we check to see if
2112 * there's already a conversation with one address/port pair
2113 * matching the source IP address and port of this packet,
2114 * the other address matching the destination IP address of this
2115 * packet, and any destination port.
2117 * If not, we create one, with its address 1/port 1 pair being
2118 * the source address/port of this packet, its address 2 being
2119 * the destination address of this packet, and its port 2 being
2120 * wildcarded, and give it the SNMP dissector as a dissector.
2122 if (pinfo->destport == UDP_PORT_SNMP) {
2123 conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
2124 pinfo->srcport, 0, NO_PORT_B);
2125 if (conversation == NULL) {
2126 conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
2127 pinfo->srcport, 0, NO_PORT2);
2128 conversation_set_dissector(conversation, snmp_handle);
2132 dissect_snmp_pdu(tvb, 0, pinfo, tree, "SNMP", proto_snmp, ett_snmp);
2136 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2138 dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
2142 proto_register_snmp(void)
2144 #if defined(HAVE_UCD_SNMP_SNMP_H) && defined(linux)
2145 void *libsnmp_handle;
2146 int (*snmp_set_suffix_only_p)(int);
2147 int (*ds_set_int_p)(int, int, int);
2150 static hf_register_info hf[] = {
2152 { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
2154 { &hf_snmpv3_flags_auth,
2155 { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
2156 TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
2157 { &hf_snmpv3_flags_crypt,
2158 { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
2159 TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
2160 { &hf_snmpv3_flags_report,
2161 { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
2162 TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
2164 static gint *ett[] = {
2168 &ett_parameters_qos,
2174 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
2175 /* UCD or CMU SNMP */
2177 #ifdef HAVE_UCD_SNMP_SNMP_H
2179 /* As per the comment near the beginning of the file, UCD SNMP 4.1.1
2180 changed "snmp_set_suffix_only()" from a function to a macro,
2181 removing "snmp_set_suffix_only()" from the library; this means
2182 that binaries that call "snmp_set_suffix_only()" and
2183 that are linked against shared libraries from earlier versions
2184 of the UCD SNMP library won't run with shared libraries from
2187 This is a problem on Red Hat Linux, as pre-6.2 releases
2188 came with pre-4.1.1 UCD SNMP, while 6.2 comes the 4.1.1.
2189 Versions of Ethereal built on pre-6.2 releases don't run
2190 on 6.2, and the current Ethereal RPMs are built on pre-6.2
2191 releases, causing problems when users running 6.2 download
2192 them and try to use them.
2194 Building the releases on 6.2 isn't necessarily the answer,
2195 as "snmp_set_suffix_only()" expands to a call to "ds_set_int()"
2196 with a second argument not supported by at least some pre-4.1.1
2197 versions of the library - it appears that the 4.0.1 library,
2198 at least, checks for invalid arguments and returns an error
2199 rather than stomping random memory, but that means that you
2200 won't get get OIDs displayed as module-name::sub-OID.
2202 So we use a trick similar to one I've seen mentioned as
2203 used in Windows applications to let you build binaries
2204 that run on many different versions of Windows 9x and
2205 Windows NT, that use features present on later versions
2206 if run on those later versions, but that avoid calling,
2207 when run on older versions, routines not present on those
2210 I.e., we load "libsnmp.so.0" with "dlopen()", and call
2211 "dlsym()" to try to find "snmp_set_suffix_only()"; if we
2212 don't find it, we make the appropriate call to
2213 "ds_set_int()" instead. (We load "libsnmp.so.0" rather
2214 than "libsnmp.so" because, at least on RH 6.2, "libsnmp.so"
2215 exists only if you've loaded the libsnmp development package,
2216 which makes "libsnmp.so" a symlink to "libsnmp.so.0"; we
2217 don't want to force users to install it or to make said
2220 We do this only on Linux, for now, as we've only seen the
2221 problem on Red Hat; it may show up on other OSes that bundle
2222 UCD SNMP, or on OSes where it's not bundled but for which
2223 binary packages are built that link against a shared version
2224 of the UCD SNMP library. If we run into one of those, we
2225 can do this under those OSes as well, *if* "dlopen()" makes
2226 the run-time linker use the same search rules as it uses when
2227 loading libraries with which the application is linked.
2229 (Perhaps we could use the GLib wrappers for run-time linking,
2230 *if* they're thin enough; however, as this code is currently
2231 used only on Linux, we don't worry about that for now.) */
2233 libsnmp_handle = dlopen("libsnmp.so.0", RTLD_LAZY|RTLD_GLOBAL);
2234 if (libsnmp_handle == NULL) {
2235 /* We didn't find "libsnmp.so.0".
2237 This could mean that there is no SNMP shared library
2238 on this system, in which case we were linked statically,
2239 in which case whatever call the following line of code
2240 makes will presumably work, as we have the routine it
2241 calls wired into our binary. (If we were linked
2242 dynamically with "-lsnmp", we would have failed to
2245 It could also mean that there is an SNMP shared library
2246 on this system, but it's called something other than
2247 "libsnmp.so.0"; so far, we've seen the problem we're
2248 working around only on systems where the SNMP shared
2249 library is called "libsnmp.so.0", so we assume for now
2250 that systems with shared SNMP libraries named something
2251 other than "libsnmp.so.0" have an SNMP library that's
2253 snmp_set_suffix_only(2);
2255 /* OK, we have it loaded. Do we have
2256 "snmp_set_suffix_only()"? */
2257 snmp_set_suffix_only_p = dlsym(libsnmp_handle,
2258 "snmp_set_suffix_only");
2259 if (snmp_set_suffix_only_p != NULL) {
2260 /* Yes - call it. */
2261 (*snmp_set_suffix_only_p)(2);
2263 /* No; do we have "ds_set_int()"? */
2264 ds_set_int_p = dlsym(libsnmp_handle, "ds_set_int");
2265 if (ds_set_int_p != NULL) {
2266 /* Yes - cal it with DS_LIBRARY_ID,
2267 DS_LIB_PRINT_SUFFIX_ONLY, and 2 as
2270 We do *not* use DS_LIBRARY_ID or
2271 DS_LIB_PRINT_SUFFIX_ONLY by name, so that
2272 we don't require that Ethereal be built
2273 with versions of UCD SNMP that include
2274 that value; instead, we use their values
2275 in UCD SNMP 4.1.1, which are 0 and 4,
2277 (*ds_set_int_p)(0, 4, 2);
2280 dlclose(libsnmp_handle);
2283 snmp_set_suffix_only(2);
2285 #endif /* HAVE_UCD_SNMP_SNMP_H */
2286 #endif /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
2287 proto_snmp = proto_register_protocol("Simple Network Management Protocol",
2289 proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2291 proto_register_field_array(proto_snmp, hf, array_length(hf));
2292 proto_register_subtree_array(ett, array_length(ett));
2293 snmp_handle = create_dissector_handle(dissect_snmp, proto_snmp);
2297 proto_reg_handoff_snmp(void)
2299 dissector_handle_t smux_handle;
2301 dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
2302 dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
2303 smux_handle = create_dissector_handle(dissect_smux, proto_smux);
2304 dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);
2305 dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
2306 dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
2307 dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
2308 data_handle = find_dissector("data");