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.70 2001/09/03 08:19:12 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;
227 #define TH_CRYPT 0x02
228 #define TH_REPORT 0x04
230 static const true_false_string flags_set_truth = {
235 #define UDP_PORT_SNMP 161
236 #define UDP_PORT_SNMP_TRAP 162
237 #define TCP_PORT_SMUX 199
239 /* Protocol version numbers */
240 #define SNMP_VERSION_1 0
241 #define SNMP_VERSION_2c 1
242 #define SNMP_VERSION_2u 2
243 #define SNMP_VERSION_3 3
245 static const value_string versions[] = {
246 { SNMP_VERSION_1, "1" },
247 { SNMP_VERSION_2c, "2C" },
248 { SNMP_VERSION_2u, "2U" },
249 { SNMP_VERSION_3, "3" },
254 #define SNMP_MSG_GET 0
255 #define SNMP_MSG_GETNEXT 1
256 #define SNMP_MSG_RESPONSE 2
257 #define SNMP_MSG_SET 3
258 #define SNMP_MSG_TRAP 4
260 #define SNMP_MSG_GETBULK 5
261 #define SNMP_MSG_INFORM 6
262 #define SNMP_MSG_TRAP2 7
263 #define SNMP_MSG_REPORT 8
265 static const value_string pdu_types[] = {
266 { SNMP_MSG_GET, "GET" },
267 { SNMP_MSG_GETNEXT, "GET-NEXT" },
268 { SNMP_MSG_SET, "SET" },
269 { SNMP_MSG_RESPONSE, "RESPONSE" },
270 { SNMP_MSG_TRAP, "TRAP-V1" },
271 { SNMP_MSG_GETBULK, "GETBULK" },
272 { SNMP_MSG_INFORM, "INFORM" },
273 { SNMP_MSG_TRAP2, "TRAP-V2" },
274 { SNMP_MSG_REPORT, "REPORT" },
279 #define SMUX_MSG_OPEN 0
280 #define SMUX_MSG_CLOSE 1
281 #define SMUX_MSG_RREQ 2
282 #define SMUX_MSG_RRSP 3
283 #define SMUX_MSG_SOUT 4
285 static const value_string smux_types[] = {
286 { SMUX_MSG_OPEN, "Open" },
287 { SMUX_MSG_CLOSE, "Close" },
288 { SMUX_MSG_RREQ, "Registration Request" },
289 { SMUX_MSG_RRSP, "Registration Response" },
290 { SMUX_MSG_SOUT, "Commit Or Rollback" },
294 /* SMUX Closing causes */
295 #define SMUX_CLOSE_DOWN 0
296 #define SMUX_CLOSE_VERSION 1
297 #define SMUX_CLOSE_PACKET 2
298 #define SMUX_CLOSE_PROTOCOL 3
299 #define SMUX_CLOSE_INTERNAL 4
300 #define SMUX_CLOSE_NOAUTH 5
302 static const value_string smux_close[] = {
303 { SMUX_CLOSE_DOWN, "Going down" },
304 { SMUX_CLOSE_VERSION, "Unsupported Version" },
305 { SMUX_CLOSE_PACKET, "Packet Format Error" },
306 { SMUX_CLOSE_PROTOCOL, "Protocol Error" },
307 { SMUX_CLOSE_INTERNAL, "Internal Error" },
308 { SMUX_CLOSE_NOAUTH, "Unauthorized" },
312 /* SMUX Request codes */
313 #define SMUX_RREQ_DELETE 0
314 #define SMUX_RREQ_READONLY 1
315 #define SMUX_RREQ_READWRITE 2
317 static const value_string smux_rreq[] = {
318 { SMUX_RREQ_DELETE, "Delete" },
319 { SMUX_RREQ_READONLY, "Read Only" },
320 { SMUX_RREQ_READWRITE, "Read Write" },
324 static const value_string smux_prio[] = {
329 /* SMUX SOut codes */
330 #define SMUX_SOUT_COMMIT 0
331 #define SMUX_SOUT_ROLLBACK 1
333 static const value_string smux_sout[] = {
334 { SMUX_SOUT_COMMIT, "Commit" },
335 { SMUX_SOUT_ROLLBACK, "Rollback" },
339 /* Error status values */
340 #define SNMP_ERR_NOERROR 0
341 #define SNMP_ERR_TOOBIG 1
342 #define SNMP_ERR_NOSUCHNAME 2
343 #define SNMP_ERR_BADVALUE 3
344 #define SNMP_ERR_READONLY 4
345 #define SNMP_ERR_GENERROR 5
347 #define SNMP_ERR_NOACCESS 6
348 #define SNMP_ERR_WRONGTYPE 7
349 #define SNMP_ERR_WRONGLENGTH 8
350 #define SNMP_ERR_WRONGENCODING 9
351 #define SNMP_ERR_WRONGVALUE 10
352 #define SNMP_ERR_NOCREATION 11
353 #define SNMP_ERR_INCONSISTENTVALUE 12
354 #define SNMP_ERR_RESOURCEUNAVAILABLE 13
355 #define SNMP_ERR_COMMITFAILED 14
356 #define SNMP_ERR_UNDOFAILED 15
357 #define SNMP_ERR_AUTHORIZATIONERROR 16
358 #define SNMP_ERR_NOTWRITABLE 17
359 #define SNMP_ERR_INCONSISTENTNAME 18
361 static const value_string error_statuses[] = {
362 { SNMP_ERR_NOERROR, "NO ERROR" },
363 { SNMP_ERR_TOOBIG, "TOOBIG" },
364 { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" },
365 { SNMP_ERR_BADVALUE, "BAD VALUE" },
366 { SNMP_ERR_READONLY, "READ ONLY" },
367 { SNMP_ERR_GENERROR, "GENERIC ERROR" },
368 { SNMP_ERR_NOACCESS, "NO ACCESS" },
369 { SNMP_ERR_WRONGTYPE, "WRONG TYPE" },
370 { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" },
371 { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" },
372 { SNMP_ERR_WRONGVALUE, "WRONG VALUE" },
373 { SNMP_ERR_NOCREATION, "NO CREATION" },
374 { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" },
375 { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" },
376 { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" },
377 { SNMP_ERR_UNDOFAILED, "UNDO FAILED" },
378 { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" },
379 { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" },
380 { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" },
384 /* General SNMP V1 Traps */
386 #define SNMP_TRAP_COLDSTART 0
387 #define SNMP_TRAP_WARMSTART 1
388 #define SNMP_TRAP_LINKDOWN 2
389 #define SNMP_TRAP_LINKUP 3
390 #define SNMP_TRAP_AUTHFAIL 4
391 #define SNMP_TRAP_EGPNEIGHBORLOSS 5
392 #define SNMP_TRAP_ENTERPRISESPECIFIC 6
394 static const value_string trap_types[] = {
395 { SNMP_TRAP_COLDSTART, "COLD START" },
396 { SNMP_TRAP_WARMSTART, "WARM START" },
397 { SNMP_TRAP_LINKDOWN, "LINK DOWN" },
398 { SNMP_TRAP_LINKUP, "LINK UP" },
399 { SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
400 { SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
401 { SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
405 /* Security Models */
407 #define SNMP_SEC_ANY 0
408 #define SNMP_SEC_V1 1
409 #define SNMP_SEC_V2C 2
410 #define SNMP_SEC_USM 3
412 static const value_string sec_models[] = {
413 { SNMP_SEC_ANY, "Any" },
414 { SNMP_SEC_V1, "V1" },
415 { SNMP_SEC_V2C, "V2C" },
416 { SNMP_SEC_USM, "USM" },
422 #define SNMP_IPA 0 /* IP Address */
423 #define SNMP_CNT 1 /* Counter (Counter32) */
424 #define SNMP_GGE 2 /* Gauge (Gauge32) */
425 #define SNMP_TIT 3 /* TimeTicks */
426 #define SNMP_OPQ 4 /* Opaque */
427 #define SNMP_NSP 5 /* NsapAddress */
428 #define SNMP_C64 6 /* Counter64 */
429 #define SNMP_U32 7 /* Uinteger32 */
438 #define SNMP_INTEGER 1 /* l */
439 #define SNMP_OCTETSTR 2 /* c */
440 #define SNMP_DISPLAYSTR 2 /* c */
441 #define SNMP_OBJECTID 3 /* ul */
442 #define SNMP_IPADDR 4 /* uc */
443 #define SNMP_COUNTER 5 /* ul */
444 #define SNMP_GAUGE 6 /* ul */
445 #define SNMP_TIMETICKS 7 /* ul */
446 #define SNMP_OPAQUE 8 /* c */
448 /* additional SNMPv2 Types */
450 #define SNMP_UINTEGER 5 /* ul */
451 #define SNMP_BITSTR 9 /* uc */
452 #define SNMP_NSAP 10 /* uc */
453 #define SNMP_COUNTER64 11 /* ul */
454 #define SNMP_NOSUCHOBJECT 12
455 #define SNMP_NOSUCHINSTANCE 13
456 #define SNMP_ENDOFMIBVIEW 14
458 typedef struct _SNMP_CNV SNMP_CNV;
468 static SNMP_CNV SnmpCnv [] =
470 {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"},
471 {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"},
472 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"},
473 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"},
474 {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"},
475 {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */
476 {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */
477 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"},
478 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"},
480 /* SNMPv2 data types and errors */
482 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"},
483 {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"},
484 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"},
485 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"},
486 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"},
491 * NAME: g_snmp_tag_cls2syntax
492 * SYNOPSIS: gboolean g_snmp_tag_cls2syntax
498 * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name.
499 * See SnmpCnv for conversion.
500 * RETURNS: name on success, NULL on failure
504 snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
509 while (cnv->syntax != -1)
511 if (cnv->tag == tag && cnv->class == cls)
513 *syntax = cnv->syntax;
522 dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
523 proto_tree *tree, const char *field_name, int ret)
529 case ASN1_ERR_EOC_MISMATCH:
530 errstr = "EOC mismatch";
533 case ASN1_ERR_WRONG_TYPE:
534 errstr = "Wrong type for that item";
537 case ASN1_ERR_LENGTH_NOT_DEFINITE:
538 errstr = "Length was indefinite";
541 case ASN1_ERR_LENGTH_MISMATCH:
542 errstr = "Length mismatch";
545 case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
546 errstr = "Wrong length for that item's type";
550 errstr = "Unknown error";
554 if (check_col(pinfo->fd, COL_INFO)) {
555 col_add_fstr(pinfo->fd, COL_INFO,
556 "ERROR: Couldn't parse %s: %s", field_name, errstr);
559 proto_tree_add_text(tree, tvb, offset, 0,
560 "ERROR: Couldn't parse %s: %s", field_name, errstr);
561 dissect_data(tvb, offset, pinfo, tree);
566 dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
567 proto_tree *tree, const char *message)
569 if (check_col(pinfo->fd, COL_INFO))
570 col_add_str(pinfo->fd, COL_INFO, message);
573 proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
574 dissect_data(tvb, offset, pinfo, tree);
579 format_oid(subid_t *oid, guint oid_length)
587 result_len = oid_length * 22;
588 result = g_malloc(result_len + 1);
590 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
592 for (i = 1; i < oid_length;i++) {
593 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
599 #ifdef HAVE_SPRINT_VALUE
601 format_var(struct variable_list *variable, subid_t *variable_oid,
602 guint variable_oid_length, gushort vb_type, guint vb_length)
612 /* We don't know how long this will be, but let's guess it
613 fits within 128 characters; that should be enough for an
614 integral value plus some sort of type indication. */
624 /* We don't know how long this will be, but let's guess it
625 fits within 128 characters plus 4 characters per octet. */
626 buf = g_malloc(128 + 4*vb_length);
630 /* We don't know how long this will be, but let's guess it
631 fits within 128 characters plus 32 characters per subid
632 (10 digits plus period, or a subid name). */
633 buf = g_malloc(1024 + 32*vb_length);
637 /* Should not happen. */
638 g_assert_not_reached();
643 variable->next_variable = NULL;
644 variable->name = variable_oid;
645 variable->name_length = variable_oid_length;
649 variable->type = VALTYPE_INTEGER;
653 variable->type = VALTYPE_COUNTER;
657 variable->type = VALTYPE_GAUGE;
661 variable->type = VALTYPE_TIMETICKS;
665 variable->type = VALTYPE_STRING;
669 variable->type = VALTYPE_IPADDR;
673 variable->type = VALTYPE_OPAQUE;
677 variable->type = VALTYPE_NSAP;
681 variable->type = VALTYPE_OBJECTID;
682 vb_length *= sizeof (subid_t); /* XXX - necessary? */
686 variable->type = VALTYPE_BITSTR;
690 variable->type = VALTYPE_COUNTER64;
693 variable->val_len = vb_length;
695 sprint_value(buf, variable_oid, variable_oid_length, variable);
701 snmp_variable_decode(proto_tree *snmp_tree, subid_t *variable_oid,
702 guint variable_oid_length, ASN1_SCK *asn1, int offset, guint *lengthp,
714 gint32 vb_integer_value;
715 guint32 vb_uinteger_value;
717 guint8 *vb_octet_string;
722 gchar *vb_display_string;
724 #ifdef HAVE_SPRINT_VALUE
725 struct variable_list variable;
726 #if defined(HAVE_UCD_SNMP_SNMP_H)
729 #endif /* HAVE_SPRINT_VALUE */
734 /* parse the type of the object */
735 start = asn1->offset;
736 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
737 if (ret != ASN1_ERR_NOERROR)
740 return ASN1_ERR_LENGTH_NOT_DEFINITE;
742 /* Convert the class, constructed flag, and tag to a type. */
743 vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
744 if (vb_type_name == NULL) {
747 * Dissect the value as an opaque string of octets.
749 vb_type_name = "unsupported type";
750 vb_type = SNMP_OPAQUE;
753 /* parse the value */
757 ret = asn1_int32_value_decode(asn1, vb_length,
759 if (ret != ASN1_ERR_NOERROR)
761 length = asn1->offset - start;
763 #ifdef HAVE_SPRINT_VALUE
765 #if defined(HAVE_UCD_SNMP_SNMP_H)
766 value = vb_integer_value;
767 variable.val.integer = &value;
768 #elif defined(HAVE_SNMP_SNMP_H)
769 variable.val.integer = &vb_integer_value;
771 vb_display_string = format_var(&variable,
772 variable_oid, variable_oid_length, vb_type,
774 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
776 "Value: %s", vb_display_string);
777 g_free(vb_display_string);
778 break; /* we added formatted version to the tree */
780 #endif /* HAVE_SPRINT_VALUE */
781 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
782 "Value: %s: %d (%#x)", vb_type_name,
783 vb_integer_value, vb_integer_value);
790 ret = asn1_uint32_value_decode(asn1, vb_length,
792 if (ret != ASN1_ERR_NOERROR)
794 length = asn1->offset - start;
796 #ifdef HAVE_SPRINT_VALUE
798 #if defined(HAVE_UCD_SNMP_SNMP_H)
799 value = vb_uinteger_value;
800 variable.val.integer = &value;
801 #elif defined(HAVE_SNMP_SNMP_H)
802 variable.val.integer = &vb_uinteger_value;
804 vb_display_string = format_var(&variable,
805 variable_oid, variable_oid_length, vb_type,
807 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
809 "Value: %s", vb_display_string);
810 g_free(vb_display_string);
811 break; /* we added formatted version to the tree */
813 #endif /* HAVE_SPRINT_VALUE */
814 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
815 "Value: %s: %u (%#x)", vb_type_name,
816 vb_uinteger_value, vb_uinteger_value);
826 ret = asn1_string_value_decode (asn1, vb_length,
828 if (ret != ASN1_ERR_NOERROR)
830 length = asn1->offset - start;
832 #ifdef HAVE_SPRINT_VALUE
834 variable.val.string = vb_octet_string;
835 vb_display_string = format_var(&variable,
836 variable_oid, variable_oid_length, vb_type,
838 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
840 "Value: %s", vb_display_string);
841 g_free(vb_display_string);
842 break; /* we added formatted version to the tree */
844 #endif /* HAVE_SPRINT_VALUE */
846 * If some characters are not printable, display
847 * the string as bytes.
849 for (i = 0; i < vb_length; i++) {
850 if (!(isprint(vb_octet_string[i])
851 || isspace(vb_octet_string[i])))
856 * We stopped, due to a non-printable
857 * character, before we got to the end
860 vb_display_string = g_malloc(4*vb_length);
861 buf = &vb_display_string[0];
862 len = sprintf(buf, "%03u", vb_octet_string[0]);
864 for (i = 1; i < vb_length; i++) {
865 len = sprintf(buf, ".%03u",
869 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
870 "Value: %s: %s", vb_type_name,
872 g_free(vb_display_string);
874 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
875 "Value: %s: %.*s", vb_type_name,
877 SAFE_STRING(vb_octet_string));
880 g_free(vb_octet_string);
884 ret = asn1_null_decode (asn1, vb_length);
885 if (ret != ASN1_ERR_NOERROR)
887 length = asn1->offset - start;
889 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
890 "Value: %s", vb_type_name);
895 ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
897 if (ret != ASN1_ERR_NOERROR)
899 length = asn1->offset - start;
901 #ifdef HAVE_SPRINT_VALUE
903 variable.val.objid = vb_oid;
904 vb_display_string = format_var(&variable,
905 variable_oid, variable_oid_length, vb_type,
907 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
909 "Value: %s", vb_display_string);
910 break; /* we added formatted version to the tree */
912 #endif /* HAVE_SPRINT_VALUE */
913 vb_display_string = format_oid(vb_oid, vb_oid_length);
914 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
915 "Value: %s: %s", vb_type_name, vb_display_string);
916 g_free(vb_display_string);
921 case SNMP_NOSUCHOBJECT:
922 length = asn1->offset - start;
924 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
925 "Value: %s: no such object", vb_type_name);
929 case SNMP_NOSUCHINSTANCE:
930 length = asn1->offset - start;
932 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
933 "Value: %s: no such instance", vb_type_name);
937 case SNMP_ENDOFMIBVIEW:
938 length = asn1->offset - start;
940 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
941 "Value: %s: end of mib view", vb_type_name);
946 g_assert_not_reached();
947 return ASN1_ERR_WRONG_TYPE;
950 return ASN1_ERR_NOERROR;
954 dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
955 proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
959 guint sequence_length;
963 guint32 error_status;
967 char *pdu_type_string;
970 guint enterprise_length;
972 guint8 *agent_address;
973 guint agent_address_length;
977 guint32 specific_type;
980 guint timestamp_length;
984 guint variable_bindings_length;
987 guint variable_length;
988 subid_t *variable_oid;
989 guint variable_oid_length;
990 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
991 gchar vb_oid_string[MAX_STRING_LEN]; /* TBC */
998 pdu_type_string = val_to_str(pdu_type, pdu_types,
999 "Unknown PDU type %#x");
1000 if (check_col(pinfo->fd, COL_INFO))
1001 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1002 length = asn1.offset - start;
1004 proto_tree_add_text(tree, tvb, offset, length,
1005 "PDU type: %s", pdu_type_string);
1009 /* get the fields in the PDU preceeding the variable-bindings sequence */
1013 case SNMP_MSG_GETNEXT:
1014 case SNMP_MSG_RESPONSE:
1016 case SNMP_MSG_GETBULK:
1017 case SNMP_MSG_INFORM:
1018 case SNMP_MSG_TRAP2:
1019 case SNMP_MSG_REPORT:
1021 ret = asn1_uint32_decode (&asn1, &request_id, &length);
1022 if (ret != ASN1_ERR_NOERROR) {
1023 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1028 proto_tree_add_text(tree, tvb, offset, length,
1029 "Request Id: %#x", request_id);
1033 /* error status, or getbulk non-repeaters */
1034 ret = asn1_uint32_decode (&asn1, &error_status, &length);
1035 if (ret != ASN1_ERR_NOERROR) {
1036 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1037 (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
1043 if (pdu_type == SNMP_MSG_GETBULK) {
1044 proto_tree_add_text(tree, tvb, offset,
1045 length, "Non-repeaters: %u", error_status);
1047 proto_tree_add_text(tree, tvb, offset,
1048 length, "Error Status: %s",
1049 val_to_str(error_status, error_statuses,
1055 /* error index, or getbulk max-repetitions */
1056 ret = asn1_uint32_decode (&asn1, &error_index, &length);
1057 if (ret != ASN1_ERR_NOERROR) {
1058 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1059 (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
1065 if (pdu_type == SNMP_MSG_GETBULK) {
1066 proto_tree_add_text(tree, tvb, offset,
1067 length, "Max repetitions: %u", error_index);
1069 proto_tree_add_text(tree, tvb, offset,
1070 length, "Error Index: %u", error_index);
1078 ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
1080 if (ret != ASN1_ERR_NOERROR) {
1081 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1082 "enterprise OID", ret);
1086 oid_string = format_oid(enterprise, enterprise_length);
1087 proto_tree_add_text(tree, tvb, offset, length,
1088 "Enterprise: %s", oid_string);
1095 start = asn1.offset;
1096 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1097 &def, &agent_address_length);
1098 if (ret != ASN1_ERR_NOERROR) {
1099 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1100 "agent address", ret);
1103 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
1104 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
1105 /* GXSNMP 0.0.15 says the latter is "needed for
1107 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1108 "agent_address", ASN1_ERR_WRONG_TYPE);
1111 if (agent_address_length != 4) {
1112 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1113 "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
1116 ret = asn1_string_value_decode (&asn1,
1117 agent_address_length, &agent_address);
1118 if (ret != ASN1_ERR_NOERROR) {
1119 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1120 "agent address", ret);
1123 length = asn1.offset - start;
1125 if (agent_address_length != 4) {
1126 proto_tree_add_text(tree, tvb, offset,
1128 "Agent address: <length is %u, not 4>",
1129 agent_address_length);
1131 proto_tree_add_text(tree, tvb, offset,
1133 "Agent address: %s",
1134 ip_to_str(agent_address));
1137 g_free(agent_address);
1140 /* generic trap type */
1141 ret = asn1_uint32_decode (&asn1, &trap_type, &length);
1142 if (ret != ASN1_ERR_NOERROR) {
1143 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1144 "generic trap type", ret);
1148 proto_tree_add_text(tree, tvb, offset, length,
1150 val_to_str(trap_type, trap_types, "Unknown (%u)"));
1154 /* specific trap type */
1155 ret = asn1_uint32_decode (&asn1, &specific_type, &length);
1156 if (ret != ASN1_ERR_NOERROR) {
1157 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1158 "specific trap type", ret);
1162 proto_tree_add_text(tree, tvb, offset, length,
1163 "Specific trap type: %u (%#x)",
1164 specific_type, specific_type);
1169 start = asn1.offset;
1170 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1171 &def, ×tamp_length);
1172 if (ret != ASN1_ERR_NOERROR) {
1173 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1177 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
1178 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
1179 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1180 "timestamp", ASN1_ERR_WRONG_TYPE);
1183 ret = asn1_uint32_value_decode(&asn1, timestamp_length,
1185 if (ret != ASN1_ERR_NOERROR) {
1186 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1190 length = asn1.offset - start;
1192 proto_tree_add_text(tree, tvb, offset, length,
1193 "Timestamp: %u", timestamp);
1199 /* variable bindings */
1200 /* get header for variable-bindings sequence */
1201 ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
1202 if (ret != ASN1_ERR_NOERROR) {
1203 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1204 "variable bindings header", ret);
1209 /* loop on variable bindings */
1211 while (variable_bindings_length > 0) {
1213 sequence_length = 0;
1216 ret = asn1_sequence_decode(&asn1, &variable_length, &length);
1217 if (ret != ASN1_ERR_NOERROR) {
1218 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1219 "variable binding header", ret);
1222 sequence_length += length;
1224 /* parse object identifier */
1225 ret = asn1_oid_decode (&asn1, &variable_oid,
1226 &variable_oid_length, &length);
1227 if (ret != ASN1_ERR_NOERROR) {
1228 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1229 "variable binding OID", ret);
1232 sequence_length += length;
1236 oid_string = format_oid(variable_oid,
1237 variable_oid_length);
1239 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
1240 sprint_objid(vb_oid_string, variable_oid,
1241 variable_oid_length);
1242 proto_tree_add_text(tree, tvb, offset, sequence_length,
1243 "Object identifier %d: %s (%s)", vb_index,
1244 oid_string, vb_oid_string);
1245 #ifdef HAVE_SNMP_SNMP_H
1247 * CMU SNMP has a bug wherein "sprint_value()"
1248 * calls "get_symbol()", passing it the
1249 * OID supplied, to get an information about the
1250 * variable, and blithely assumes that it will
1251 * never get a null pointer back and dereferences
1252 * the resulting pointer.
1254 * Not true. If there's nothing in the MIB
1255 * about *any* of the components of the OID,
1256 * it'll return a null pointer.
1258 * So we have to check for that, and pass
1259 * down to "snmp_variable_decode" a flag
1260 * saying "don't pass this to 'sprint_value()'.
1262 * We check for that by looking for a decoded
1263 * OID string beginning with "." followed by a
1264 * digit, meaning it couldn't even find any
1265 * symbolic representation for the very
1266 * beginning of the OID string.
1268 if (vb_oid_string[0] == '.' &&
1269 isdigit((guchar)vb_oid_string[1]))
1271 #endif /* HAVE_SNMP_SNMP_H */
1272 #else /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
1273 proto_tree_add_text(tree, tvb, offset, sequence_length,
1274 "Object identifier %d: %s", vb_index,
1276 #endif /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
1279 offset += sequence_length;
1280 variable_bindings_length -= sequence_length;
1282 /* Parse the variable's value */
1283 ret = snmp_variable_decode(tree, variable_oid,
1284 variable_oid_length, &asn1, offset, &length,
1286 if (ret != ASN1_ERR_NOERROR) {
1287 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1292 variable_bindings_length -= length;
1296 static const value_string qos_vals[] = {
1297 { 0x0, "No authentication or privacy" },
1298 { 0x1, "Authentication, no privacy" },
1299 { 0x2, "Authentication and privacy" },
1300 { 0x3, "Authentication and privacy" },
1305 dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
1306 guchar *parameters, int parameters_length)
1309 proto_tree *parameters_tree;
1310 proto_tree *qos_tree;
1315 item = proto_tree_add_text(tree, tvb, offset, length,
1317 parameters_tree = proto_item_add_subtree(item, ett_parameters);
1318 offset += length - parameters_length;
1320 if (parameters_length < 1)
1322 model = *parameters;
1323 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1324 "model: %u", model);
1327 parameters_length -= 1;
1329 /* Unknown model. */
1330 proto_tree_add_text(parameters_tree, tvb, offset,
1331 parameters_length, "parameters: %s",
1332 bytes_to_str(parameters, parameters_length));
1336 if (parameters_length < 1)
1339 item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
1341 qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
1342 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1343 decode_boolean_bitfield(qos, 0x04,
1344 8, "Generation of report PDU allowed",
1345 "Generation of report PDU not allowed"));
1346 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1347 decode_enumerated_bitfield(qos, 0x03,
1348 8, qos_vals, "%s"));
1351 parameters_length -= 1;
1353 if (parameters_length < 12)
1355 proto_tree_add_text(parameters_tree, tvb, offset, 12,
1356 "agentID: %s", bytes_to_str(parameters, 12));
1359 parameters_length -= 12;
1361 if (parameters_length < 4)
1363 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1364 "agentBoots: %u", pntohl(parameters));
1367 parameters_length -= 4;
1369 if (parameters_length < 4)
1371 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1372 "agentTime: %u", pntohl(parameters));
1375 parameters_length -= 4;
1377 if (parameters_length < 2)
1379 proto_tree_add_text(parameters_tree, tvb, offset, 2,
1380 "maxSize: %u", pntohs(parameters));
1383 parameters_length -= 2;
1385 if (parameters_length < 1)
1388 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1389 "userLen: %u", len);
1392 parameters_length -= 1;
1394 if (parameters_length < len)
1396 proto_tree_add_text(parameters_tree, tvb, offset, len,
1397 "userName: %.*s", len, parameters);
1400 parameters_length -= len;
1402 if (parameters_length < 1)
1405 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1406 "authLen: %u", len);
1409 parameters_length -= 1;
1411 if (parameters_length < len)
1413 proto_tree_add_text(parameters_tree, tvb, offset, len,
1414 "authDigest: %s", bytes_to_str(parameters, len));
1417 parameters_length -= len;
1419 if (parameters_length < 1)
1421 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
1422 "contextSelector: %s", bytes_to_str(parameters, parameters_length));
1426 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1427 proto_tree *tree, char *proto_name, int proto, gint ett)
1434 guint message_length;
1435 guint global_length;
1441 guint32 engineboots;
1454 int msgflags_length;
1455 int community_length;
1457 int cengineid_length;
1459 int cryptpdu_length;
1460 int aengineid_length;
1461 int username_length;
1468 proto_tree *snmp_tree = NULL;
1469 proto_tree *global_tree = NULL;
1470 proto_tree *flags_tree = NULL;
1471 proto_tree *secur_tree = NULL;
1472 proto_item *item = NULL;
1474 guint cls, con, tag;
1476 if (check_col(pinfo->fd, COL_PROTOCOL))
1477 col_add_str(pinfo->fd, COL_PROTOCOL, proto_name);
1480 item = proto_tree_add_item(tree, proto, tvb, offset,
1481 tvb_length_remaining(tvb, offset), FALSE);
1482 snmp_tree = proto_item_add_subtree(item, ett);
1485 /* NOTE: we have to parse the message piece by piece, since the
1486 * capture length may be less than the message length: a 'global'
1487 * parsing is likely to fail.
1489 /* parse the SNMP header */
1490 asn1_open(&asn1, tvb, offset);
1491 ret = asn1_sequence_decode(&asn1, &message_length, &length);
1492 if (ret != ASN1_ERR_NOERROR) {
1493 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1494 "message header", ret);
1499 ret = asn1_uint32_decode (&asn1, &version, &length);
1500 if (ret != ASN1_ERR_NOERROR) {
1501 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1502 "version number", ret);
1506 proto_tree_add_text(snmp_tree, tvb, offset, length,
1508 val_to_str(version, versions, "Unknown version %#x"));
1514 case SNMP_VERSION_1:
1515 case SNMP_VERSION_2c:
1516 ret = asn1_octet_string_decode (&asn1, &community,
1517 &community_length, &length);
1518 if (ret != ASN1_ERR_NOERROR) {
1519 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1524 proto_tree_add_text(snmp_tree, tvb, offset, length,
1525 "Community: %.*s", community_length,
1526 SAFE_STRING(community));
1531 case SNMP_VERSION_2u:
1532 ret = asn1_octet_string_decode (&asn1, &community,
1533 &community_length, &length);
1535 dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
1536 community, community_length);
1541 case SNMP_VERSION_3:
1542 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1543 if (ret != ASN1_ERR_NOERROR) {
1544 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1545 "message global header", ret);
1549 item = proto_tree_add_text(snmp_tree, tvb, offset,
1550 global_length + length, "Message Global Header");
1551 global_tree = proto_item_add_subtree(item, ett_global);
1552 proto_tree_add_text(global_tree, tvb, offset,
1554 "Message Global Header Length: %d", global_length);
1557 ret = asn1_uint32_decode (&asn1, &msgid, &length);
1558 if (ret != ASN1_ERR_NOERROR) {
1559 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1564 proto_tree_add_text(global_tree, tvb, offset,
1565 length, "Message ID: %d", msgid);
1568 ret = asn1_uint32_decode (&asn1, &msgmax, &length);
1569 if (ret != ASN1_ERR_NOERROR) {
1570 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1571 "message max size", ret);
1575 proto_tree_add_text(global_tree, tvb, offset,
1576 length, "Message Max Size: %d", msgmax);
1579 ret = asn1_octet_string_decode (&asn1, &msgflags,
1580 &msgflags_length, &length);
1581 if (ret != ASN1_ERR_NOERROR) {
1582 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1583 "message flags", ret);
1586 if (msgflags_length != 1) {
1587 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1588 "message flags wrong length", ret);
1593 item = proto_tree_add_uint_format(global_tree,
1594 hf_snmpv3_flags, tvb, offset, length,
1595 msgflags[0], "Flags: 0x%02x", msgflags[0]);
1596 flags_tree = proto_item_add_subtree(item, ett_flags);
1597 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
1598 tvb, offset, length, msgflags[0]);
1599 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
1600 tvb, offset, length, msgflags[0]);
1601 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
1602 tvb, offset, length, msgflags[0]);
1604 encrypted = msgflags[0] & TH_CRYPT;
1607 ret = asn1_uint32_decode (&asn1, &msgsec, &length);
1608 if (ret != ASN1_ERR_NOERROR) {
1609 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1610 "message security model", ret);
1614 proto_tree_add_text(global_tree, tvb, offset,
1615 length, "Message Security Model: %s",
1616 val_to_str(msgsec, sec_models,
1617 "Unknown model %#x"));
1622 start = asn1.offset;
1623 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1624 &def, &secparm_length);
1625 length = asn1.offset - start;
1626 if (cls != ASN1_UNI && con != ASN1_PRI &&
1628 dissect_snmp_parse_error(tvb, offset, pinfo,
1629 snmp_tree, "Message Security Parameters",
1630 ASN1_ERR_WRONG_TYPE);
1634 item = proto_tree_add_text(snmp_tree, tvb,
1635 offset, secparm_length + length,
1636 "Message Security Parameters");
1637 secur_tree = proto_item_add_subtree(item,
1639 proto_tree_add_text(secur_tree, tvb, offset,
1641 "Message Security Parameters Length: %d",
1645 ret = asn1_sequence_decode(&asn1, &secparm_length,
1647 if (ret != ASN1_ERR_NOERROR) {
1648 dissect_snmp_parse_error(tvb, offset, pinfo,
1649 snmp_tree, "USM sequence header", ret);
1653 ret = asn1_octet_string_decode (&asn1, &aengineid,
1654 &aengineid_length, &length);
1655 if (ret != ASN1_ERR_NOERROR) {
1656 dissect_snmp_parse_error(tvb, offset, pinfo,
1657 snmp_tree, "authoritative engine id", ret);
1661 proto_tree_add_text(secur_tree, tvb, offset,
1662 length, "Authoritative Engine ID: %s",
1663 bytes_to_str(aengineid, aengineid_length));
1667 ret = asn1_uint32_decode (&asn1, &engineboots, &length);
1668 if (ret != ASN1_ERR_NOERROR) {
1669 dissect_snmp_parse_error(tvb, offset, pinfo,
1670 snmp_tree, "engine boots", ret);
1674 proto_tree_add_text(secur_tree, tvb,
1675 offset, length, "Engine Boots: %d",
1679 ret = asn1_uint32_decode (&asn1, &enginetime, &length);
1680 if (ret != ASN1_ERR_NOERROR) {
1681 dissect_snmp_parse_error(tvb, offset, pinfo,
1682 snmp_tree, "engine time", ret);
1686 proto_tree_add_text(secur_tree, tvb,
1687 offset, length, "Engine Time: %d",
1691 ret = asn1_octet_string_decode (&asn1, &username,
1692 &username_length, &length);
1693 if (ret != ASN1_ERR_NOERROR) {
1694 dissect_snmp_parse_error(tvb, offset, pinfo,
1695 snmp_tree, "user name", ret);
1699 proto_tree_add_text(secur_tree, tvb, offset,
1700 length, "User Name: %.*s",
1702 SAFE_STRING(username));
1706 ret = asn1_octet_string_decode (&asn1, &authpar,
1707 &authpar_length, &length);
1708 if (ret != ASN1_ERR_NOERROR) {
1709 dissect_snmp_parse_error(tvb, offset, pinfo,
1710 snmp_tree, "authentication parameter", ret);
1714 proto_tree_add_text(secur_tree, tvb, offset,
1715 length, "Authentication Parameter: %s",
1716 bytes_to_str(authpar, authpar_length));
1720 ret = asn1_octet_string_decode (&asn1, &privpar,
1721 &privpar_length, &length);
1722 if (ret != ASN1_ERR_NOERROR) {
1723 dissect_snmp_parse_error(tvb, offset, pinfo,
1724 snmp_tree, "privacy parameter", ret);
1728 proto_tree_add_text(secur_tree, tvb, offset,
1729 length, "Privacy Parameter: %s",
1730 bytes_to_str(privpar, privpar_length));
1736 ret = asn1_octet_string_decode (&asn1,
1737 &secparm, &secparm_length, &length);
1738 if (ret != ASN1_ERR_NOERROR) {
1739 dissect_snmp_parse_error(tvb, offset, pinfo,
1740 snmp_tree, "Message Security Parameters",
1745 proto_tree_add_text(snmp_tree, tvb, offset,
1747 "Message Security Parameters Data"
1748 " (%d bytes)", secparm_length);
1754 /* PDU starts here */
1756 ret = asn1_octet_string_decode (&asn1, &cryptpdu,
1757 &cryptpdu_length, &length);
1758 if (ret != ASN1_ERR_NOERROR) {
1759 dissect_snmp_parse_error(tvb, offset, pinfo,
1760 snmp_tree, "encrypted PDU header", ret);
1763 proto_tree_add_text(snmp_tree, tvb, offset, length,
1764 "Encrypted PDU (%d bytes)", length);
1766 if (check_col(pinfo->fd, COL_INFO))
1767 col_set_str(pinfo->fd, COL_INFO, "Encrypted PDU");
1770 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1771 if (ret != ASN1_ERR_NOERROR) {
1772 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1777 ret = asn1_octet_string_decode (&asn1, &cengineid,
1778 &cengineid_length, &length);
1779 if (ret != ASN1_ERR_NOERROR) {
1780 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1781 "context engine id", ret);
1785 proto_tree_add_text(snmp_tree, tvb, offset, length,
1786 "Context Engine ID: %s",
1787 bytes_to_str(cengineid, cengineid_length));
1791 ret = asn1_octet_string_decode (&asn1, &cname,
1792 &cname_length, &length);
1793 if (ret != ASN1_ERR_NOERROR) {
1794 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1795 "context name", ret);
1799 proto_tree_add_text(snmp_tree, tvb, offset, length,
1800 "Context Name: %.*s", cname_length,
1801 SAFE_STRING(cname));
1807 dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
1808 "PDU for unknown version of SNMP");
1812 start = asn1.offset;
1813 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1815 if (ret != ASN1_ERR_NOERROR) {
1816 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1820 if (cls != ASN1_CTX || con != ASN1_CON) {
1821 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1822 "PDU type", ASN1_ERR_WRONG_TYPE);
1825 dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
1829 dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1830 proto_tree *tree, int proto, gint ett)
1838 char *pdu_type_string;
1848 int password_length;
1850 guchar *application;
1851 int application_length;
1858 proto_tree *smux_tree = NULL;
1859 proto_item *item = NULL;
1863 if (check_col(pinfo->fd, COL_PROTOCOL))
1864 col_set_str(pinfo->fd, COL_PROTOCOL, "SMUX");
1867 item = proto_tree_add_item(tree, proto, tvb, offset,
1868 tvb_length_remaining(tvb, offset), FALSE);
1869 smux_tree = proto_item_add_subtree(item, ett);
1872 /* NOTE: we have to parse the message piece by piece, since the
1873 * capture length may be less than the message length: a 'global'
1874 * parsing is likely to fail.
1876 /* parse the SNMP header */
1877 asn1_open(&asn1, tvb, offset);
1878 start = asn1.offset;
1879 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1881 if (ret != ASN1_ERR_NOERROR) {
1882 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1887 /* Dissect SMUX here */
1888 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
1889 pdu_type_string = val_to_str(pdu_type, smux_types,
1890 "Unknown PDU type %#x");
1891 if (check_col(pinfo->fd, COL_INFO))
1892 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1893 length = asn1.offset - start;
1895 proto_tree_add_text(smux_tree, tvb, offset, length,
1896 "PDU type: %s", pdu_type_string);
1899 ret = asn1_uint32_decode (&asn1, &version, &length);
1900 if (ret != ASN1_ERR_NOERROR) {
1901 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1906 proto_tree_add_text(smux_tree, tvb, offset, length,
1907 "Version: %d", version);
1911 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1912 if (ret != ASN1_ERR_NOERROR) {
1913 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1914 "registration OID", ret);
1918 oid_string = format_oid(regid, regid_length);
1919 proto_tree_add_text(smux_tree, tvb, offset, length,
1920 "Registration: %s", oid_string);
1926 ret = asn1_octet_string_decode (&asn1, &application,
1927 &application_length, &length);
1928 if (ret != ASN1_ERR_NOERROR) {
1929 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1930 "application", ret);
1934 proto_tree_add_text(smux_tree, tvb, offset, length,
1935 "Application: %.*s", application_length,
1936 SAFE_STRING(application));
1938 g_free(application);
1941 ret = asn1_octet_string_decode (&asn1, &password,
1942 &password_length, &length);
1943 if (ret != ASN1_ERR_NOERROR) {
1944 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1949 proto_tree_add_text(smux_tree, tvb, offset, length,
1950 "Password: %.*s", password_length,
1951 SAFE_STRING(password));
1957 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
1958 pdu_type_string = val_to_str(pdu_type, smux_types,
1959 "Unknown PDU type %#x");
1960 if (check_col(pinfo->fd, COL_INFO))
1961 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1962 length = asn1.offset - start;
1964 proto_tree_add_text(smux_tree, tvb, offset, length,
1965 "PDU type: %s", pdu_type_string);
1968 ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
1969 if (ret != ASN1_ERR_NOERROR) {
1970 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1975 proto_tree_add_text(smux_tree, tvb, offset,
1976 pdu_length, "Cause: %s",
1977 val_to_str(cause, smux_close,
1978 "Unknown cause %#x"));
1980 offset += pdu_length;
1983 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
1984 pdu_type_string = val_to_str(pdu_type, smux_types,
1985 "Unknown PDU type %#x");
1986 if (check_col(pinfo->fd, COL_INFO))
1987 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1988 length = asn1.offset - start;
1990 proto_tree_add_text(smux_tree, tvb, offset, length,
1991 "PDU type: %s", pdu_type_string);
1994 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1995 if (ret != ASN1_ERR_NOERROR) {
1996 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1997 "registration subtree", ret);
2001 oid_string = format_oid(regid, regid_length);
2002 proto_tree_add_text(smux_tree, tvb, offset, length,
2003 "Registration: %s", oid_string);
2009 ret = asn1_uint32_decode (&asn1, &priority, &length);
2010 if (ret != ASN1_ERR_NOERROR) {
2011 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2016 proto_tree_add_text(smux_tree, tvb, offset, length,
2017 "Priority: %d", priority);
2021 ret = asn1_uint32_decode (&asn1, &operation, &length);
2022 if (ret != ASN1_ERR_NOERROR) {
2023 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2028 proto_tree_add_text(smux_tree, tvb, offset, length,
2030 val_to_str(operation, smux_rreq,
2031 "Unknown operation %#x"));
2036 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
2037 pdu_type_string = val_to_str(pdu_type, smux_types,
2038 "Unknown PDU type %#x");
2039 if (check_col(pinfo->fd, COL_INFO))
2040 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
2041 length = asn1.offset - start;
2043 proto_tree_add_text(smux_tree, tvb, offset, length,
2044 "PDU type: %s", pdu_type_string);
2047 ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
2048 if (ret != ASN1_ERR_NOERROR) {
2049 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2054 proto_tree_add_text(smux_tree, tvb, offset,
2056 val_to_str(priority, smux_prio,
2059 offset += pdu_length;
2062 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
2063 pdu_type_string = val_to_str(pdu_type, smux_types,
2064 "Unknown PDU type %#x");
2065 if (check_col(pinfo->fd, COL_INFO))
2066 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
2067 length = asn1.offset - start;
2069 proto_tree_add_text(smux_tree, tvb, offset, length,
2070 "PDU type: %s", pdu_type_string);
2073 ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
2074 if (ret != ASN1_ERR_NOERROR) {
2075 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2080 proto_tree_add_text(smux_tree, tvb, offset,
2082 val_to_str(commit, smux_sout,
2083 "Unknown SOUT Value: %#x"));
2085 offset += pdu_length;
2088 if (cls != ASN1_CTX || con != ASN1_CON) {
2089 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2090 "PDU type", ASN1_ERR_WRONG_TYPE);
2093 dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
2097 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2099 conversation_t *conversation;
2102 * XXX - this is a conversation dissector, and the code to
2103 * call a conversation dissector doesn't check for disabled
2104 * protocols or set "pinfo->current_proto".
2106 CHECK_DISPLAY_AS_DATA(proto_snmp, tvb, pinfo, tree);
2108 pinfo->current_proto = "SNMP";
2111 * The first SNMP packet goes to the SNMP port; the second one
2112 * may come from some *other* port, but goes back to the same
2113 * IP address and port as the ones from which the first packet
2114 * came; all subsequent packets presumably go between those two
2115 * IP addresses and ports.
2117 * If this packet went to the SNMP port, we check to see if
2118 * there's already a conversation with one address/port pair
2119 * matching the source IP address and port of this packet,
2120 * the other address matching the destination IP address of this
2121 * packet, and any destination port.
2123 * If not, we create one, with its address 1/port 1 pair being
2124 * the source address/port of this packet, its address 2 being
2125 * the destination address of this packet, and its port 2 being
2126 * wildcarded, and give it the SNMP dissector as a dissector.
2128 if (pinfo->destport == UDP_PORT_SNMP) {
2129 conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
2130 pinfo->srcport, 0, NO_PORT_B);
2131 if (conversation == NULL) {
2132 conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
2133 pinfo->srcport, 0, NULL,
2135 conversation_set_dissector(conversation, dissect_snmp);
2139 dissect_snmp_pdu(tvb, 0, pinfo, tree, "SNMP", proto_snmp, ett_snmp);
2143 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2145 dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
2149 proto_register_snmp(void)
2151 #if defined(HAVE_UCD_SNMP_SNMP_H) && defined(linux)
2152 void *libsnmp_handle;
2153 int (*snmp_set_suffix_only_p)(int);
2154 int (*ds_set_int_p)(int, int, int);
2157 static hf_register_info hf[] = {
2159 { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
2161 { &hf_snmpv3_flags_auth,
2162 { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
2163 TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
2164 { &hf_snmpv3_flags_crypt,
2165 { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
2166 TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
2167 { &hf_snmpv3_flags_report,
2168 { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
2169 TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
2171 static gint *ett[] = {
2175 &ett_parameters_qos,
2181 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
2182 /* UCD or CMU SNMP */
2184 #ifdef HAVE_UCD_SNMP_SNMP_H
2186 /* As per the comment near the beginning of the file, UCD SNMP 4.1.1
2187 changed "snmp_set_suffix_only()" from a function to a macro,
2188 removing "snmp_set_suffix_only()" from the library; this means
2189 that binaries that call "snmp_set_suffix_only()" and
2190 that are linked against shared libraries from earlier versions
2191 of the UCD SNMP library won't run with shared libraries from
2194 This is a problem on Red Hat Linux, as pre-6.2 releases
2195 came with pre-4.1.1 UCD SNMP, while 6.2 comes the 4.1.1.
2196 Versions of Ethereal built on pre-6.2 releases don't run
2197 on 6.2, and the current Ethereal RPMs are built on pre-6.2
2198 releases, causing problems when users running 6.2 download
2199 them and try to use them.
2201 Building the releases on 6.2 isn't necessarily the answer,
2202 as "snmp_set_suffix_only()" expands to a call to "ds_set_int()"
2203 with a second argument not supported by at least some pre-4.1.1
2204 versions of the library - it appears that the 4.0.1 library,
2205 at least, checks for invalid arguments and returns an error
2206 rather than stomping random memory, but that means that you
2207 won't get get OIDs displayed as module-name::sub-OID.
2209 So we use a trick similar to one I've seen mentioned as
2210 used in Windows applications to let you build binaries
2211 that run on many different versions of Windows 9x and
2212 Windows NT, that use features present on later versions
2213 if run on those later versions, but that avoid calling,
2214 when run on older versions, routines not present on those
2217 I.e., we load "libsnmp.so.0" with "dlopen()", and call
2218 "dlsym()" to try to find "snmp_set_suffix_only()"; if we
2219 don't find it, we make the appropriate call to
2220 "ds_set_int()" instead. (We load "libsnmp.so.0" rather
2221 than "libsnmp.so" because, at least on RH 6.2, "libsnmp.so"
2222 exists only if you've loaded the libsnmp development package,
2223 which makes "libsnmp.so" a symlink to "libsnmp.so.0"; we
2224 don't want to force users to install it or to make said
2227 We do this only on Linux, for now, as we've only seen the
2228 problem on Red Hat; it may show up on other OSes that bundle
2229 UCD SNMP, or on OSes where it's not bundled but for which
2230 binary packages are built that link against a shared version
2231 of the UCD SNMP library. If we run into one of those, we
2232 can do this under those OSes as well, *if* "dlopen()" makes
2233 the run-time linker use the same search rules as it uses when
2234 loading libraries with which the application is linked.
2236 (Perhaps we could use the GLib wrappers for run-time linking,
2237 *if* they're thin enough; however, as this code is currently
2238 used only on Linux, we don't worry about that for now.) */
2240 libsnmp_handle = dlopen("libsnmp.so.0", RTLD_LAZY|RTLD_GLOBAL);
2241 if (libsnmp_handle == NULL) {
2242 /* We didn't find "libsnmp.so.0".
2244 This could mean that there is no SNMP shared library
2245 on this system, in which case we were linked statically,
2246 in which case whatever call the following line of code
2247 makes will presumably work, as we have the routine it
2248 calls wired into our binary. (If we were linked
2249 dynamically with "-lsnmp", we would have failed to
2252 It could also mean that there is an SNMP shared library
2253 on this system, but it's called something other than
2254 "libsnmp.so.0"; so far, we've seen the problem we're
2255 working around only on systems where the SNMP shared
2256 library is called "libsnmp.so.0", so we assume for now
2257 that systems with shared SNMP libraries named something
2258 other than "libsnmp.so.0" have an SNMP library that's
2260 snmp_set_suffix_only(2);
2262 /* OK, we have it loaded. Do we have
2263 "snmp_set_suffix_only()"? */
2264 snmp_set_suffix_only_p = dlsym(libsnmp_handle,
2265 "snmp_set_suffix_only");
2266 if (snmp_set_suffix_only_p != NULL) {
2267 /* Yes - call it. */
2268 (*snmp_set_suffix_only_p)(2);
2270 /* No; do we have "ds_set_int()"? */
2271 ds_set_int_p = dlsym(libsnmp_handle, "ds_set_int");
2272 if (ds_set_int_p != NULL) {
2273 /* Yes - cal it with DS_LIBRARY_ID,
2274 DS_LIB_PRINT_SUFFIX_ONLY, and 2 as
2277 We do *not* use DS_LIBRARY_ID or
2278 DS_LIB_PRINT_SUFFIX_ONLY by name, so that
2279 we don't require that Ethereal be built
2280 with versions of UCD SNMP that include
2281 that value; instead, we use their values
2282 in UCD SNMP 4.1.1, which are 0 and 4,
2284 (*ds_set_int_p)(0, 4, 2);
2287 dlclose(libsnmp_handle);
2290 snmp_set_suffix_only(2);
2292 #endif /* HAVE_UCD_SNMP_SNMP_H */
2293 #endif /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
2294 proto_snmp = proto_register_protocol("Simple Network Management Protocol",
2296 proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2298 proto_register_field_array(proto_snmp, hf, array_length(hf));
2299 proto_register_subtree_array(ett, array_length(ett));
2303 proto_reg_handoff_snmp(void)
2305 dissector_add("udp.port", UDP_PORT_SNMP, dissect_snmp, proto_snmp);
2306 dissector_add("udp.port", UDP_PORT_SNMP_TRAP, dissect_snmp, proto_snmp);
2307 dissector_add("tcp.port", TCP_PORT_SMUX, dissect_smux, proto_smux);
2308 dissector_add("ethertype", ETHERTYPE_SNMP, dissect_snmp, proto_snmp);
2309 dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, dissect_snmp,
2311 dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, dissect_snmp,