2 * Routines for SNMP (simple network management protocol)
3 * Copyright (C) 1998 Didier Jorand
5 * See RFC 1157 for SNMPv1.
7 * See RFCs 1901, 1905, and 1906 for SNMPv2c.
9 * See RFCs 1905, 1906, 1909, and 1910 for SNMPv2u [historic].
11 * See RFCs 2570-2576 for SNMPv3
13 * $Id: packet-snmp.c,v 1.116 2003/09/08 20:45:50 guy Exp $
15 * Ethereal - Network traffic analyzer
16 * By Gerald Combs <gerald@ethereal.com>
17 * Copyright 1998 Gerald Combs
21 * GXSNMP -- An snmp mangament application
22 * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
23 * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version 2
28 * of the License, or (at your option) any later version.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
50 #include <epan/packet.h>
51 #include <epan/strutil.h>
52 #include <epan/conversation.h>
55 #include "packet-ipx.h"
56 #include "packet-hpext.h"
57 #include "packet-frame.h"
62 # include <net-snmp/net-snmp-config.h>
63 # include <net-snmp/mib_api.h>
64 # include <net-snmp/library/default_store.h>
65 # include <net-snmp/config_api.h>
66 #else /* HAVE_NET_SNMP */
67 # include <ucd-snmp/ucd-snmp-config.h>
68 # include <ucd-snmp/asn1.h>
69 # include <ucd-snmp/snmp_api.h>
70 # include <ucd-snmp/snmp_impl.h>
71 # include <ucd-snmp/mib.h>
72 # include <ucd-snmp/default_store.h>
73 # include <ucd-snmp/read_config.h>
74 # include <ucd-snmp/tools.h>
75 #endif /* HAVE_NET_SNMP */
77 #ifndef NETSNMP_DS_LIBRARY_ID
78 # define NETSNMP_DS_LIBRARY_ID DS_LIBRARY_ID
79 # define NETSNMP_DS_LIB_NO_TOKEN_WARNINGS DS_LIB_NO_TOKEN_WARNINGS
80 # define NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY DS_LIB_PRINT_SUFFIX_ONLY
81 # define netsnmp_ds_set_boolean ds_set_boolean
82 # define netsnmp_ds_set_int ds_set_int
86 # include <epan/filesystem.h>
90 * Define values "sprint_realloc_value()" expects.
92 # define VALTYPE_INTEGER ASN_INTEGER
93 # define VALTYPE_COUNTER ASN_COUNTER
94 # define VALTYPE_GAUGE ASN_GAUGE
95 # define VALTYPE_TIMETICKS ASN_TIMETICKS
96 # define VALTYPE_STRING ASN_OCTET_STR
97 # define VALTYPE_IPADDR ASN_IPADDRESS
98 # define VALTYPE_OPAQUE ASN_OPAQUE
99 # define VALTYPE_NSAP ASN_NSAP
100 # define VALTYPE_OBJECTID ASN_OBJECT_ID
101 # define VALTYPE_BITSTR ASN_BIT_STR
102 # define VALTYPE_COUNTER64 ASN_COUNTER64
104 #endif /* HAVE_SOME_SNMP */
108 #include "packet-snmp.h"
109 #include "format-oid.h"
111 /* Take a pointer that may be null and return a pointer that's not null
112 by turning null pointers into pointers to the above null string,
113 and, if the argument pointer wasn't null, make sure we handle
114 non-printable characters in the string by escaping them. */
115 #define SAFE_STRING(s, l) (((s) != NULL) ? format_text((s), (l)) : "")
117 static int proto_snmp = -1;
119 /* Default MIB modules to load */
120 #define DEF_MIB_MODULES "IP-MIB:IF-MIB:TCP-MIB:UDP-MIB:SNMPv2-MIB:RFC1213-MIB:UCD-SNMP-MIB"
122 static gchar *mib_modules = DEF_MIB_MODULES;
123 static gboolean display_oid = TRUE;
125 static gint ett_snmp = -1;
126 static gint ett_parameters = -1;
127 static gint ett_parameters_qos = -1;
128 static gint ett_global = -1;
129 static gint ett_flags = -1;
130 static gint ett_secur = -1;
132 static int hf_snmp_version = -1;
133 static int hf_snmp_community = -1;
134 static int hf_snmp_request_id = -1;
135 static int hf_snmp_pdutype = -1;
136 static int hf_snmp_agent = -1;
137 static int hf_snmp_enterprise = -1;
138 static int hf_snmp_error_status = -1;
139 static int hf_snmp_oid = -1;
140 static int hf_snmp_traptype = -1;
141 static int hf_snmp_spectraptype = -1;
142 static int hf_snmp_timestamp = -1;
143 static int hf_snmpv3_flags = -1;
144 static int hf_snmpv3_flags_auth = -1;
145 static int hf_snmpv3_flags_crypt = -1;
146 static int hf_snmpv3_flags_report = -1;
148 static int proto_smux = -1;
150 static gint ett_smux = -1;
152 static int hf_smux_version = -1;
153 static int hf_smux_pdutype = -1;
155 /* desegmentation of SNMP-over-TCP */
156 static gboolean snmp_desegment = TRUE;
158 static dissector_handle_t snmp_handle;
159 static dissector_handle_t data_handle;
162 #define TH_CRYPT 0x02
163 #define TH_REPORT 0x04
165 #define UDP_PORT_SNMP 161
166 #define UDP_PORT_SNMP_TRAP 162
167 #define TCP_PORT_SNMP 161
168 #define TCP_PORT_SNMP_TRAP 162
169 #define TCP_PORT_SMUX 199
171 /* Protocol version numbers */
172 #define SNMP_VERSION_1 0
173 #define SNMP_VERSION_2c 1
174 #define SNMP_VERSION_2u 2
175 #define SNMP_VERSION_3 3
177 static const value_string versions[] = {
178 { SNMP_VERSION_1, "1" },
179 { SNMP_VERSION_2c, "2C" },
180 { SNMP_VERSION_2u, "2U" },
181 { SNMP_VERSION_3, "3" },
186 #define SNMP_MSG_GET 0
187 #define SNMP_MSG_GETNEXT 1
188 #define SNMP_MSG_RESPONSE 2
189 #define SNMP_MSG_SET 3
190 #define SNMP_MSG_TRAP 4
192 #define SNMP_MSG_GETBULK 5
193 #define SNMP_MSG_INFORM 6
194 #define SNMP_MSG_TRAP2 7
195 #define SNMP_MSG_REPORT 8
197 static const value_string pdu_types[] = {
198 { SNMP_MSG_GET, "GET" },
199 { SNMP_MSG_GETNEXT, "GET-NEXT" },
200 { SNMP_MSG_SET, "SET" },
201 { SNMP_MSG_RESPONSE, "RESPONSE" },
202 { SNMP_MSG_TRAP, "TRAP-V1" },
203 { SNMP_MSG_GETBULK, "GETBULK" },
204 { SNMP_MSG_INFORM, "INFORM" },
205 { SNMP_MSG_TRAP2, "TRAP-V2" },
206 { SNMP_MSG_REPORT, "REPORT" },
211 #define SMUX_MSG_OPEN 0
212 #define SMUX_MSG_CLOSE 1
213 #define SMUX_MSG_RREQ 2
214 #define SMUX_MSG_RRSP 3
215 #define SMUX_MSG_SOUT 4
217 static const value_string smux_types[] = {
218 { SMUX_MSG_OPEN, "Open" },
219 { SMUX_MSG_CLOSE, "Close" },
220 { SMUX_MSG_RREQ, "Registration Request" },
221 { SMUX_MSG_RRSP, "Registration Response" },
222 { SMUX_MSG_SOUT, "Commit Or Rollback" },
226 /* SMUX Closing causes */
227 #define SMUX_CLOSE_DOWN 0
228 #define SMUX_CLOSE_VERSION 1
229 #define SMUX_CLOSE_PACKET 2
230 #define SMUX_CLOSE_PROTOCOL 3
231 #define SMUX_CLOSE_INTERNAL 4
232 #define SMUX_CLOSE_NOAUTH 5
234 static const value_string smux_close[] = {
235 { SMUX_CLOSE_DOWN, "Going down" },
236 { SMUX_CLOSE_VERSION, "Unsupported Version" },
237 { SMUX_CLOSE_PACKET, "Packet Format Error" },
238 { SMUX_CLOSE_PROTOCOL, "Protocol Error" },
239 { SMUX_CLOSE_INTERNAL, "Internal Error" },
240 { SMUX_CLOSE_NOAUTH, "Unauthorized" },
244 /* SMUX Request codes */
245 #define SMUX_RREQ_DELETE 0
246 #define SMUX_RREQ_READONLY 1
247 #define SMUX_RREQ_READWRITE 2
249 static const value_string smux_rreq[] = {
250 { SMUX_RREQ_DELETE, "Delete" },
251 { SMUX_RREQ_READONLY, "Read Only" },
252 { SMUX_RREQ_READWRITE, "Read Write" },
256 static const value_string smux_prio[] = {
261 /* SMUX SOut codes */
262 #define SMUX_SOUT_COMMIT 0
263 #define SMUX_SOUT_ROLLBACK 1
265 static const value_string smux_sout[] = {
266 { SMUX_SOUT_COMMIT, "Commit" },
267 { SMUX_SOUT_ROLLBACK, "Rollback" },
271 /* Error status values */
272 #ifndef SNMP_ERR_NOERROR
273 #define SNMP_ERR_NOERROR 0
275 #ifndef SNMP_ERR_TOOBIG
276 #define SNMP_ERR_TOOBIG 1
278 #ifndef SNMP_ERR_NOSUCHNAME
279 #define SNMP_ERR_NOSUCHNAME 2
281 #ifndef SNMP_ERR_BADVALUE
282 #define SNMP_ERR_BADVALUE 3
284 #ifndef SNMP_ERR_READONLY
285 #define SNMP_ERR_READONLY 4
287 #ifndef SNMP_ERR_GENERR
288 #define SNMP_ERR_GENERR 5
290 #ifndef SNMP_ERR_NOACCESS
291 #define SNMP_ERR_NOACCESS 6
293 #ifndef SNMP_ERR_WRONGTYPE
294 #define SNMP_ERR_WRONGTYPE 7
296 #ifndef SNMP_ERR_WRONGLENGTH
297 #define SNMP_ERR_WRONGLENGTH 8
299 #ifndef SNMP_ERR_WRONGENCODING
300 #define SNMP_ERR_WRONGENCODING 9
302 #ifndef SNMP_ERR_WRONGVALUE
303 #define SNMP_ERR_WRONGVALUE 10
305 #ifndef SNMP_ERR_NOCREATION
306 #define SNMP_ERR_NOCREATION 11
308 #ifndef SNMP_ERR_INCONSISTENTVALUE
309 #define SNMP_ERR_INCONSISTENTVALUE 12
311 #ifndef SNMP_ERR_RESOURCEUNAVAILABLE
312 #define SNMP_ERR_RESOURCEUNAVAILABLE 13
314 #ifndef SNMP_ERR_COMMITFAILED
315 #define SNMP_ERR_COMMITFAILED 14
317 #ifndef SNMP_ERR_UNDOFAILED
318 #define SNMP_ERR_UNDOFAILED 15
320 #ifndef SNMP_ERR_AUTHORIZATIONERROR
321 #define SNMP_ERR_AUTHORIZATIONERROR 16
323 #ifndef SNMP_ERR_NOTWRITABLE
324 #define SNMP_ERR_NOTWRITABLE 17
326 #ifndef SNMP_ERR_INCONSISTENTNAME
327 #define SNMP_ERR_INCONSISTENTNAME 18
330 static const value_string error_statuses[] = {
331 { SNMP_ERR_NOERROR, "NO ERROR" },
332 { SNMP_ERR_TOOBIG, "TOOBIG" },
333 { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" },
334 { SNMP_ERR_BADVALUE, "BAD VALUE" },
335 { SNMP_ERR_READONLY, "READ ONLY" },
336 { SNMP_ERR_GENERR, "GENERIC ERROR" },
337 { SNMP_ERR_NOACCESS, "NO ACCESS" },
338 { SNMP_ERR_WRONGTYPE, "WRONG TYPE" },
339 { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" },
340 { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" },
341 { SNMP_ERR_WRONGVALUE, "WRONG VALUE" },
342 { SNMP_ERR_NOCREATION, "NO CREATION" },
343 { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" },
344 { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" },
345 { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" },
346 { SNMP_ERR_UNDOFAILED, "UNDO FAILED" },
347 { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" },
348 { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" },
349 { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" },
353 /* General SNMP V1 Traps */
355 #ifndef SNMP_TRAP_COLDSTART
356 #define SNMP_TRAP_COLDSTART 0
358 #ifndef SNMP_TRAP_WARMSTART
359 #define SNMP_TRAP_WARMSTART 1
361 #ifndef SNMP_TRAP_LINKDOWN
362 #define SNMP_TRAP_LINKDOWN 2
364 #ifndef SNMP_TRAP_LINKUP
365 #define SNMP_TRAP_LINKUP 3
367 #ifndef SNMP_TRAP_AUTHFAIL
368 #define SNMP_TRAP_AUTHFAIL 4
370 #ifndef SNMP_TRAP_EGPNEIGHBORLOSS
371 #define SNMP_TRAP_EGPNEIGHBORLOSS 5
373 #ifndef SNMP_TRAP_ENTERPRISESPECIFIC
374 #define SNMP_TRAP_ENTERPRISESPECIFIC 6
377 static const value_string trap_types[] = {
378 { SNMP_TRAP_COLDSTART, "COLD START" },
379 { SNMP_TRAP_WARMSTART, "WARM START" },
380 { SNMP_TRAP_LINKDOWN, "LINK DOWN" },
381 { SNMP_TRAP_LINKUP, "LINK UP" },
382 { SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
383 { SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
384 { SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
388 /* Security Models */
390 #define SNMP_SEC_ANY 0
391 #define SNMP_SEC_V1 1
392 #define SNMP_SEC_V2C 2
393 #define SNMP_SEC_USM 3
395 static const value_string sec_models[] = {
396 { SNMP_SEC_ANY, "Any" },
397 { SNMP_SEC_V1, "V1" },
398 { SNMP_SEC_V2C, "V2C" },
399 { SNMP_SEC_USM, "USM" },
405 #define SNMP_IPA 0 /* IP Address */
406 #define SNMP_CNT 1 /* Counter (Counter32) */
407 #define SNMP_GGE 2 /* Gauge (Gauge32) */
408 #define SNMP_TIT 3 /* TimeTicks */
409 #define SNMP_OPQ 4 /* Opaque */
410 #define SNMP_NSP 5 /* NsapAddress */
411 #define SNMP_C64 6 /* Counter64 */
412 #define SNMP_U32 7 /* Uinteger32 */
421 #define SNMP_INTEGER 1 /* l */
422 #define SNMP_OCTETSTR 2 /* c */
423 #define SNMP_DISPLAYSTR 2 /* c */
424 #define SNMP_OBJECTID 3 /* ul */
425 #define SNMP_IPADDR 4 /* uc */
426 #define SNMP_COUNTER 5 /* ul */
427 #define SNMP_GAUGE 6 /* ul */
428 #define SNMP_TIMETICKS 7 /* ul */
429 #define SNMP_OPAQUE 8 /* c */
431 /* additional SNMPv2 Types */
433 #define SNMP_UINTEGER 5 /* ul */
434 #define SNMP_BITSTR 9 /* uc */
435 #define SNMP_NSAP 10 /* uc */
436 #define SNMP_COUNTER64 11 /* ul */
437 #define SNMP_NOSUCHOBJECT 12
438 #define SNMP_NOSUCHINSTANCE 13
439 #define SNMP_ENDOFMIBVIEW 14
441 typedef struct _SNMP_CNV SNMP_CNV;
451 static SNMP_CNV SnmpCnv [] =
453 {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"},
454 {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"},
455 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"},
456 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"},
457 {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"},
458 {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */
459 {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */
460 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"},
461 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"},
463 /* SNMPv2 data types and errors */
465 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"},
466 {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"},
467 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"},
468 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"},
469 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"},
474 * NAME: g_snmp_tag_cls2syntax
475 * SYNOPSIS: gboolean g_snmp_tag_cls2syntax
481 * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name.
482 * See SnmpCnv for conversion.
483 * RETURNS: name on success, NULL on failure
487 snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
492 while (cnv->syntax != -1)
494 if (cnv->tag == tag && cnv->class == cls)
496 *syntax = cnv->syntax;
505 dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
506 proto_tree *tree, const char *field_name, int ret)
510 errstr = asn1_err_to_str(ret);
512 if (check_col(pinfo->cinfo, COL_INFO)) {
513 col_add_fstr(pinfo->cinfo, COL_INFO,
514 "ERROR: Couldn't parse %s: %s", field_name, errstr);
517 proto_tree_add_text(tree, tvb, offset, 0,
518 "ERROR: Couldn't parse %s: %s", field_name, errstr);
519 call_dissector(data_handle,
520 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
525 dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
526 proto_tree *tree, const char *message)
528 if (check_col(pinfo->cinfo, COL_INFO))
529 col_add_str(pinfo->cinfo, COL_INFO, message);
532 proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
533 call_dissector(data_handle,
534 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
539 format_oid(subid_t *oid, guint oid_length)
546 #ifdef HAVE_SOME_SNMP
548 size_t oid_string_len;
552 result_len = oid_length * 22;
554 #ifdef HAVE_SOME_SNMP
556 * Get the decoded form of the OID, and add its length to the
557 * length of the result string.
559 * XXX - check for "sprint_realloc_objid()" failure.
561 oid_string_len = 256;
562 oid_string = g_malloc(oid_string_len);
565 sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
567 result_len += strlen(oid_string) + 3;
570 result = g_malloc(result_len + 1);
572 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
574 for (i = 1; i < oid_length;i++) {
575 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
579 #ifdef HAVE_SOME_SNMP
581 * Append the decoded form of the OID.
583 sprintf(buf, " (%s)", oid_string);
590 /* returns the decoded (can be NULL) and non_decoded OID strings,
591 returned pointers shall be freed by the caller */
593 new_format_oid(subid_t *oid, guint oid_length,
594 gchar **non_decoded, gchar **decoded)
600 #ifdef HAVE_SOME_SNMP
602 size_t oid_string_len;
606 * Get the decoded form of the OID, and add its length to the
607 * length of the result string.
610 oid_string_len = 256;
611 oid_string = g_malloc(oid_string_len);
614 sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
616 *decoded = oid_string;
621 *non_decoded = g_malloc(oid_length * 22 + 1);
623 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
625 for (i = 1; i < oid_length; i++) {
626 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
631 #ifdef HAVE_SOME_SNMP
633 check_var_length(guint vb_length, guint required_length)
636 static const char badlen_fmt[] = "Length is %u, should be %u";
638 if (vb_length != required_length) {
639 /* Enough room for the largest "Length is XXX,
640 should be XXX" message - 10 digits for each
642 buf = g_malloc(sizeof badlen_fmt + 10 + 10);
643 sprintf(buf, badlen_fmt, vb_length, required_length);
646 return NULL; /* length is OK */
650 format_var(struct variable_list *variable, subid_t *variable_oid,
651 guint variable_oid_length, gushort vb_type, guint val_len)
660 /* Length has to be 4 bytes. */
661 buf = check_var_length(val_len, 4);
663 return buf; /* it's not 4 bytes */
667 /* Length has to be 8 bytes. */
668 buf = check_var_length(val_len, 8);
670 return buf; /* it's not 8 bytes */
677 variable->next_variable = NULL;
678 variable->name = variable_oid;
679 variable->name_length = variable_oid_length;
683 variable->type = VALTYPE_INTEGER;
687 variable->type = VALTYPE_COUNTER;
691 variable->type = VALTYPE_GAUGE;
695 variable->type = VALTYPE_TIMETICKS;
699 variable->type = VALTYPE_STRING;
703 variable->type = VALTYPE_IPADDR;
707 variable->type = VALTYPE_OPAQUE;
711 variable->type = VALTYPE_NSAP;
715 variable->type = VALTYPE_OBJECTID;
719 variable->type = VALTYPE_BITSTR;
723 variable->type = VALTYPE_COUNTER64;
726 variable->val_len = val_len;
729 * XXX - check for "sprint_realloc_objid()" failure.
732 buf = g_malloc(buf_len);
735 sprint_realloc_value(&buf, &buf_len, &out_len, 1, variable_oid,
736 variable_oid_length, variable);
742 snmp_variable_decode(proto_tree *snmp_tree,
743 subid_t *variable_oid
744 #ifndef HAVE_SOME_SNMP
748 guint variable_oid_length
749 #ifndef HAVE_SOME_SNMP
753 ASN1_SCK *asn1, int offset, guint *lengthp)
764 gint32 vb_integer_value;
765 guint32 vb_uinteger_value;
767 guint8 *vb_octet_string;
772 gchar *vb_display_string;
774 #ifdef HAVE_SOME_SNMP
775 struct variable_list variable;
777 #else /* HAVE_SOME_SNMP */
781 #endif /* HAVE_SOME_SNMP */
783 /* parse the type of the object */
784 start = asn1->offset;
785 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
786 if (ret != ASN1_ERR_NOERROR)
789 return ASN1_ERR_LENGTH_NOT_DEFINITE;
791 /* Convert the class, constructed flag, and tag to a type. */
792 vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
793 if (vb_type_name == NULL) {
796 * Dissect the value as an opaque string of octets.
798 vb_type_name = "unsupported type";
799 vb_type = SNMP_OPAQUE;
802 /* parse the value */
806 ret = asn1_int32_value_decode(asn1, vb_length,
808 if (ret != ASN1_ERR_NOERROR)
810 length = asn1->offset - start;
812 #ifdef HAVE_SOME_SNMP
813 value = vb_integer_value;
814 variable.val.integer = &value;
815 vb_display_string = format_var(&variable,
816 variable_oid, variable_oid_length, vb_type,
818 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
820 "Value: %s", vb_display_string);
821 g_free(vb_display_string);
822 #else /* HAVE_SOME_SNMP */
823 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
825 "Value: %s: %d (%#x)", vb_type_name,
826 vb_integer_value, vb_integer_value);
827 #endif /* HAVE_SOME_SNMP */
834 ret = asn1_uint32_value_decode(asn1, vb_length,
836 if (ret != ASN1_ERR_NOERROR)
838 length = asn1->offset - start;
840 #ifdef HAVE_SOME_SNMP
841 value = vb_uinteger_value;
842 variable.val.integer = &value;
843 vb_display_string = format_var(&variable,
844 variable_oid, variable_oid_length, vb_type,
846 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
848 "Value: %s", vb_display_string);
849 g_free(vb_display_string);
850 #else /* HAVE_SOME_SNMP */
851 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
853 "Value: %s: %u (%#x)", vb_type_name,
854 vb_uinteger_value, vb_uinteger_value);
855 #endif /* HAVE_SOME_SNMP */
865 ret = asn1_string_value_decode (asn1, vb_length,
867 if (ret != ASN1_ERR_NOERROR)
869 length = asn1->offset - start;
871 #ifdef HAVE_SOME_SNMP
872 variable.val.string = vb_octet_string;
873 vb_display_string = format_var(&variable,
874 variable_oid, variable_oid_length, vb_type,
876 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
878 "Value: %s", vb_display_string);
879 g_free(vb_display_string);
880 #else /* HAVE_SOME_SNMP */
882 * If some characters are not printable, display
883 * the string as bytes.
885 for (i = 0; i < vb_length; i++) {
886 if (!(isprint(vb_octet_string[i])
887 || isspace(vb_octet_string[i])))
892 * We stopped, due to a non-printable
893 * character, before we got to the end
896 vb_display_string = g_malloc(4*vb_length);
897 buf = &vb_display_string[0];
898 len = sprintf(buf, "%03u", vb_octet_string[0]);
900 for (i = 1; i < vb_length; i++) {
901 len = sprintf(buf, ".%03u",
905 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
907 "Value: %s: %s", vb_type_name,
909 g_free(vb_display_string);
911 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
913 "Value: %s: %s", vb_type_name,
914 SAFE_STRING(vb_octet_string, vb_length));
916 #endif /* HAVE_SOME_SNMP */
918 g_free(vb_octet_string);
922 ret = asn1_null_decode (asn1, vb_length);
923 if (ret != ASN1_ERR_NOERROR)
925 length = asn1->offset - start;
927 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
928 "Value: %s", vb_type_name);
933 ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
935 if (ret != ASN1_ERR_NOERROR)
937 length = asn1->offset - start;
939 #ifdef HAVE_SOME_SNMP
940 variable.val.objid = vb_oid;
941 vb_display_string = format_var(&variable,
942 variable_oid, variable_oid_length, vb_type,
943 vb_oid_length * sizeof (subid_t));
944 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
946 "Value: %s", vb_display_string);
947 g_free(vb_display_string);
948 #else /* HAVE_SOME_SNMP */
949 vb_display_string = format_oid(vb_oid, vb_oid_length);
950 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
952 "Value: %s: %s", vb_type_name, vb_display_string);
953 g_free(vb_display_string);
954 #endif /* HAVE_SOME_SNMP */
959 case SNMP_NOSUCHOBJECT:
960 length = asn1->offset - start;
962 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
963 "Value: %s: no such object", vb_type_name);
967 case SNMP_NOSUCHINSTANCE:
968 length = asn1->offset - start;
970 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
971 "Value: %s: no such instance", vb_type_name);
975 case SNMP_ENDOFMIBVIEW:
976 length = asn1->offset - start;
978 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
979 "Value: %s: end of mib view", vb_type_name);
984 g_assert_not_reached();
985 return ASN1_ERR_WRONG_TYPE;
988 return ASN1_ERR_NOERROR;
992 dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
993 proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
997 guint sequence_length;
1001 guint32 error_status;
1003 guint32 error_index;
1005 char *pdu_type_string;
1007 subid_t *enterprise;
1008 guint enterprise_length;
1010 guint32 agent_ipaddr;
1012 guint8 *agent_address;
1013 guint agent_address_length;
1017 guint32 specific_type;
1020 guint timestamp_length;
1024 guint variable_bindings_length;
1027 guint variable_length;
1028 subid_t *variable_oid;
1029 guint variable_oid_length;
1032 guint cls, con, tag;
1034 pdu_type_string = val_to_str(pdu_type, pdu_types,
1035 "Unknown PDU type %#x");
1036 if (check_col(pinfo->cinfo, COL_INFO))
1037 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1038 length = asn1.offset - start;
1040 proto_tree_add_uint(tree, hf_snmp_pdutype, tvb, offset, length,
1045 /* get the fields in the PDU preceeding the variable-bindings sequence */
1049 case SNMP_MSG_GETNEXT:
1050 case SNMP_MSG_RESPONSE:
1052 case SNMP_MSG_GETBULK:
1053 case SNMP_MSG_INFORM:
1054 case SNMP_MSG_TRAP2:
1055 case SNMP_MSG_REPORT:
1057 ret = asn1_uint32_decode (&asn1, &request_id, &length);
1058 if (ret != ASN1_ERR_NOERROR) {
1059 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1064 proto_tree_add_uint(tree, hf_snmp_request_id,
1065 tvb, offset, length, request_id);
1069 /* error status, or getbulk non-repeaters */
1070 ret = asn1_uint32_decode (&asn1, &error_status, &length);
1071 if (ret != ASN1_ERR_NOERROR) {
1072 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1073 (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
1079 if (pdu_type == SNMP_MSG_GETBULK) {
1080 proto_tree_add_text(tree, tvb, offset,
1081 length, "Non-repeaters: %u", error_status);
1083 proto_tree_add_uint(tree,
1084 hf_snmp_error_status,
1086 length, error_status);
1091 /* error index, or getbulk max-repetitions */
1092 ret = asn1_uint32_decode (&asn1, &error_index, &length);
1093 if (ret != ASN1_ERR_NOERROR) {
1094 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1095 (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
1101 if (pdu_type == SNMP_MSG_GETBULK) {
1102 proto_tree_add_text(tree, tvb, offset,
1103 length, "Max repetitions: %u", error_index);
1105 proto_tree_add_text(tree, tvb, offset,
1106 length, "Error Index: %u", error_index);
1114 ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
1116 if (ret != ASN1_ERR_NOERROR) {
1117 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1118 "enterprise OID", ret);
1122 oid_string = format_oid(enterprise, enterprise_length);
1123 proto_tree_add_string(tree, hf_snmp_enterprise, tvb,
1124 offset, length, oid_string);
1131 start = asn1.offset;
1132 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1133 &def, &agent_address_length);
1134 if (ret != ASN1_ERR_NOERROR) {
1135 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1136 "agent address", ret);
1139 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
1140 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
1141 /* GXSNMP 0.0.15 says the latter is "needed for
1143 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1144 "agent_address", ASN1_ERR_WRONG_TYPE);
1147 if (agent_address_length != 4) {
1148 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1149 "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
1152 ret = asn1_string_value_decode (&asn1,
1153 agent_address_length, &agent_address);
1154 if (ret != ASN1_ERR_NOERROR) {
1155 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1156 "agent address", ret);
1159 length = asn1.offset - start;
1161 if (agent_address_length != 4) {
1162 proto_tree_add_text(tree, tvb, offset,
1164 "Agent address: <length is %u, not 4>",
1165 agent_address_length);
1167 memcpy((guint8 *)&agent_ipaddr, agent_address,
1168 agent_address_length);
1169 proto_tree_add_ipv4(tree, hf_snmp_agent, tvb,
1170 offset, length, agent_ipaddr);
1173 g_free(agent_address);
1176 /* generic trap type */
1177 ret = asn1_uint32_decode (&asn1, &trap_type, &length);
1178 if (ret != ASN1_ERR_NOERROR) {
1179 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1180 "generic trap type", ret);
1184 proto_tree_add_uint(tree, hf_snmp_traptype, tvb,
1185 offset, length, trap_type);
1189 /* specific trap type */
1190 ret = asn1_uint32_decode (&asn1, &specific_type, &length);
1191 if (ret != ASN1_ERR_NOERROR) {
1192 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1193 "specific trap type", ret);
1197 proto_tree_add_uint(tree, hf_snmp_spectraptype, tvb,
1198 offset, length, specific_type);
1203 start = asn1.offset;
1204 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1205 &def, ×tamp_length);
1206 if (ret != ASN1_ERR_NOERROR) {
1207 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1211 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
1212 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
1213 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1214 "timestamp", ASN1_ERR_WRONG_TYPE);
1217 ret = asn1_uint32_value_decode(&asn1, timestamp_length,
1219 if (ret != ASN1_ERR_NOERROR) {
1220 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1224 length = asn1.offset - start;
1226 proto_tree_add_uint(tree, hf_snmp_timestamp, tvb,
1227 offset, length, timestamp);
1233 /* variable bindings */
1234 /* get header for variable-bindings sequence */
1235 ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
1236 if (ret != ASN1_ERR_NOERROR) {
1237 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1238 "variable bindings header", ret);
1243 /* loop on variable bindings */
1245 while (variable_bindings_length > 0) {
1247 sequence_length = 0;
1250 ret = asn1_sequence_decode(&asn1, &variable_length, &length);
1251 if (ret != ASN1_ERR_NOERROR) {
1252 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1253 "variable binding header", ret);
1256 sequence_length += length;
1258 /* parse object identifier */
1259 ret = asn1_oid_decode (&asn1, &variable_oid,
1260 &variable_oid_length, &length);
1261 if (ret != ASN1_ERR_NOERROR) {
1262 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1263 "variable binding OID", ret);
1266 sequence_length += length;
1268 if (display_oid || tree) {
1271 gchar *non_decoded_oid;
1273 new_format_oid(variable_oid, variable_oid_length,
1274 &non_decoded_oid, &decoded_oid);
1276 if (display_oid && check_col(pinfo->cinfo, COL_INFO)) {
1277 col_append_fstr(pinfo->cinfo, COL_INFO,
1279 (decoded_oid == NULL) ? non_decoded_oid :
1285 proto_tree_add_string_format(tree, hf_snmp_oid,
1289 "Object identifier %d: %s (%s)",
1293 /* add also the non decoded oid string */
1294 proto_tree_add_string_hidden(tree, hf_snmp_oid,
1299 proto_tree_add_string_format(tree, hf_snmp_oid,
1303 "Object identifier %d: %s",
1309 if (decoded_oid) g_free(decoded_oid);
1310 g_free(non_decoded_oid);
1314 offset += sequence_length;
1315 variable_bindings_length -= sequence_length;
1317 /* Parse the variable's value */
1318 ret = snmp_variable_decode(tree, variable_oid,
1319 variable_oid_length, &asn1, offset, &length);
1320 if (ret != ASN1_ERR_NOERROR) {
1321 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1326 variable_bindings_length -= length;
1330 static const value_string qos_vals[] = {
1331 { 0x0, "No authentication or privacy" },
1332 { 0x1, "Authentication, no privacy" },
1333 { 0x2, "Authentication and privacy" },
1334 { 0x3, "Authentication and privacy" },
1339 dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
1340 guchar *parameters, int parameters_length)
1343 proto_tree *parameters_tree;
1344 proto_tree *qos_tree;
1349 item = proto_tree_add_text(tree, tvb, offset, length,
1351 parameters_tree = proto_item_add_subtree(item, ett_parameters);
1352 offset += length - parameters_length;
1354 if (parameters_length < 1)
1356 model = *parameters;
1357 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1358 "model: %u", model);
1361 parameters_length -= 1;
1363 /* Unknown model. */
1364 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length, "parameters: %s",
1365 bytes_to_str(parameters, parameters_length));
1369 if (parameters_length < 1)
1372 item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
1374 qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
1375 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1376 decode_boolean_bitfield(qos, 0x04,
1377 8, "Generation of report PDU allowed",
1378 "Generation of report PDU not allowed"));
1379 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1380 decode_enumerated_bitfield(qos, 0x03,
1381 8, qos_vals, "%s"));
1384 parameters_length -= 1;
1386 if (parameters_length < 12)
1388 proto_tree_add_text(parameters_tree, tvb, offset, 12,
1389 "agentID: %s", bytes_to_str(parameters, 12));
1392 parameters_length -= 12;
1394 if (parameters_length < 4)
1396 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1397 "agentBoots: %u", pntohl(parameters));
1400 parameters_length -= 4;
1402 if (parameters_length < 4)
1404 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1405 "agentTime: %u", pntohl(parameters));
1408 parameters_length -= 4;
1410 if (parameters_length < 2)
1412 proto_tree_add_text(parameters_tree, tvb, offset, 2,
1413 "maxSize: %u", pntohs(parameters));
1416 parameters_length -= 2;
1418 if (parameters_length < 1)
1421 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1422 "userLen: %u", len);
1425 parameters_length -= 1;
1427 if (parameters_length < len)
1429 proto_tree_add_text(parameters_tree, tvb, offset, len,
1430 "userName: %.*s", len, parameters);
1433 parameters_length -= len;
1435 if (parameters_length < 1)
1438 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1439 "authLen: %u", len);
1442 parameters_length -= 1;
1444 if (parameters_length < len)
1446 proto_tree_add_text(parameters_tree, tvb, offset, len,
1447 "authDigest: %s", bytes_to_str(parameters, len));
1450 parameters_length -= len;
1452 if (parameters_length < 1)
1454 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
1455 "contextSelector: %s", bytes_to_str(parameters, parameters_length));
1459 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1460 proto_tree *tree, int proto, gint ett, gboolean is_tcp)
1462 guint length_remaining;
1468 guint message_length;
1469 guint global_length;
1475 guint32 engineboots;
1489 int msgflags_length;
1490 int community_length;
1492 int cengineid_length;
1494 int cryptpdu_length;
1495 int aengineid_length;
1496 int username_length;
1503 proto_tree *snmp_tree = NULL;
1504 proto_tree *global_tree = NULL;
1505 proto_tree *flags_tree = NULL;
1506 proto_tree *secur_tree = NULL;
1507 proto_item *item = NULL;
1509 guint cls, con, tag;
1512 * This will throw an exception if we don't have any data left.
1513 * That's what we want. (See "tcp_dissect_pdus()", which is
1514 * similar, but doesn't have to deal with ASN.1.
1515 * XXX - can we make "tcp_dissect_pdus()" provide enough
1516 * information to the "get_pdu_len" routine so that we could
1517 * have that routine deal with ASN.1, and just use
1518 * "tcp_dissect_pdus()"?)
1520 length_remaining = tvb_ensure_length_remaining(tvb, offset);
1522 /* NOTE: we have to parse the message piece by piece, since the
1523 * capture length may be less than the message length: a 'global'
1524 * parsing is likely to fail.
1528 * If this is SNMP-over-TCP, we might have to do reassembly
1529 * in order to read the "Sequence Of" header.
1531 if (is_tcp && snmp_desegment && pinfo->can_desegment) {
1533 * This is TCP, and we should, and can, do reassembly.
1535 * Is the "Sequence Of" header split across segment
1536 * boundaries? We requre at least 6 bytes for the
1537 * header, which allows for a 4-byte length (ASN.1
1540 if (length_remaining < 6) {
1541 pinfo->desegment_offset = offset;
1542 pinfo->desegment_len = 6 - length_remaining;
1545 * Return 0, which means "I didn't dissect anything
1546 * because I don't have enough data - we need
1554 * OK, try to read the "Sequence Of" header; this gets the total
1555 * length of the SNMP message.
1557 asn1_open(&asn1, tvb, offset);
1558 ret = asn1_sequence_decode(&asn1, &message_length, &length);
1559 if (ret != ASN1_ERR_NOERROR) {
1561 item = proto_tree_add_item(tree, proto, tvb, offset,
1563 snmp_tree = proto_item_add_subtree(item, ett);
1565 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1566 "message header", ret);
1569 * Return the length remaining in the tvbuff, so
1570 * if this is SNMP-over-TCP, our caller thinks there's
1571 * nothing left to dissect.
1573 return length_remaining;
1577 * Add the length of the "Sequence Of" header to the message
1580 message_length += length;
1581 if (message_length < length) {
1583 * The message length was probably so large that the
1584 * total length overflowed.
1586 * Report this as an error.
1588 show_reported_bounds_error(tvb, pinfo, tree);
1591 * Return the length remaining in the tvbuff, so
1592 * if this is SNMP-over-TCP, our caller thinks there's
1593 * nothing left to dissect.
1595 return length_remaining;
1599 * If this is SNMP-over-TCP, we might have to do reassembly
1600 * to get all of this message.
1602 if (is_tcp && snmp_desegment && pinfo->can_desegment) {
1604 * Yes - is the message split across segment boundaries?
1606 if (length_remaining < message_length) {
1608 * Yes. Tell the TCP dissector where the data
1609 * for this message starts in the data it handed
1610 * us, and how many more bytes we need, and
1613 pinfo->desegment_offset = offset;
1614 pinfo->desegment_len =
1615 message_length - length_remaining;
1618 * Return 0, which means "I didn't dissect anything
1619 * because I don't have enough data - we need
1626 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1627 col_set_str(pinfo->cinfo, COL_PROTOCOL,
1628 proto_get_protocol_short_name(proto));
1632 item = proto_tree_add_item(tree, proto, tvb, offset,
1633 message_length, FALSE);
1634 snmp_tree = proto_item_add_subtree(item, ett);
1638 ret = asn1_uint32_decode (&asn1, &version, &length);
1639 if (ret != ASN1_ERR_NOERROR) {
1640 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1641 "version number", ret);
1642 return message_length;
1645 proto_tree_add_uint(snmp_tree, hf_snmp_version, tvb, offset,
1652 case SNMP_VERSION_1:
1653 case SNMP_VERSION_2c:
1654 ret = asn1_octet_string_decode (&asn1, &community,
1655 &community_length, &length);
1656 if (ret != ASN1_ERR_NOERROR) {
1657 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1659 return message_length;
1662 commustr = g_malloc(community_length+1);
1663 memcpy(commustr, community, community_length);
1664 commustr[community_length] = '\0';
1666 proto_tree_add_string(snmp_tree, hf_snmp_community,
1667 tvb, offset, length, commustr);
1673 case SNMP_VERSION_2u:
1674 ret = asn1_octet_string_decode (&asn1, &community,
1675 &community_length, &length);
1677 dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
1678 community, community_length);
1683 case SNMP_VERSION_3:
1684 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1685 if (ret != ASN1_ERR_NOERROR) {
1686 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1687 "message global header", ret);
1688 return message_length;
1691 item = proto_tree_add_text(snmp_tree, tvb, offset,
1692 global_length + length, "Message Global Header");
1693 global_tree = proto_item_add_subtree(item, ett_global);
1694 proto_tree_add_text(global_tree, tvb, offset,
1696 "Message Global Header Length: %d", global_length);
1699 ret = asn1_uint32_decode (&asn1, &msgid, &length);
1700 if (ret != ASN1_ERR_NOERROR) {
1701 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1703 return message_length;
1706 proto_tree_add_text(global_tree, tvb, offset,
1707 length, "Message ID: %d", msgid);
1710 ret = asn1_uint32_decode (&asn1, &msgmax, &length);
1711 if (ret != ASN1_ERR_NOERROR) {
1712 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1713 "message max size", ret);
1714 return message_length;
1717 proto_tree_add_text(global_tree, tvb, offset,
1718 length, "Message Max Size: %d", msgmax);
1721 ret = asn1_octet_string_decode (&asn1, &msgflags,
1722 &msgflags_length, &length);
1723 if (ret != ASN1_ERR_NOERROR) {
1724 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1725 "message flags", ret);
1726 return message_length;
1728 if (msgflags_length != 1) {
1729 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1730 "message flags wrong length", ret);
1732 return message_length;
1735 item = proto_tree_add_uint_format(global_tree,
1736 hf_snmpv3_flags, tvb, offset, length,
1737 msgflags[0], "Flags: 0x%02x", msgflags[0]);
1738 flags_tree = proto_item_add_subtree(item, ett_flags);
1739 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
1740 tvb, offset, length, msgflags[0]);
1741 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
1742 tvb, offset, length, msgflags[0]);
1743 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
1744 tvb, offset, length, msgflags[0]);
1746 encrypted = msgflags[0] & TH_CRYPT;
1749 ret = asn1_uint32_decode (&asn1, &msgsec, &length);
1750 if (ret != ASN1_ERR_NOERROR) {
1751 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1752 "message security model", ret);
1753 return message_length;
1756 proto_tree_add_text(global_tree, tvb, offset,
1757 length, "Message Security Model: %s",
1758 val_to_str(msgsec, sec_models,
1759 "Unknown model %#x"));
1764 start = asn1.offset;
1765 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1766 &def, &secparm_length);
1767 length = asn1.offset - start;
1768 if (cls != ASN1_UNI && con != ASN1_PRI &&
1770 dissect_snmp_parse_error(tvb, offset, pinfo,
1771 snmp_tree, "Message Security Parameters",
1772 ASN1_ERR_WRONG_TYPE);
1773 return message_length;
1776 item = proto_tree_add_text(snmp_tree, tvb,
1777 offset, secparm_length + length,
1778 "Message Security Parameters");
1779 secur_tree = proto_item_add_subtree(item,
1781 proto_tree_add_text(secur_tree, tvb, offset,
1783 "Message Security Parameters Length: %d",
1787 ret = asn1_sequence_decode(&asn1, &secparm_length,
1789 if (ret != ASN1_ERR_NOERROR) {
1790 dissect_snmp_parse_error(tvb, offset, pinfo,
1791 snmp_tree, "USM sequence header", ret);
1792 return message_length;
1795 ret = asn1_octet_string_decode (&asn1, &aengineid,
1796 &aengineid_length, &length);
1797 if (ret != ASN1_ERR_NOERROR) {
1798 dissect_snmp_parse_error(tvb, offset, pinfo,
1799 snmp_tree, "authoritative engine id", ret);
1800 return message_length;
1803 proto_tree_add_text(secur_tree, tvb, offset,
1804 length, "Authoritative Engine ID: %s",
1805 bytes_to_str(aengineid, aengineid_length));
1809 ret = asn1_uint32_decode (&asn1, &engineboots, &length);
1810 if (ret != ASN1_ERR_NOERROR) {
1811 dissect_snmp_parse_error(tvb, offset, pinfo,
1812 snmp_tree, "engine boots", ret);
1813 return message_length;
1816 proto_tree_add_text(secur_tree, tvb,
1817 offset, length, "Engine Boots: %d",
1821 ret = asn1_uint32_decode (&asn1, &enginetime, &length);
1822 if (ret != ASN1_ERR_NOERROR) {
1823 dissect_snmp_parse_error(tvb, offset, pinfo,
1824 snmp_tree, "engine time", ret);
1825 return message_length;
1828 proto_tree_add_text(secur_tree, tvb,
1829 offset, length, "Engine Time: %d",
1833 ret = asn1_octet_string_decode (&asn1, &username,
1834 &username_length, &length);
1835 if (ret != ASN1_ERR_NOERROR) {
1836 dissect_snmp_parse_error(tvb, offset, pinfo,
1837 snmp_tree, "user name", ret);
1838 return message_length;
1841 proto_tree_add_text(secur_tree, tvb, offset,
1842 length, "User Name: %s",
1843 SAFE_STRING(username, username_length));
1847 ret = asn1_octet_string_decode (&asn1, &authpar,
1848 &authpar_length, &length);
1849 if (ret != ASN1_ERR_NOERROR) {
1850 dissect_snmp_parse_error(tvb, offset, pinfo,
1851 snmp_tree, "authentication parameter", ret);
1852 return message_length;
1855 proto_tree_add_text(secur_tree, tvb, offset,
1856 length, "Authentication Parameter: %s",
1857 bytes_to_str(authpar, authpar_length));
1861 ret = asn1_octet_string_decode (&asn1, &privpar,
1862 &privpar_length, &length);
1863 if (ret != ASN1_ERR_NOERROR) {
1864 dissect_snmp_parse_error(tvb, offset, pinfo,
1865 snmp_tree, "privacy parameter", ret);
1866 return message_length;
1869 proto_tree_add_text(secur_tree, tvb, offset,
1870 length, "Privacy Parameter: %s",
1871 bytes_to_str(privpar, privpar_length));
1877 ret = asn1_octet_string_decode (&asn1,
1878 &secparm, &secparm_length, &length);
1879 if (ret != ASN1_ERR_NOERROR) {
1880 dissect_snmp_parse_error(tvb, offset, pinfo,
1881 snmp_tree, "Message Security Parameters",
1883 return message_length;
1886 proto_tree_add_text(snmp_tree, tvb, offset,
1888 "Message Security Parameters Data"
1889 " (%d bytes)", secparm_length);
1895 /* PDU starts here */
1897 ret = asn1_octet_string_decode (&asn1, &cryptpdu,
1898 &cryptpdu_length, &length);
1899 if (ret != ASN1_ERR_NOERROR) {
1900 dissect_snmp_parse_error(tvb, offset, pinfo,
1901 snmp_tree, "encrypted PDU header", ret);
1902 return message_length;
1904 proto_tree_add_text(snmp_tree, tvb, offset, length,
1905 "Encrypted PDU (%d bytes)", length);
1907 if (check_col(pinfo->cinfo, COL_INFO))
1908 col_set_str(pinfo->cinfo, COL_INFO, "Encrypted PDU");
1909 return message_length;
1911 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1912 if (ret != ASN1_ERR_NOERROR) {
1913 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1915 return message_length;
1918 ret = asn1_octet_string_decode (&asn1, &cengineid,
1919 &cengineid_length, &length);
1920 if (ret != ASN1_ERR_NOERROR) {
1921 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1922 "context engine id", ret);
1923 return message_length;
1926 proto_tree_add_text(snmp_tree, tvb, offset, length,
1927 "Context Engine ID: %s",
1928 bytes_to_str(cengineid, cengineid_length));
1932 ret = asn1_octet_string_decode (&asn1, &cname,
1933 &cname_length, &length);
1934 if (ret != ASN1_ERR_NOERROR) {
1935 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1936 "context name", ret);
1937 return message_length;
1940 proto_tree_add_text(snmp_tree, tvb, offset, length,
1942 SAFE_STRING(cname, cname_length));
1948 dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
1949 "PDU for unknown version of SNMP");
1950 return message_length;
1953 start = asn1.offset;
1954 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1956 if (ret != ASN1_ERR_NOERROR) {
1957 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1959 return message_length;
1961 if (cls != ASN1_CTX || con != ASN1_CON) {
1962 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1963 "PDU type", ASN1_ERR_WRONG_TYPE);
1964 return message_length;
1966 dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
1967 return message_length;
1971 dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1972 proto_tree *tree, int proto, gint ett)
1980 char *pdu_type_string;
1990 int password_length;
1992 guchar *application;
1993 int application_length;
2000 proto_tree *smux_tree = NULL;
2001 proto_item *item = NULL;
2005 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2006 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
2009 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
2010 smux_tree = proto_item_add_subtree(item, ett);
2013 /* NOTE: we have to parse the message piece by piece, since the
2014 * capture length may be less than the message length: a 'global'
2015 * parsing is likely to fail.
2017 /* parse the SNMP header */
2018 asn1_open(&asn1, tvb, offset);
2019 start = asn1.offset;
2020 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
2022 if (ret != ASN1_ERR_NOERROR) {
2023 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2028 /* Dissect SMUX here */
2029 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
2030 pdu_type_string = val_to_str(pdu_type, smux_types,
2031 "Unknown PDU type %#x");
2032 if (check_col(pinfo->cinfo, COL_INFO))
2033 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2034 length = asn1.offset - start;
2036 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2037 offset, length, pdu_type);
2040 ret = asn1_uint32_decode (&asn1, &version, &length);
2041 if (ret != ASN1_ERR_NOERROR) {
2042 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2047 proto_tree_add_uint(smux_tree, hf_smux_version, tvb,
2048 offset, length, version);
2052 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
2053 if (ret != ASN1_ERR_NOERROR) {
2054 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2055 "registration OID", ret);
2059 oid_string = format_oid(regid, regid_length);
2060 proto_tree_add_text(smux_tree, tvb, offset, length,
2061 "Registration: %s", oid_string);
2067 ret = asn1_octet_string_decode (&asn1, &application,
2068 &application_length, &length);
2069 if (ret != ASN1_ERR_NOERROR) {
2070 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2071 "application", ret);
2075 proto_tree_add_text(smux_tree, tvb, offset, length,
2077 SAFE_STRING(application, application_length));
2079 g_free(application);
2082 ret = asn1_octet_string_decode (&asn1, &password,
2083 &password_length, &length);
2084 if (ret != ASN1_ERR_NOERROR) {
2085 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2090 proto_tree_add_text(smux_tree, tvb, offset, length,
2092 SAFE_STRING(password, password_length));
2098 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
2099 pdu_type_string = val_to_str(pdu_type, smux_types,
2100 "Unknown PDU type %#x");
2101 if (check_col(pinfo->cinfo, COL_INFO))
2102 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2103 length = asn1.offset - start;
2105 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2106 offset, length, pdu_type);
2109 ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
2110 if (ret != ASN1_ERR_NOERROR) {
2111 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2116 proto_tree_add_text(smux_tree, tvb, offset,
2117 pdu_length, "Cause: %s",
2118 val_to_str(cause, smux_close,
2119 "Unknown cause %#x"));
2121 offset += pdu_length;
2124 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
2125 pdu_type_string = val_to_str(pdu_type, smux_types,
2126 "Unknown PDU type %#x");
2127 if (check_col(pinfo->cinfo, COL_INFO))
2128 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2129 length = asn1.offset - start;
2131 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2132 offset, length, pdu_type);
2135 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
2136 if (ret != ASN1_ERR_NOERROR) {
2137 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2138 "registration subtree", ret);
2142 oid_string = format_oid(regid, regid_length);
2143 proto_tree_add_text(smux_tree, tvb, offset, length,
2144 "Registration: %s", oid_string);
2150 ret = asn1_uint32_decode (&asn1, &priority, &length);
2151 if (ret != ASN1_ERR_NOERROR) {
2152 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2157 proto_tree_add_text(smux_tree, tvb, offset, length,
2158 "Priority: %d", priority);
2162 ret = asn1_uint32_decode (&asn1, &operation, &length);
2163 if (ret != ASN1_ERR_NOERROR) {
2164 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2169 proto_tree_add_text(smux_tree, tvb, offset, length,
2171 val_to_str(operation, smux_rreq,
2172 "Unknown operation %#x"));
2177 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
2178 pdu_type_string = val_to_str(pdu_type, smux_types,
2179 "Unknown PDU type %#x");
2180 if (check_col(pinfo->cinfo, COL_INFO))
2181 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2182 length = asn1.offset - start;
2184 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2185 offset, length, pdu_type);
2188 ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
2189 if (ret != ASN1_ERR_NOERROR) {
2190 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2195 proto_tree_add_text(smux_tree, tvb, offset,
2197 val_to_str(priority, smux_prio,
2200 offset += pdu_length;
2203 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
2204 pdu_type_string = val_to_str(pdu_type, smux_types,
2205 "Unknown PDU type %#x");
2206 if (check_col(pinfo->cinfo, COL_INFO))
2207 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2208 length = asn1.offset - start;
2210 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2211 offset, length, pdu_type);
2214 ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
2215 if (ret != ASN1_ERR_NOERROR) {
2216 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2221 proto_tree_add_text(smux_tree, tvb, offset,
2223 val_to_str(commit, smux_sout,
2224 "Unknown SOUT Value: %#x"));
2226 offset += pdu_length;
2229 if (cls != ASN1_CTX || con != ASN1_CON) {
2230 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2231 "PDU type", ASN1_ERR_WRONG_TYPE);
2234 dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
2238 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2240 conversation_t *conversation;
2243 * The first SNMP packet goes to the SNMP port; the second one
2244 * may come from some *other* port, but goes back to the same
2245 * IP address and port as the ones from which the first packet
2246 * came; all subsequent packets presumably go between those two
2247 * IP addresses and ports.
2249 * If this packet went to the SNMP port, we check to see if
2250 * there's already a conversation with one address/port pair
2251 * matching the source IP address and port of this packet,
2252 * the other address matching the destination IP address of this
2253 * packet, and any destination port.
2255 * If not, we create one, with its address 1/port 1 pair being
2256 * the source address/port of this packet, its address 2 being
2257 * the destination address of this packet, and its port 2 being
2258 * wildcarded, and give it the SNMP dissector as a dissector.
2260 if (pinfo->destport == UDP_PORT_SNMP) {
2261 conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
2262 pinfo->srcport, 0, NO_PORT_B);
2263 if (conversation == NULL) {
2264 conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
2265 pinfo->srcport, 0, NO_PORT2);
2266 conversation_set_dissector(conversation, snmp_handle);
2270 dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_snmp, ett_snmp, FALSE);
2274 dissect_snmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2279 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2280 message_len = dissect_snmp_pdu(tvb, 0, pinfo, tree,
2281 proto_snmp, ett_snmp, TRUE);
2282 if (message_len == 0) {
2284 * We don't have all the data for that message,
2285 * so we need to do desegmentation;
2286 * "dissect_snmp_pdu()" has set that up.
2290 offset += message_len;
2295 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2297 dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
2303 #ifdef HAVE_SOME_SNMP
2304 gchar *tmp_mib_modules;
2305 static gboolean mibs_loaded = FALSE;
2309 * Unload the MIBs, as we'll be reloading them based on
2310 * the current preference setting.
2312 shutdown_mib(); /* unload MIBs */
2316 * Cannot check if MIBS is already set, as it could be set by Ethereal.
2318 * If we have a list of modules to load, put that list in MIBS,
2319 * otherwise clear MIBS.
2321 if (mib_modules != NULL) {
2322 tmp_mib_modules = g_strconcat("MIBS=", mib_modules, NULL);
2325 _putenv(tmp_mib_modules);
2327 putenv(tmp_mib_modules);
2340 register_mib_handlers();
2341 read_premib_configs();
2345 #endif /* HAVE_SOME_SNMP */
2349 proto_register_snmp(void)
2351 #if defined(WIN32) && defined(HAVE_SOME_SNMP)
2353 #define MIB_PATH_APPEND "snmp\\mibs"
2355 gchar *tmp_mib_modules;
2357 static hf_register_info hf[] = {
2359 { "Version", "snmp.version", FT_UINT8, BASE_DEC, VALS(versions),
2361 { &hf_snmp_community,
2362 { "Community", "snmp.community", FT_STRING, BASE_NONE, NULL,
2364 { &hf_snmp_request_id,
2365 { "Request Id", "snmp.id", FT_UINT32, BASE_HEX, NULL,
2366 0x0, "Id for this transaction", HFILL }},
2368 { "PDU type", "snmp.pdutype", FT_UINT8, BASE_DEC, VALS(pdu_types),
2371 { "Agent address", "snmp.agent", FT_IPv4, BASE_NONE, NULL,
2373 { &hf_snmp_enterprise,
2374 { "Enterprise", "snmp.enterprise", FT_STRING, BASE_NONE, NULL,
2376 { &hf_snmp_error_status,
2377 { "Error Status", "snmp.error", FT_UINT8, BASE_DEC, VALS(error_statuses),
2380 { "Object identifier", "snmp.oid", FT_STRING, BASE_NONE, NULL,
2382 { &hf_snmp_traptype,
2383 { "Trap type", "snmp.traptype", FT_UINT8, BASE_DEC, VALS(trap_types),
2385 { &hf_snmp_spectraptype,
2386 { "Specific trap type", "snmp.spectraptype", FT_UINT32, BASE_DEC, NULL,
2388 { &hf_snmp_timestamp,
2389 { "Timestamp", "snmp.timestamp", FT_UINT8, BASE_DEC, NULL,
2392 { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
2394 { &hf_snmpv3_flags_auth,
2395 { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
2396 TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
2397 { &hf_snmpv3_flags_crypt,
2398 { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
2399 TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
2400 { &hf_snmpv3_flags_report,
2401 { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
2402 TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
2404 static gint *ett[] = {
2407 &ett_parameters_qos,
2412 module_t *snmp_module;
2414 #ifdef HAVE_SOME_SNMP
2417 /* Set MIBDIRS so that the SNMP library can find its mibs. */
2418 /* XXX - Should we set MIBS or MIBFILES as well? */
2420 mib_path = g_malloc (strlen(get_datafile_dir()) + strlen(MIB_PATH_APPEND) + 20);
2421 sprintf (mib_path, "MIBDIRS=%s\\%s", get_datafile_dir(), MIB_PATH_APPEND);
2422 /* Amazingly enough, Windows does not provide setenv(). */
2423 if (getenv("MIBDIRS") == NULL)
2430 * Suppress warnings about unknown tokens - we aren't initializing
2431 * UCD SNMP in its entirety, we're just initializing the
2432 * MIB-handling part because that's all we're using, which
2433 * means that entries in the configuration file for other
2434 * pars of the library will not be handled, and we don't want
2435 * the config file reading code to whine about that.
2437 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
2438 NETSNMP_DS_LIB_NO_TOKEN_WARNINGS, TRUE);
2439 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
2440 NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 2);
2441 #endif /* HAVE_SOME_SNMP */
2442 proto_snmp = proto_register_protocol("Simple Network Management Protocol",
2444 proto_register_field_array(proto_snmp, hf, array_length(hf));
2445 proto_register_subtree_array(ett, array_length(ett));
2446 snmp_handle = create_dissector_handle(dissect_snmp, proto_snmp);
2448 /* Register configuration preferences */
2449 snmp_module = prefs_register_protocol(proto_snmp, process_prefs);
2450 prefs_register_bool_preference(snmp_module, "display_oid",
2451 "Show SNMP OID in info column",
2452 "Whether the SNMP OID should be shown in the info column",
2456 * Set the default value of "mib_modules".
2458 * If the MIBS environment variable is set, make its value
2459 * the value of "mib_modules", otherwise, set "mib_modules"
2460 * to DEF_MIB_MODULES.
2462 tmp_mib_modules = getenv("MIBS");
2463 if (tmp_mib_modules != NULL)
2464 mib_modules = tmp_mib_modules;
2465 prefs_register_string_preference(snmp_module, "mib_modules",
2466 "MIB modules to load",
2467 "List of MIB modules to load (the list is set to environment variable MIBS if the variable is not already set)",
2469 prefs_register_bool_preference(snmp_module, "desegment",
2470 "Desegment all SNMP-over-TCP messages spanning multiple TCP segments",
2471 "Whether the SNMP dissector should desegment all messages "
2472 "spanning multiple TCP segments",
2477 proto_reg_handoff_snmp(void)
2479 dissector_handle_t snmp_tcp_handle;
2481 dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
2482 dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
2483 dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
2484 dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
2485 dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
2486 dissector_add("hpext.dxsap", HPEXT_SNMP, snmp_handle);
2488 snmp_tcp_handle = create_dissector_handle(dissect_snmp_tcp, proto_snmp);
2489 dissector_add("tcp.port", TCP_PORT_SNMP, snmp_tcp_handle);
2490 dissector_add("tcp.port", TCP_PORT_SNMP_TRAP, snmp_tcp_handle);
2492 data_handle = find_dissector("data");
2495 * Process preference settings.
2497 * We can't do this in the register routine, as preferences aren't
2498 * read until all dissector register routines have been called (so
2499 * that all dissector preferences have been registered).
2505 proto_register_smux(void)
2507 static hf_register_info hf[] = {
2509 { "Version", "smux.version", FT_UINT8, BASE_DEC, NULL,
2512 { "PDU type", "smux.pdutype", FT_UINT8, BASE_DEC, VALS(smux_types),
2515 static gint *ett[] = {
2519 proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2521 proto_register_field_array(proto_smux, hf, array_length(hf));
2522 proto_register_subtree_array(ett, array_length(ett));
2526 proto_reg_handoff_smux(void)
2528 dissector_handle_t smux_handle;
2530 smux_handle = create_dissector_handle(dissect_smux, proto_smux);
2531 dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);