2 * Routines for SNMP (simple network management protocol)
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.67 2001/04/23 04:29:53 guy Exp $
13 * Ethereal - Network traffic analyzer
14 * By Gerald Combs <gerald@zing.org>
15 * Copyright 1998 Didier Jorand
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)
586 result_len = oid_length * 22;
587 result = g_malloc(result_len + 1);
589 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
591 for (i = 1; i < oid_length;i++) {
592 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
598 #ifdef HAVE_SPRINT_VALUE
600 format_var(struct variable_list *variable, subid_t *variable_oid,
601 guint variable_oid_length, gushort vb_type, guint vb_length)
611 /* We don't know how long this will be, but let's guess it
612 fits within 128 characters; that should be enough for an
613 integral value plus some sort of type indication. */
623 /* We don't know how long this will be, but let's guess it
624 fits within 128 characters plus 4 characters per octet. */
625 buf = g_malloc(128 + 4*vb_length);
629 /* We don't know how long this will be, but let's guess it
630 fits within 128 characters plus 32 characters per subid
631 (10 digits plus period, or a subid name). */
632 buf = g_malloc(1024 + 32*vb_length);
636 /* Should not happen. */
637 g_assert_not_reached();
642 variable->next_variable = NULL;
643 variable->name = variable_oid;
644 variable->name_length = variable_oid_length;
648 variable->type = VALTYPE_INTEGER;
652 variable->type = VALTYPE_COUNTER;
656 variable->type = VALTYPE_GAUGE;
660 variable->type = VALTYPE_TIMETICKS;
664 variable->type = VALTYPE_STRING;
668 variable->type = VALTYPE_IPADDR;
672 variable->type = VALTYPE_OPAQUE;
676 variable->type = VALTYPE_NSAP;
680 variable->type = VALTYPE_OBJECTID;
681 vb_length *= sizeof (subid_t); /* XXX - necessary? */
685 variable->type = VALTYPE_BITSTR;
689 variable->type = VALTYPE_COUNTER64;
692 variable->val_len = vb_length;
694 sprint_value(buf, variable_oid, variable_oid_length, variable);
700 snmp_variable_decode(proto_tree *snmp_tree, subid_t *variable_oid,
701 guint variable_oid_length, ASN1_SCK *asn1, int offset, guint *lengthp,
713 gint32 vb_integer_value;
714 guint32 vb_uinteger_value;
716 guint8 *vb_octet_string;
721 gchar *vb_display_string;
723 #ifdef HAVE_SPRINT_VALUE
724 struct variable_list variable;
725 #if defined(HAVE_UCD_SNMP_SNMP_H)
728 #endif /* HAVE_SPRINT_VALUE */
733 /* parse the type of the object */
734 start = asn1->offset;
735 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
736 if (ret != ASN1_ERR_NOERROR)
739 return ASN1_ERR_LENGTH_NOT_DEFINITE;
741 /* Convert the class, constructed flag, and tag to a type. */
742 vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
743 if (vb_type_name == NULL) {
746 * Dissect the value as an opaque string of octets.
748 vb_type_name = "unsupported type";
749 vb_type = SNMP_OPAQUE;
752 /* parse the value */
756 ret = asn1_int32_value_decode(asn1, vb_length,
758 if (ret != ASN1_ERR_NOERROR)
760 length = asn1->offset - start;
762 #ifdef HAVE_SPRINT_VALUE
764 #if defined(HAVE_UCD_SNMP_SNMP_H)
765 value = vb_integer_value;
766 variable.val.integer = &value;
767 #elif defined(HAVE_SNMP_SNMP_H)
768 variable.val.integer = &vb_integer_value;
770 vb_display_string = format_var(&variable,
771 variable_oid, variable_oid_length, vb_type,
773 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
775 "Value: %s", vb_display_string);
776 g_free(vb_display_string);
777 break; /* we added formatted version to the tree */
779 #endif /* HAVE_SPRINT_VALUE */
780 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
781 "Value: %s: %d (%#x)", vb_type_name,
782 vb_integer_value, vb_integer_value);
789 ret = asn1_uint32_value_decode(asn1, vb_length,
791 if (ret != ASN1_ERR_NOERROR)
793 length = asn1->offset - start;
795 #ifdef HAVE_SPRINT_VALUE
797 #if defined(HAVE_UCD_SNMP_SNMP_H)
798 value = vb_uinteger_value;
799 variable.val.integer = &value;
800 #elif defined(HAVE_SNMP_SNMP_H)
801 variable.val.integer = &vb_uinteger_value;
803 vb_display_string = format_var(&variable,
804 variable_oid, variable_oid_length, vb_type,
806 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
808 "Value: %s", vb_display_string);
809 g_free(vb_display_string);
810 break; /* we added formatted version to the tree */
812 #endif /* HAVE_SPRINT_VALUE */
813 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
814 "Value: %s: %u (%#x)", vb_type_name,
815 vb_uinteger_value, vb_uinteger_value);
825 ret = asn1_string_value_decode (asn1, vb_length,
827 if (ret != ASN1_ERR_NOERROR)
829 length = asn1->offset - start;
831 #ifdef HAVE_SPRINT_VALUE
833 variable.val.string = vb_octet_string;
834 vb_display_string = format_var(&variable,
835 variable_oid, variable_oid_length, vb_type,
837 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
839 "Value: %s", vb_display_string);
840 g_free(vb_display_string);
841 break; /* we added formatted version to the tree */
843 #endif /* HAVE_SPRINT_VALUE */
845 * If some characters are not printable, display
846 * the string as bytes.
848 for (i = 0; i < vb_length; i++) {
849 if (!(isprint(vb_octet_string[i])
850 || isspace(vb_octet_string[i])))
855 * We stopped, due to a non-printable
856 * character, before we got to the end
859 vb_display_string = g_malloc(4*vb_length);
860 buf = &vb_display_string[0];
861 len = sprintf(buf, "%03u", vb_octet_string[0]);
863 for (i = 1; i < vb_length; i++) {
864 len = sprintf(buf, ".%03u",
868 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
869 "Value: %s: %s", vb_type_name,
871 g_free(vb_display_string);
873 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
874 "Value: %s: %.*s", vb_type_name,
876 SAFE_STRING(vb_octet_string));
879 g_free(vb_octet_string);
883 ret = asn1_null_decode (asn1, vb_length);
884 if (ret != ASN1_ERR_NOERROR)
886 length = asn1->offset - start;
888 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
889 "Value: %s", vb_type_name);
894 ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
896 if (ret != ASN1_ERR_NOERROR)
898 length = asn1->offset - start;
900 #ifdef HAVE_SPRINT_VALUE
902 variable.val.objid = vb_oid;
903 vb_display_string = format_var(&variable,
904 variable_oid, variable_oid_length, vb_type,
906 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
908 "Value: %s", vb_display_string);
909 break; /* we added formatted version to the tree */
911 #endif /* HAVE_SPRINT_VALUE */
912 vb_display_string = format_oid(vb_oid, vb_oid_length);
913 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
914 "Value: %s: %s", vb_type_name, vb_display_string);
915 g_free(vb_display_string);
920 case SNMP_NOSUCHOBJECT:
921 length = asn1->offset - start;
923 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
924 "Value: %s: no such object", vb_type_name);
928 case SNMP_NOSUCHINSTANCE:
929 length = asn1->offset - start;
931 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
932 "Value: %s: no such instance", vb_type_name);
936 case SNMP_ENDOFMIBVIEW:
937 length = asn1->offset - start;
939 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
940 "Value: %s: end of mib view", vb_type_name);
945 g_assert_not_reached();
946 return ASN1_ERR_WRONG_TYPE;
949 return ASN1_ERR_NOERROR;
953 dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
954 proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
958 guint sequence_length;
962 guint32 error_status;
966 char *pdu_type_string;
969 guint enterprise_length;
971 guint8 *agent_address;
972 guint agent_address_length;
976 guint32 specific_type;
979 guint timestamp_length;
983 guint variable_bindings_length;
986 guint variable_length;
987 subid_t *variable_oid;
988 guint variable_oid_length;
989 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
990 gchar vb_oid_string[MAX_STRING_LEN]; /* TBC */
997 pdu_type_string = val_to_str(pdu_type, pdu_types,
998 "Unknown PDU type %#x");
999 if (check_col(pinfo->fd, COL_INFO))
1000 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1001 length = asn1.offset - start;
1003 proto_tree_add_text(tree, tvb, offset, length,
1004 "PDU type: %s", pdu_type_string);
1008 /* get the fields in the PDU preceeding the variable-bindings sequence */
1012 case SNMP_MSG_GETNEXT:
1013 case SNMP_MSG_RESPONSE:
1015 case SNMP_MSG_GETBULK:
1016 case SNMP_MSG_INFORM:
1017 case SNMP_MSG_TRAP2:
1018 case SNMP_MSG_REPORT:
1020 ret = asn1_uint32_decode (&asn1, &request_id, &length);
1021 if (ret != ASN1_ERR_NOERROR) {
1022 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1027 proto_tree_add_text(tree, tvb, offset, length,
1028 "Request Id: %#x", request_id);
1032 /* error status, or getbulk non-repeaters */
1033 ret = asn1_uint32_decode (&asn1, &error_status, &length);
1034 if (ret != ASN1_ERR_NOERROR) {
1035 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1036 (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
1042 if (pdu_type == SNMP_MSG_GETBULK) {
1043 proto_tree_add_text(tree, tvb, offset,
1044 length, "Non-repeaters: %u", error_status);
1046 proto_tree_add_text(tree, tvb, offset,
1047 length, "Error Status: %s",
1048 val_to_str(error_status, error_statuses,
1054 /* error index, or getbulk max-repetitions */
1055 ret = asn1_uint32_decode (&asn1, &error_index, &length);
1056 if (ret != ASN1_ERR_NOERROR) {
1057 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1058 (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
1064 if (pdu_type == SNMP_MSG_GETBULK) {
1065 proto_tree_add_text(tree, tvb, offset,
1066 length, "Max repetitions: %u", error_index);
1068 proto_tree_add_text(tree, tvb, offset,
1069 length, "Error Index: %u", error_index);
1077 ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
1079 if (ret != ASN1_ERR_NOERROR) {
1080 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1081 "enterprise OID", ret);
1085 oid_string = format_oid(enterprise, enterprise_length);
1086 proto_tree_add_text(tree, tvb, offset, length,
1087 "Enterprise: %s", oid_string);
1094 start = asn1.offset;
1095 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1096 &def, &agent_address_length);
1097 if (ret != ASN1_ERR_NOERROR) {
1098 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1099 "agent address", ret);
1102 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
1103 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
1104 /* GXSNMP 0.0.15 says the latter is "needed for
1106 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1107 "agent_address", ASN1_ERR_WRONG_TYPE);
1110 if (agent_address_length != 4) {
1111 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1112 "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
1115 ret = asn1_string_value_decode (&asn1,
1116 agent_address_length, &agent_address);
1117 if (ret != ASN1_ERR_NOERROR) {
1118 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1119 "agent address", ret);
1122 length = asn1.offset - start;
1124 if (agent_address_length != 4) {
1125 proto_tree_add_text(tree, tvb, offset,
1127 "Agent address: <length is %u, not 4>",
1128 agent_address_length);
1130 proto_tree_add_text(tree, tvb, offset,
1132 "Agent address: %s",
1133 ip_to_str(agent_address));
1136 g_free(agent_address);
1139 /* generic trap type */
1140 ret = asn1_uint32_decode (&asn1, &trap_type, &length);
1141 if (ret != ASN1_ERR_NOERROR) {
1142 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1143 "generic trap type", ret);
1147 proto_tree_add_text(tree, tvb, offset, length,
1149 val_to_str(trap_type, trap_types, "Unknown (%u)"));
1153 /* specific trap type */
1154 ret = asn1_uint32_decode (&asn1, &specific_type, &length);
1155 if (ret != ASN1_ERR_NOERROR) {
1156 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1157 "specific trap type", ret);
1161 proto_tree_add_text(tree, tvb, offset, length,
1162 "Specific trap type: %u (%#x)",
1163 specific_type, specific_type);
1168 start = asn1.offset;
1169 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1170 &def, ×tamp_length);
1171 if (ret != ASN1_ERR_NOERROR) {
1172 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1176 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
1177 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
1178 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1179 "timestamp", ASN1_ERR_WRONG_TYPE);
1182 ret = asn1_uint32_value_decode(&asn1, timestamp_length,
1184 if (ret != ASN1_ERR_NOERROR) {
1185 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1189 length = asn1.offset - start;
1191 proto_tree_add_text(tree, tvb, offset, length,
1192 "Timestamp: %u", timestamp);
1198 /* variable bindings */
1199 /* get header for variable-bindings sequence */
1200 ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
1201 if (ret != ASN1_ERR_NOERROR) {
1202 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1203 "variable bindings header", ret);
1208 /* loop on variable bindings */
1210 while (variable_bindings_length > 0) {
1212 sequence_length = 0;
1215 ret = asn1_sequence_decode(&asn1, &variable_length, &length);
1216 if (ret != ASN1_ERR_NOERROR) {
1217 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1218 "variable binding header", ret);
1221 sequence_length += length;
1223 /* parse object identifier */
1224 ret = asn1_oid_decode (&asn1, &variable_oid,
1225 &variable_oid_length, &length);
1226 if (ret != ASN1_ERR_NOERROR) {
1227 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1228 "variable binding OID", ret);
1231 sequence_length += length;
1235 oid_string = format_oid(variable_oid,
1236 variable_oid_length);
1238 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
1239 sprint_objid(vb_oid_string, variable_oid,
1240 variable_oid_length);
1241 proto_tree_add_text(tree, tvb, offset, sequence_length,
1242 "Object identifier %d: %s (%s)", vb_index,
1243 oid_string, vb_oid_string);
1244 #ifdef HAVE_SNMP_SNMP_H
1246 * CMU SNMP has a bug wherein "sprint_value()"
1247 * calls "get_symbol()", passing it the
1248 * OID supplied, to get an information about the
1249 * variable, and blithely assumes that it will
1250 * never get a null pointer back and dereferences
1251 * the resulting pointer.
1253 * Not true. If there's nothing in the MIB
1254 * about *any* of the components of the OID,
1255 * it'll return a null pointer.
1257 * So we have to check for that, and pass
1258 * down to "snmp_variable_decode" a flag
1259 * saying "don't pass this to 'sprint_value()'.
1261 * We check for that by looking for a decoded
1262 * OID string beginning with "." followed by a
1263 * digit, meaning it couldn't even find any
1264 * symbolic representation for the very
1265 * beginning of the OID string.
1267 if (vb_oid_string[0] == '.' &&
1268 isdigit((guchar)vb_oid_string[1]))
1270 #endif /* HAVE_SNMP_SNMP_H */
1271 #else /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
1272 proto_tree_add_text(tree, tvb, offset, sequence_length,
1273 "Object identifier %d: %s", vb_index,
1275 #endif /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
1278 offset += sequence_length;
1279 variable_bindings_length -= sequence_length;
1281 /* Parse the variable's value */
1282 ret = snmp_variable_decode(tree, variable_oid,
1283 variable_oid_length, &asn1, offset, &length,
1285 if (ret != ASN1_ERR_NOERROR) {
1286 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1291 variable_bindings_length -= length;
1295 static const value_string qos_vals[] = {
1296 { 0x0, "No authentication or privacy" },
1297 { 0x1, "Authentication, no privacy" },
1298 { 0x2, "Authentication and privacy" },
1299 { 0x3, "Authentication and privacy" },
1304 dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
1305 guchar *parameters, int parameters_length)
1308 proto_tree *parameters_tree;
1309 proto_tree *qos_tree;
1314 item = proto_tree_add_text(tree, tvb, offset, length,
1316 parameters_tree = proto_item_add_subtree(item, ett_parameters);
1317 offset += length - parameters_length;
1319 if (parameters_length < 1)
1321 model = *parameters;
1322 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1323 "model: %u", model);
1326 parameters_length -= 1;
1328 /* Unknown model. */
1329 proto_tree_add_text(parameters_tree, tvb, offset,
1330 parameters_length, "parameters: %s",
1331 bytes_to_str(parameters, parameters_length));
1335 if (parameters_length < 1)
1338 item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
1340 qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
1341 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1342 decode_boolean_bitfield(qos, 0x04,
1343 8, "Generation of report PDU allowed",
1344 "Generation of report PDU not allowed"));
1345 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1346 decode_enumerated_bitfield(qos, 0x03,
1347 8, qos_vals, "%s"));
1350 parameters_length -= 1;
1352 if (parameters_length < 12)
1354 proto_tree_add_text(parameters_tree, tvb, offset, 12,
1355 "agentID: %s", bytes_to_str(parameters, 12));
1358 parameters_length -= 12;
1360 if (parameters_length < 4)
1362 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1363 "agentBoots: %u", pntohl(parameters));
1366 parameters_length -= 4;
1368 if (parameters_length < 4)
1370 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1371 "agentTime: %u", pntohl(parameters));
1374 parameters_length -= 4;
1376 if (parameters_length < 2)
1378 proto_tree_add_text(parameters_tree, tvb, offset, 2,
1379 "maxSize: %u", pntohs(parameters));
1382 parameters_length -= 2;
1384 if (parameters_length < 1)
1387 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1388 "userLen: %u", len);
1391 parameters_length -= 1;
1393 if (parameters_length < len)
1395 proto_tree_add_text(parameters_tree, tvb, offset, len,
1396 "userName: %.*s", len, parameters);
1399 parameters_length -= len;
1401 if (parameters_length < 1)
1404 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1405 "authLen: %u", len);
1408 parameters_length -= 1;
1410 if (parameters_length < len)
1412 proto_tree_add_text(parameters_tree, tvb, offset, len,
1413 "authDigest: %s", bytes_to_str(parameters, len));
1416 parameters_length -= len;
1418 if (parameters_length < 1)
1420 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
1421 "contextSelector: %s", bytes_to_str(parameters, parameters_length));
1425 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1426 proto_tree *tree, char *proto_name, int proto, gint ett)
1433 guint message_length;
1434 guint global_length;
1440 guint32 engineboots;
1453 int msgflags_length;
1454 int community_length;
1456 int cengineid_length;
1458 int cryptpdu_length;
1459 int aengineid_length;
1460 int username_length;
1467 proto_tree *snmp_tree = NULL;
1468 proto_tree *global_tree = NULL;
1469 proto_tree *flags_tree = NULL;
1470 proto_tree *secur_tree = NULL;
1471 proto_item *item = NULL;
1473 guint cls, con, tag;
1475 if (check_col(pinfo->fd, COL_PROTOCOL))
1476 col_add_str(pinfo->fd, COL_PROTOCOL, proto_name);
1479 item = proto_tree_add_item(tree, proto, tvb, offset,
1480 tvb_length_remaining(tvb, offset), FALSE);
1481 snmp_tree = proto_item_add_subtree(item, ett);
1484 /* NOTE: we have to parse the message piece by piece, since the
1485 * capture length may be less than the message length: a 'global'
1486 * parsing is likely to fail.
1488 /* parse the SNMP header */
1489 asn1_open(&asn1, tvb, offset);
1490 ret = asn1_sequence_decode(&asn1, &message_length, &length);
1491 if (ret != ASN1_ERR_NOERROR) {
1492 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1493 "message header", ret);
1498 ret = asn1_uint32_decode (&asn1, &version, &length);
1499 if (ret != ASN1_ERR_NOERROR) {
1500 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1501 "version number", ret);
1505 proto_tree_add_text(snmp_tree, tvb, offset, length,
1507 val_to_str(version, versions, "Unknown version %#x"));
1513 case SNMP_VERSION_1:
1514 case SNMP_VERSION_2c:
1515 ret = asn1_octet_string_decode (&asn1, &community,
1516 &community_length, &length);
1517 if (ret != ASN1_ERR_NOERROR) {
1518 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1523 proto_tree_add_text(snmp_tree, tvb, offset, length,
1524 "Community: %.*s", community_length,
1525 SAFE_STRING(community));
1530 case SNMP_VERSION_2u:
1531 ret = asn1_octet_string_decode (&asn1, &community,
1532 &community_length, &length);
1534 dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
1535 community, community_length);
1540 case SNMP_VERSION_3:
1541 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1542 if (ret != ASN1_ERR_NOERROR) {
1543 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1544 "message global header", ret);
1548 item = proto_tree_add_text(snmp_tree, tvb, offset,
1549 global_length + length, "Message Global Header");
1550 global_tree = proto_item_add_subtree(item, ett_global);
1551 proto_tree_add_text(global_tree, tvb, offset,
1553 "Message Global Header Length: %d", global_length);
1556 ret = asn1_uint32_decode (&asn1, &msgid, &length);
1557 if (ret != ASN1_ERR_NOERROR) {
1558 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1563 proto_tree_add_text(global_tree, tvb, offset,
1564 length, "Message ID: %d", msgid);
1567 ret = asn1_uint32_decode (&asn1, &msgmax, &length);
1568 if (ret != ASN1_ERR_NOERROR) {
1569 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1570 "message max size", ret);
1574 proto_tree_add_text(global_tree, tvb, offset,
1575 length, "Message Max Size: %d", msgmax);
1578 ret = asn1_octet_string_decode (&asn1, &msgflags,
1579 &msgflags_length, &length);
1580 if (ret != ASN1_ERR_NOERROR) {
1581 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1582 "message flags", ret);
1585 if (msgflags_length != 1) {
1586 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1587 "message flags wrong length", ret);
1592 item = proto_tree_add_uint_format(global_tree,
1593 hf_snmpv3_flags, tvb, offset, length,
1594 msgflags[0], "Flags: 0x%02x", msgflags[0]);
1595 flags_tree = proto_item_add_subtree(item, ett_flags);
1596 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
1597 tvb, offset, length, msgflags[0]);
1598 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
1599 tvb, offset, length, msgflags[0]);
1600 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
1601 tvb, offset, length, msgflags[0]);
1603 encrypted = msgflags[0] & TH_CRYPT;
1606 ret = asn1_uint32_decode (&asn1, &msgsec, &length);
1607 if (ret != ASN1_ERR_NOERROR) {
1608 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1609 "message security model", ret);
1613 proto_tree_add_text(global_tree, tvb, offset,
1614 length, "Message Security Model: %s",
1615 val_to_str(msgsec, sec_models,
1616 "Unknown model %#x"));
1621 start = asn1.offset;
1622 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1623 &def, &secparm_length);
1624 length = asn1.offset - start;
1625 if (cls != ASN1_UNI && con != ASN1_PRI &&
1627 dissect_snmp_parse_error(tvb, offset, pinfo,
1628 snmp_tree, "Message Security Parameters",
1629 ASN1_ERR_WRONG_TYPE);
1633 item = proto_tree_add_text(snmp_tree, tvb,
1634 offset, secparm_length + length,
1635 "Message Security Parameters");
1636 secur_tree = proto_item_add_subtree(item,
1638 proto_tree_add_text(secur_tree, tvb, offset,
1640 "Message Security Parameters Length: %d",
1644 ret = asn1_sequence_decode(&asn1, &secparm_length,
1646 if (ret != ASN1_ERR_NOERROR) {
1647 dissect_snmp_parse_error(tvb, offset, pinfo,
1648 snmp_tree, "USM sequence header", ret);
1652 ret = asn1_octet_string_decode (&asn1, &aengineid,
1653 &aengineid_length, &length);
1654 if (ret != ASN1_ERR_NOERROR) {
1655 dissect_snmp_parse_error(tvb, offset, pinfo,
1656 snmp_tree, "authoritative engine id", ret);
1660 proto_tree_add_text(secur_tree, tvb, offset,
1661 length, "Authoritative Engine ID: %s",
1662 bytes_to_str(aengineid, aengineid_length));
1666 ret = asn1_uint32_decode (&asn1, &engineboots, &length);
1667 if (ret != ASN1_ERR_NOERROR) {
1668 dissect_snmp_parse_error(tvb, offset, pinfo,
1669 snmp_tree, "engine boots", ret);
1673 proto_tree_add_text(secur_tree, tvb,
1674 offset, length, "Engine Boots: %d",
1678 ret = asn1_uint32_decode (&asn1, &enginetime, &length);
1679 if (ret != ASN1_ERR_NOERROR) {
1680 dissect_snmp_parse_error(tvb, offset, pinfo,
1681 snmp_tree, "engine time", ret);
1685 proto_tree_add_text(secur_tree, tvb,
1686 offset, length, "Engine Time: %d",
1690 ret = asn1_octet_string_decode (&asn1, &username,
1691 &username_length, &length);
1692 if (ret != ASN1_ERR_NOERROR) {
1693 dissect_snmp_parse_error(tvb, offset, pinfo,
1694 snmp_tree, "user name", ret);
1698 proto_tree_add_text(secur_tree, tvb, offset,
1699 length, "User Name: %.*s",
1701 SAFE_STRING(username));
1705 ret = asn1_octet_string_decode (&asn1, &authpar,
1706 &authpar_length, &length);
1707 if (ret != ASN1_ERR_NOERROR) {
1708 dissect_snmp_parse_error(tvb, offset, pinfo,
1709 snmp_tree, "authentication parameter", ret);
1713 proto_tree_add_text(secur_tree, tvb, offset,
1714 length, "Authentication Parameter: %s",
1715 bytes_to_str(authpar, authpar_length));
1719 ret = asn1_octet_string_decode (&asn1, &privpar,
1720 &privpar_length, &length);
1721 if (ret != ASN1_ERR_NOERROR) {
1722 dissect_snmp_parse_error(tvb, offset, pinfo,
1723 snmp_tree, "privacy parameter", ret);
1727 proto_tree_add_text(secur_tree, tvb, offset,
1728 length, "Privacy Parameter: %s",
1729 bytes_to_str(privpar, privpar_length));
1735 ret = asn1_octet_string_decode (&asn1,
1736 &secparm, &secparm_length, &length);
1737 if (ret != ASN1_ERR_NOERROR) {
1738 dissect_snmp_parse_error(tvb, offset, pinfo,
1739 snmp_tree, "Message Security Parameters",
1744 proto_tree_add_text(snmp_tree, tvb, offset,
1746 "Message Security Parameters Data"
1747 " (%d bytes)", secparm_length);
1753 /* PDU starts here */
1755 ret = asn1_octet_string_decode (&asn1, &cryptpdu,
1756 &cryptpdu_length, &length);
1757 if (ret != ASN1_ERR_NOERROR) {
1758 dissect_snmp_parse_error(tvb, offset, pinfo,
1759 snmp_tree, "encrypted PDU header", ret);
1762 proto_tree_add_text(snmp_tree, tvb, offset, length,
1763 "Encrypted PDU (%d bytes)", length);
1765 if (check_col(pinfo->fd, COL_INFO))
1766 col_set_str(pinfo->fd, COL_INFO, "Encrypted PDU");
1769 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1770 if (ret != ASN1_ERR_NOERROR) {
1771 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1776 ret = asn1_octet_string_decode (&asn1, &cengineid,
1777 &cengineid_length, &length);
1778 if (ret != ASN1_ERR_NOERROR) {
1779 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1780 "context engine id", ret);
1784 proto_tree_add_text(snmp_tree, tvb, offset, length,
1785 "Context Engine ID: %s",
1786 bytes_to_str(cengineid, cengineid_length));
1790 ret = asn1_octet_string_decode (&asn1, &cname,
1791 &cname_length, &length);
1792 if (ret != ASN1_ERR_NOERROR) {
1793 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1794 "context name", ret);
1798 proto_tree_add_text(snmp_tree, tvb, offset, length,
1799 "Context Name: %.*s", cname_length,
1800 SAFE_STRING(cname));
1806 dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
1807 "PDU for unknown version of SNMP");
1811 start = asn1.offset;
1812 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1814 if (ret != ASN1_ERR_NOERROR) {
1815 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1819 if (cls != ASN1_CTX || con != ASN1_CON) {
1820 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1821 "PDU type", ASN1_ERR_WRONG_TYPE);
1824 dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
1828 dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1829 proto_tree *tree, int proto, gint ett)
1837 char *pdu_type_string;
1847 int password_length;
1849 guchar *application;
1850 int application_length;
1857 proto_tree *smux_tree = NULL;
1858 proto_item *item = NULL;
1862 if (check_col(pinfo->fd, COL_PROTOCOL))
1863 col_set_str(pinfo->fd, COL_PROTOCOL, "SMUX");
1866 item = proto_tree_add_item(tree, proto, tvb, offset,
1867 tvb_length_remaining(tvb, offset), FALSE);
1868 smux_tree = proto_item_add_subtree(item, ett);
1871 /* NOTE: we have to parse the message piece by piece, since the
1872 * capture length may be less than the message length: a 'global'
1873 * parsing is likely to fail.
1875 /* parse the SNMP header */
1876 asn1_open(&asn1, tvb, offset);
1877 start = asn1.offset;
1878 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1880 if (ret != ASN1_ERR_NOERROR) {
1881 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1886 /* Dissect SMUX here */
1887 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
1888 pdu_type_string = val_to_str(pdu_type, smux_types,
1889 "Unknown PDU type %#x");
1890 if (check_col(pinfo->fd, COL_INFO))
1891 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1892 length = asn1.offset - start;
1894 proto_tree_add_text(smux_tree, tvb, offset, length,
1895 "PDU type: %s", pdu_type_string);
1898 ret = asn1_uint32_decode (&asn1, &version, &length);
1899 if (ret != ASN1_ERR_NOERROR) {
1900 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1905 proto_tree_add_text(smux_tree, tvb, offset, length,
1906 "Version: %d", version);
1910 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1911 if (ret != ASN1_ERR_NOERROR) {
1912 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1913 "registration OID", ret);
1917 oid_string = format_oid(regid, regid_length);
1918 proto_tree_add_text(smux_tree, tvb, offset, length,
1919 "Registration: %s", oid_string);
1925 ret = asn1_octet_string_decode (&asn1, &application,
1926 &application_length, &length);
1927 if (ret != ASN1_ERR_NOERROR) {
1928 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1929 "application", ret);
1933 proto_tree_add_text(smux_tree, tvb, offset, length,
1934 "Application: %.*s", application_length,
1935 SAFE_STRING(application));
1937 g_free(application);
1940 ret = asn1_octet_string_decode (&asn1, &password,
1941 &password_length, &length);
1942 if (ret != ASN1_ERR_NOERROR) {
1943 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1948 proto_tree_add_text(smux_tree, tvb, offset, length,
1949 "Password: %.*s", password_length,
1950 SAFE_STRING(password));
1956 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
1957 pdu_type_string = val_to_str(pdu_type, smux_types,
1958 "Unknown PDU type %#x");
1959 if (check_col(pinfo->fd, COL_INFO))
1960 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1961 length = asn1.offset - start;
1963 proto_tree_add_text(smux_tree, tvb, offset, length,
1964 "PDU type: %s", pdu_type_string);
1967 ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
1968 if (ret != ASN1_ERR_NOERROR) {
1969 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1974 proto_tree_add_text(smux_tree, tvb, offset,
1975 pdu_length, "Cause: %s",
1976 val_to_str(cause, smux_close,
1977 "Unknown cause %#x"));
1979 offset += pdu_length;
1982 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
1983 pdu_type_string = val_to_str(pdu_type, smux_types,
1984 "Unknown PDU type %#x");
1985 if (check_col(pinfo->fd, COL_INFO))
1986 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
1987 length = asn1.offset - start;
1989 proto_tree_add_text(smux_tree, tvb, offset, length,
1990 "PDU type: %s", pdu_type_string);
1993 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
1994 if (ret != ASN1_ERR_NOERROR) {
1995 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
1996 "registration subtree", ret);
2000 oid_string = format_oid(regid, regid_length);
2001 proto_tree_add_text(smux_tree, tvb, offset, length,
2002 "Registration: %s", oid_string);
2008 ret = asn1_uint32_decode (&asn1, &priority, &length);
2009 if (ret != ASN1_ERR_NOERROR) {
2010 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2015 proto_tree_add_text(smux_tree, tvb, offset, length,
2016 "Priority: %d", priority);
2020 ret = asn1_uint32_decode (&asn1, &operation, &length);
2021 if (ret != ASN1_ERR_NOERROR) {
2022 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2027 proto_tree_add_text(smux_tree, tvb, offset, length,
2029 val_to_str(operation, smux_rreq,
2030 "Unknown operation %#x"));
2035 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
2036 pdu_type_string = val_to_str(pdu_type, smux_types,
2037 "Unknown PDU type %#x");
2038 if (check_col(pinfo->fd, COL_INFO))
2039 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
2040 length = asn1.offset - start;
2042 proto_tree_add_text(smux_tree, tvb, offset, length,
2043 "PDU type: %s", pdu_type_string);
2046 ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
2047 if (ret != ASN1_ERR_NOERROR) {
2048 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2053 proto_tree_add_text(smux_tree, tvb, offset,
2055 val_to_str(priority, smux_prio,
2058 offset += pdu_length;
2061 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
2062 pdu_type_string = val_to_str(pdu_type, smux_types,
2063 "Unknown PDU type %#x");
2064 if (check_col(pinfo->fd, COL_INFO))
2065 col_add_str(pinfo->fd, COL_INFO, pdu_type_string);
2066 length = asn1.offset - start;
2068 proto_tree_add_text(smux_tree, tvb, offset, length,
2069 "PDU type: %s", pdu_type_string);
2072 ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
2073 if (ret != ASN1_ERR_NOERROR) {
2074 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2079 proto_tree_add_text(smux_tree, tvb, offset,
2081 val_to_str(commit, smux_sout,
2082 "Unknown SOUT Value: %#x"));
2084 offset += pdu_length;
2087 if (cls != ASN1_CTX || con != ASN1_CON) {
2088 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2089 "PDU type", ASN1_ERR_WRONG_TYPE);
2092 dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
2096 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2098 conversation_t *conversation;
2101 * XXX - this is a conversation dissector, and the code to
2102 * call a conversation dissector doesn't check for disabled
2103 * protocols or set "pinfo->current_proto".
2105 CHECK_DISPLAY_AS_DATA(proto_snmp, tvb, pinfo, tree);
2107 pinfo->current_proto = "SNMP";
2110 * The first SNMP packet goes to the SNMP port; the second one
2111 * may come from some *other* port, but goes back to the same
2112 * IP address and port as the ones from which the first packet
2113 * came; all subsequent packets presumably go between those two
2114 * IP addresses and ports.
2116 * If this packet went to the SNMP port, we check to see if
2117 * there's already a conversation with the source IP address
2118 * and port of this packet, the destination IP address of this
2119 * packet, and any destination UDP port. If not, we create
2120 * one, with a wildcard UDP port, and give it the SNMP dissector
2123 if (pinfo->destport == UDP_PORT_SNMP) {
2124 conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
2125 pinfo->srcport, 0, NO_DST_PORT);
2126 if (conversation == NULL) {
2127 conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
2128 pinfo->srcport, 0, NULL,
2130 conversation_set_dissector(conversation, dissect_snmp);
2134 dissect_snmp_pdu(tvb, 0, pinfo, tree, "SNMP", proto_snmp, ett_snmp);
2138 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2140 dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
2144 proto_register_snmp(void)
2146 #if defined(HAVE_UCD_SNMP_SNMP_H) && defined(linux)
2147 void *libsnmp_handle;
2148 int (*snmp_set_suffix_only_p)(int);
2149 int (*ds_set_int_p)(int, int, int);
2152 static hf_register_info hf[] = {
2154 { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
2156 { &hf_snmpv3_flags_auth,
2157 { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
2158 TFS(&flags_set_truth), TH_AUTH, "" }},
2159 { &hf_snmpv3_flags_crypt,
2160 { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
2161 TFS(&flags_set_truth), TH_CRYPT, "" }},
2162 { &hf_snmpv3_flags_report,
2163 { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
2164 TFS(&flags_set_truth), TH_REPORT, "" }},
2166 static gint *ett[] = {
2170 &ett_parameters_qos,
2176 #if defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H)
2177 /* UCD or CMU SNMP */
2179 #ifdef HAVE_UCD_SNMP_SNMP_H
2181 /* As per the comment near the beginning of the file, UCD SNMP 4.1.1
2182 changed "snmp_set_suffix_only()" from a function to a macro,
2183 removing "snmp_set_suffix_only()" from the library; this means
2184 that binaries that call "snmp_set_suffix_only()" and
2185 that are linked against shared libraries from earlier versions
2186 of the UCD SNMP library won't run with shared libraries from
2189 This is a problem on Red Hat Linux, as pre-6.2 releases
2190 came with pre-4.1.1 UCD SNMP, while 6.2 comes the 4.1.1.
2191 Versions of Ethereal built on pre-6.2 releases don't run
2192 on 6.2, and the current Ethereal RPMs are built on pre-6.2
2193 releases, causing problems when users running 6.2 download
2194 them and try to use them.
2196 Building the releases on 6.2 isn't necessarily the answer,
2197 as "snmp_set_suffix_only()" expands to a call to "ds_set_int()"
2198 with a second argument not supported by at least some pre-4.1.1
2199 versions of the library - it appears that the 4.0.1 library,
2200 at least, checks for invalid arguments and returns an error
2201 rather than stomping random memory, but that means that you
2202 won't get get OIDs displayed as module-name::sub-OID.
2204 So we use a trick similar to one I've seen mentioned as
2205 used in Windows applications to let you build binaries
2206 that run on many different versions of Windows 9x and
2207 Windows NT, that use features present on later versions
2208 if run on those later versions, but that avoid calling,
2209 when run on older versions, routines not present on those
2212 I.e., we load "libsnmp.so.0" with "dlopen()", and call
2213 "dlsym()" to try to find "snmp_set_suffix_only()"; if we
2214 don't find it, we make the appropriate call to
2215 "ds_set_int()" instead. (We load "libsnmp.so.0" rather
2216 than "libsnmp.so" because, at least on RH 6.2, "libsnmp.so"
2217 exists only if you've loaded the libsnmp development package,
2218 which makes "libsnmp.so" a symlink to "libsnmp.so.0"; we
2219 don't want to force users to install it or to make said
2222 We do this only on Linux, for now, as we've only seen the
2223 problem on Red Hat; it may show up on other OSes that bundle
2224 UCD SNMP, or on OSes where it's not bundled but for which
2225 binary packages are built that link against a shared version
2226 of the UCD SNMP library. If we run into one of those, we
2227 can do this under those OSes as well, *if* "dlopen()" makes
2228 the run-time linker use the same search rules as it uses when
2229 loading libraries with which the application is linked.
2231 (Perhaps we could use the GLib wrappers for run-time linking,
2232 *if* they're thin enough; however, as this code is currently
2233 used only on Linux, we don't worry about that for now.) */
2235 libsnmp_handle = dlopen("libsnmp.so.0", RTLD_LAZY|RTLD_GLOBAL);
2236 if (libsnmp_handle == NULL) {
2237 /* We didn't find "libsnmp.so.0".
2239 This could mean that there is no SNMP shared library
2240 on this system, in which case we were linked statically,
2241 in which case whatever call the following line of code
2242 makes will presumably work, as we have the routine it
2243 calls wired into our binary. (If we were linked
2244 dynamically with "-lsnmp", we would have failed to
2247 It could also mean that there is an SNMP shared library
2248 on this system, but it's called something other than
2249 "libsnmp.so.0"; so far, we've seen the problem we're
2250 working around only on systems where the SNMP shared
2251 library is called "libsnmp.so.0", so we assume for now
2252 that systems with shared SNMP libraries named something
2253 other than "libsnmp.so.0" have an SNMP library that's
2255 snmp_set_suffix_only(2);
2257 /* OK, we have it loaded. Do we have
2258 "snmp_set_suffix_only()"? */
2259 snmp_set_suffix_only_p = dlsym(libsnmp_handle,
2260 "snmp_set_suffix_only");
2261 if (snmp_set_suffix_only_p != NULL) {
2262 /* Yes - call it. */
2263 (*snmp_set_suffix_only_p)(2);
2265 /* No; do we have "ds_set_int()"? */
2266 ds_set_int_p = dlsym(libsnmp_handle, "ds_set_int");
2267 if (ds_set_int_p != NULL) {
2268 /* Yes - cal it with DS_LIBRARY_ID,
2269 DS_LIB_PRINT_SUFFIX_ONLY, and 2 as
2272 We do *not* use DS_LIBRARY_ID or
2273 DS_LIB_PRINT_SUFFIX_ONLY by name, so that
2274 we don't require that Ethereal be built
2275 with versions of UCD SNMP that include
2276 that value; instead, we use their values
2277 in UCD SNMP 4.1.1, which are 0 and 4,
2279 (*ds_set_int_p)(0, 4, 2);
2282 dlclose(libsnmp_handle);
2285 snmp_set_suffix_only(2);
2287 #endif /* HAVE_UCD_SNMP_SNMP_H */
2288 #endif /* defined(HAVE_UCD_SNMP_SNMP_H) || defined(HAVE_SNMP_SNMP_H) */
2289 proto_snmp = proto_register_protocol("Simple Network Management Protocol",
2291 proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2293 proto_register_field_array(proto_snmp, hf, array_length(hf));
2294 proto_register_subtree_array(ett, array_length(ett));
2298 proto_reg_handoff_snmp(void)
2300 dissector_add("udp.port", UDP_PORT_SNMP, dissect_snmp, proto_snmp);
2301 dissector_add("udp.port", UDP_PORT_SNMP_TRAP, dissect_snmp, proto_snmp);
2302 dissector_add("tcp.port", TCP_PORT_SMUX, dissect_smux, proto_smux);
2303 dissector_add("ethertype", ETHERTYPE_SNMP, dissect_snmp, proto_snmp);
2304 dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, dissect_snmp,
2306 dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, dissect_snmp,