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.129 2004/07/09 23:17:05 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.
52 #include <epan/packet.h>
53 #include <epan/strutil.h>
54 #include <epan/conversation.h>
57 #include "packet-ipx.h"
58 #include "packet-hpext.h"
59 #include "packet-frame.h"
64 # include <net-snmp/net-snmp-config.h>
65 # include <net-snmp/mib_api.h>
66 # include <net-snmp/library/default_store.h>
67 # include <net-snmp/config_api.h>
68 #else /* HAVE_NET_SNMP */
69 # include <ucd-snmp/ucd-snmp-config.h>
70 # include <ucd-snmp/asn1.h>
71 # include <ucd-snmp/snmp_api.h>
72 # include <ucd-snmp/snmp_impl.h>
73 # include <ucd-snmp/mib.h>
74 # include <ucd-snmp/default_store.h>
75 # include <ucd-snmp/read_config.h>
76 # include <ucd-snmp/tools.h>
77 #endif /* HAVE_NET_SNMP */
79 #ifndef NETSNMP_DS_LIBRARY_ID
80 # define NETSNMP_DS_LIBRARY_ID DS_LIBRARY_ID
81 # define NETSNMP_DS_LIB_NO_TOKEN_WARNINGS DS_LIB_NO_TOKEN_WARNINGS
82 # define NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY DS_LIB_PRINT_SUFFIX_ONLY
83 # define netsnmp_ds_set_boolean ds_set_boolean
84 # define netsnmp_ds_set_int ds_set_int
88 # include <epan/filesystem.h>
92 * Define values "sprint_realloc_value()" expects.
94 # define VALTYPE_INTEGER ASN_INTEGER
95 # define VALTYPE_COUNTER ASN_COUNTER
96 # define VALTYPE_GAUGE ASN_GAUGE
97 # define VALTYPE_TIMETICKS ASN_TIMETICKS
98 # define VALTYPE_STRING ASN_OCTET_STR
99 # define VALTYPE_IPADDR ASN_IPADDRESS
100 # define VALTYPE_OPAQUE ASN_OPAQUE
101 # define VALTYPE_NSAP ASN_NSAP
102 # define VALTYPE_OBJECTID ASN_OBJECT_ID
103 # define VALTYPE_BITSTR ASN_BIT_STR
104 # define VALTYPE_COUNTER64 ASN_COUNTER64
106 #endif /* HAVE_SOME_SNMP */
110 #include "packet-snmp.h"
111 #include "format-oid.h"
113 /* Take a pointer that may be null and return a pointer that's not null
114 by turning null pointers into pointers to the above null string,
115 and, if the argument pointer wasn't null, make sure we handle
116 non-printable characters in the string by escaping them. */
117 #define SAFE_STRING(s, l) (((s) != NULL) ? format_text((s), (l)) : "")
119 static int proto_snmp = -1;
121 /* Default MIB modules to load */
122 #define DEF_MIB_MODULES "IP-MIB:IF-MIB:TCP-MIB:UDP-MIB:SNMPv2-MIB:RFC1213-MIB:UCD-SNMP-MIB"
124 static gchar *mib_modules = DEF_MIB_MODULES;
125 static gboolean display_oid = TRUE;
127 static gint ett_snmp = -1;
128 static gint ett_parameters = -1;
129 static gint ett_parameters_qos = -1;
130 static gint ett_global = -1;
131 static gint ett_flags = -1;
132 static gint ett_secur = -1;
134 static int hf_snmp_version = -1;
135 static int hf_snmp_community = -1;
136 static int hf_snmp_request_id = -1;
137 static int hf_snmp_pdutype = -1;
138 static int hf_snmp_agent = -1;
139 static int hf_snmp_enterprise = -1;
140 static int hf_snmp_error_status = -1;
141 static int hf_snmp_oid = -1;
142 static int hf_snmp_traptype = -1;
143 static int hf_snmp_spectraptype = -1;
144 static int hf_snmp_timestamp = -1;
145 static int hf_snmpv3_flags = -1;
146 static int hf_snmpv3_flags_auth = -1;
147 static int hf_snmpv3_flags_crypt = -1;
148 static int hf_snmpv3_flags_report = -1;
150 static int proto_smux = -1;
152 static gint ett_smux = -1;
154 static int hf_smux_version = -1;
155 static int hf_smux_pdutype = -1;
157 /* desegmentation of SNMP-over-TCP */
158 static gboolean snmp_desegment = TRUE;
160 static dissector_handle_t snmp_handle;
161 static dissector_handle_t data_handle;
164 #define TH_CRYPT 0x02
165 #define TH_REPORT 0x04
167 #define UDP_PORT_SNMP 161
168 #define UDP_PORT_SNMP_TRAP 162
169 #define TCP_PORT_SNMP 161
170 #define TCP_PORT_SNMP_TRAP 162
171 #define TCP_PORT_SMUX 199
173 /* Protocol version numbers */
174 #define SNMP_VERSION_1 0
175 #define SNMP_VERSION_2c 1
176 #define SNMP_VERSION_2u 2
177 #define SNMP_VERSION_3 3
179 static const value_string versions[] = {
180 { SNMP_VERSION_1, "1" },
181 { SNMP_VERSION_2c, "2C" },
182 { SNMP_VERSION_2u, "2U" },
183 { SNMP_VERSION_3, "3" },
187 /* defined in net-SNMP; include/net-snmp/library/snmp.h */
190 #undef SNMP_MSG_GETNEXT
191 #undef SNMP_MSG_RESPONSE
193 #undef SNMP_MSG_GETBULK
194 #undef SNMP_MSG_INFORM
195 #undef SNMP_MSG_TRAP2
196 #undef SNMP_MSG_REPORT
197 #undef SNMP_NOSUCHOBJECT
198 #undef SNMP_NOSUCHINSTANCE
199 #undef SNMP_ENDOFMIBVIEW
202 #define SNMP_MSG_GET 0
203 #define SNMP_MSG_GETNEXT 1
204 #define SNMP_MSG_RESPONSE 2
205 #define SNMP_MSG_SET 3
206 #define SNMP_MSG_TRAP 4
208 #define SNMP_MSG_GETBULK 5
209 #define SNMP_MSG_INFORM 6
210 #define SNMP_MSG_TRAP2 7
211 #define SNMP_MSG_REPORT 8
213 static const value_string pdu_types[] = {
214 { SNMP_MSG_GET, "GET" },
215 { SNMP_MSG_GETNEXT, "GET-NEXT" },
216 { SNMP_MSG_SET, "SET" },
217 { SNMP_MSG_RESPONSE, "RESPONSE" },
218 { SNMP_MSG_TRAP, "TRAP-V1" },
219 { SNMP_MSG_GETBULK, "GETBULK" },
220 { SNMP_MSG_INFORM, "INFORM" },
221 { SNMP_MSG_TRAP2, "TRAP-V2" },
222 { SNMP_MSG_REPORT, "REPORT" },
227 #define SMUX_MSG_OPEN 0
228 #define SMUX_MSG_CLOSE 1
229 #define SMUX_MSG_RREQ 2
230 #define SMUX_MSG_RRSP 3
231 #define SMUX_MSG_SOUT 4
233 static const value_string smux_types[] = {
234 { SMUX_MSG_OPEN, "Open" },
235 { SMUX_MSG_CLOSE, "Close" },
236 { SMUX_MSG_RREQ, "Registration Request" },
237 { SMUX_MSG_RRSP, "Registration Response" },
238 { SMUX_MSG_SOUT, "Commit Or Rollback" },
242 /* SMUX Closing causes */
243 #define SMUX_CLOSE_DOWN 0
244 #define SMUX_CLOSE_VERSION 1
245 #define SMUX_CLOSE_PACKET 2
246 #define SMUX_CLOSE_PROTOCOL 3
247 #define SMUX_CLOSE_INTERNAL 4
248 #define SMUX_CLOSE_NOAUTH 5
250 static const value_string smux_close[] = {
251 { SMUX_CLOSE_DOWN, "Going down" },
252 { SMUX_CLOSE_VERSION, "Unsupported Version" },
253 { SMUX_CLOSE_PACKET, "Packet Format Error" },
254 { SMUX_CLOSE_PROTOCOL, "Protocol Error" },
255 { SMUX_CLOSE_INTERNAL, "Internal Error" },
256 { SMUX_CLOSE_NOAUTH, "Unauthorized" },
260 /* SMUX Request codes */
261 #define SMUX_RREQ_DELETE 0
262 #define SMUX_RREQ_READONLY 1
263 #define SMUX_RREQ_READWRITE 2
265 static const value_string smux_rreq[] = {
266 { SMUX_RREQ_DELETE, "Delete" },
267 { SMUX_RREQ_READONLY, "Read Only" },
268 { SMUX_RREQ_READWRITE, "Read Write" },
272 static const value_string smux_prio[] = {
277 /* SMUX SOut codes */
278 #define SMUX_SOUT_COMMIT 0
279 #define SMUX_SOUT_ROLLBACK 1
281 static const value_string smux_sout[] = {
282 { SMUX_SOUT_COMMIT, "Commit" },
283 { SMUX_SOUT_ROLLBACK, "Rollback" },
287 /* Error status values */
288 #ifndef SNMP_ERR_NOERROR
289 #define SNMP_ERR_NOERROR 0
291 #ifndef SNMP_ERR_TOOBIG
292 #define SNMP_ERR_TOOBIG 1
294 #ifndef SNMP_ERR_NOSUCHNAME
295 #define SNMP_ERR_NOSUCHNAME 2
297 #ifndef SNMP_ERR_BADVALUE
298 #define SNMP_ERR_BADVALUE 3
300 #ifndef SNMP_ERR_READONLY
301 #define SNMP_ERR_READONLY 4
303 #ifndef SNMP_ERR_GENERR
304 #define SNMP_ERR_GENERR 5
306 #ifndef SNMP_ERR_NOACCESS
307 #define SNMP_ERR_NOACCESS 6
309 #ifndef SNMP_ERR_WRONGTYPE
310 #define SNMP_ERR_WRONGTYPE 7
312 #ifndef SNMP_ERR_WRONGLENGTH
313 #define SNMP_ERR_WRONGLENGTH 8
315 #ifndef SNMP_ERR_WRONGENCODING
316 #define SNMP_ERR_WRONGENCODING 9
318 #ifndef SNMP_ERR_WRONGVALUE
319 #define SNMP_ERR_WRONGVALUE 10
321 #ifndef SNMP_ERR_NOCREATION
322 #define SNMP_ERR_NOCREATION 11
324 #ifndef SNMP_ERR_INCONSISTENTVALUE
325 #define SNMP_ERR_INCONSISTENTVALUE 12
327 #ifndef SNMP_ERR_RESOURCEUNAVAILABLE
328 #define SNMP_ERR_RESOURCEUNAVAILABLE 13
330 #ifndef SNMP_ERR_COMMITFAILED
331 #define SNMP_ERR_COMMITFAILED 14
333 #ifndef SNMP_ERR_UNDOFAILED
334 #define SNMP_ERR_UNDOFAILED 15
336 #ifndef SNMP_ERR_AUTHORIZATIONERROR
337 #define SNMP_ERR_AUTHORIZATIONERROR 16
339 #ifndef SNMP_ERR_NOTWRITABLE
340 #define SNMP_ERR_NOTWRITABLE 17
342 #ifndef SNMP_ERR_INCONSISTENTNAME
343 #define SNMP_ERR_INCONSISTENTNAME 18
346 static const value_string error_statuses[] = {
347 { SNMP_ERR_NOERROR, "NO ERROR" },
348 { SNMP_ERR_TOOBIG, "TOOBIG" },
349 { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" },
350 { SNMP_ERR_BADVALUE, "BAD VALUE" },
351 { SNMP_ERR_READONLY, "READ ONLY" },
352 { SNMP_ERR_GENERR, "GENERIC ERROR" },
353 { SNMP_ERR_NOACCESS, "NO ACCESS" },
354 { SNMP_ERR_WRONGTYPE, "WRONG TYPE" },
355 { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" },
356 { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" },
357 { SNMP_ERR_WRONGVALUE, "WRONG VALUE" },
358 { SNMP_ERR_NOCREATION, "NO CREATION" },
359 { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" },
360 { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" },
361 { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" },
362 { SNMP_ERR_UNDOFAILED, "UNDO FAILED" },
363 { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" },
364 { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" },
365 { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" },
369 /* General SNMP V1 Traps */
371 #ifndef SNMP_TRAP_COLDSTART
372 #define SNMP_TRAP_COLDSTART 0
374 #ifndef SNMP_TRAP_WARMSTART
375 #define SNMP_TRAP_WARMSTART 1
377 #ifndef SNMP_TRAP_LINKDOWN
378 #define SNMP_TRAP_LINKDOWN 2
380 #ifndef SNMP_TRAP_LINKUP
381 #define SNMP_TRAP_LINKUP 3
383 #ifndef SNMP_TRAP_AUTHFAIL
384 #define SNMP_TRAP_AUTHFAIL 4
386 #ifndef SNMP_TRAP_EGPNEIGHBORLOSS
387 #define SNMP_TRAP_EGPNEIGHBORLOSS 5
389 #ifndef SNMP_TRAP_ENTERPRISESPECIFIC
390 #define SNMP_TRAP_ENTERPRISESPECIFIC 6
393 static const value_string trap_types[] = {
394 { SNMP_TRAP_COLDSTART, "COLD START" },
395 { SNMP_TRAP_WARMSTART, "WARM START" },
396 { SNMP_TRAP_LINKDOWN, "LINK DOWN" },
397 { SNMP_TRAP_LINKUP, "LINK UP" },
398 { SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
399 { SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
400 { SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
404 /* Security Models */
406 #define SNMP_SEC_ANY 0
407 #define SNMP_SEC_V1 1
408 #define SNMP_SEC_V2C 2
409 #define SNMP_SEC_USM 3
411 static const value_string sec_models[] = {
412 { SNMP_SEC_ANY, "Any" },
413 { SNMP_SEC_V1, "V1" },
414 { SNMP_SEC_V2C, "V2C" },
415 { SNMP_SEC_USM, "USM" },
421 #define SNMP_IPA 0 /* IP Address */
422 #define SNMP_CNT 1 /* Counter (Counter32) */
423 #define SNMP_GGE 2 /* Gauge (Gauge32) */
424 #define SNMP_TIT 3 /* TimeTicks */
425 #define SNMP_OPQ 4 /* Opaque */
426 #define SNMP_NSP 5 /* NsapAddress */
427 #define SNMP_C64 6 /* Counter64 */
428 #define SNMP_U32 7 /* Uinteger32 */
437 #define SNMP_INTEGER 1 /* l */
438 #define SNMP_OCTETSTR 2 /* c */
439 #define SNMP_DISPLAYSTR 2 /* c */
440 #define SNMP_OBJECTID 3 /* ul */
441 #define SNMP_IPADDR 4 /* uc */
442 #define SNMP_COUNTER 5 /* ul */
443 #define SNMP_GAUGE 6 /* ul */
444 #define SNMP_TIMETICKS 7 /* ul */
445 #define SNMP_OPAQUE 8 /* c */
447 /* additional SNMPv2 Types */
449 #define SNMP_UINTEGER 5 /* ul */
450 #define SNMP_BITSTR 9 /* uc */
451 #define SNMP_NSAP 10 /* uc */
452 #define SNMP_COUNTER64 11 /* ul */
453 #define SNMP_NOSUCHOBJECT 12
454 #define SNMP_NOSUCHINSTANCE 13
455 #define SNMP_ENDOFMIBVIEW 14
457 typedef struct _SNMP_CNV SNMP_CNV;
467 static SNMP_CNV SnmpCnv [] =
469 {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"},
470 {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"},
471 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"},
472 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"},
473 {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"},
474 {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */
475 {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */
476 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"},
477 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"},
479 /* SNMPv2 data types and errors */
481 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"},
482 {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"},
483 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"},
484 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"},
485 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"},
490 * NAME: g_snmp_tag_cls2syntax
491 * SYNOPSIS: gboolean g_snmp_tag_cls2syntax
497 * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name.
498 * See SnmpCnv for conversion.
499 * RETURNS: name on success, NULL on failure
503 snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
508 while (cnv->syntax != -1)
510 if (cnv->tag == tag && cnv->class == cls)
512 *syntax = cnv->syntax;
521 dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
522 proto_tree *tree, const char *field_name, int ret)
526 errstr = asn1_err_to_str(ret);
528 if (check_col(pinfo->cinfo, COL_INFO)) {
529 col_add_fstr(pinfo->cinfo, COL_INFO,
530 "ERROR: Couldn't parse %s: %s", field_name, errstr);
533 proto_tree_add_text(tree, tvb, offset, 0,
534 "ERROR: Couldn't parse %s: %s", field_name, errstr);
535 call_dissector(data_handle,
536 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
541 dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
542 proto_tree *tree, const char *message)
544 if (check_col(pinfo->cinfo, COL_INFO))
545 col_add_str(pinfo->cinfo, COL_INFO, message);
548 proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
549 call_dissector(data_handle,
550 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
555 format_oid(subid_t *oid, guint oid_length)
562 #ifdef HAVE_SOME_SNMP
564 size_t oid_string_len;
568 result_len = oid_length * 22;
570 #ifdef HAVE_SOME_SNMP
572 * Get the decoded form of the OID, and add its length to the
573 * length of the result string.
575 * XXX - check for "sprint_realloc_objid()" failure.
577 oid_string_len = 256;
578 oid_string = g_malloc(oid_string_len);
581 sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
583 result_len += strlen(oid_string) + 3;
586 result = g_malloc(result_len + 1);
588 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
590 for (i = 1; i < oid_length;i++) {
591 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
595 #ifdef HAVE_SOME_SNMP
597 * Append the decoded form of the OID.
599 sprintf(buf, " (%s)", oid_string);
606 /* returns the decoded (can be NULL) and non_decoded OID strings,
607 returned pointers shall be freed by the caller */
609 new_format_oid(subid_t *oid, guint oid_length,
610 gchar **non_decoded, gchar **decoded)
616 #ifdef HAVE_SOME_SNMP
618 size_t oid_string_len;
622 * Get the decoded form of the OID, and add its length to the
623 * length of the result string.
626 oid_string_len = 256;
627 oid_string = g_malloc(oid_string_len);
630 sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
632 *decoded = oid_string;
637 *non_decoded = g_malloc(oid_length * 22 + 1);
639 len = sprintf(buf, "%lu", (unsigned long)oid[0]);
641 for (i = 1; i < oid_length; i++) {
642 len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
647 #ifdef HAVE_SOME_SNMP
649 check_var_length(guint vb_length, guint required_length)
652 static const char badlen_fmt[] = "Length is %u, should be %u";
654 if (vb_length != required_length) {
655 /* Enough room for the largest "Length is XXX,
656 should be XXX" message - 10 digits for each
658 buf = g_malloc(sizeof badlen_fmt + 10 + 10);
659 sprintf(buf, badlen_fmt, vb_length, required_length);
662 return NULL; /* length is OK */
666 format_var(struct variable_list *variable, subid_t *variable_oid,
667 guint variable_oid_length, gushort vb_type, guint val_len)
676 /* Length has to be 4 bytes. */
677 buf = check_var_length(val_len, 4);
679 return buf; /* it's not 4 bytes */
683 /* not all counters are encoded as a full 64bit integer */
685 /* Length has to be 8 bytes. */
686 buf = check_var_length(val_len, 8);
688 return buf; /* it's not 8 bytes */
695 variable->next_variable = NULL;
696 variable->name = variable_oid;
697 variable->name_length = variable_oid_length;
701 variable->type = VALTYPE_INTEGER;
705 variable->type = VALTYPE_COUNTER;
709 variable->type = VALTYPE_GAUGE;
713 variable->type = VALTYPE_TIMETICKS;
717 variable->type = VALTYPE_STRING;
721 variable->type = VALTYPE_IPADDR;
725 variable->type = VALTYPE_OPAQUE;
729 variable->type = VALTYPE_NSAP;
733 variable->type = VALTYPE_OBJECTID;
737 variable->type = VALTYPE_BITSTR;
741 variable->type = VALTYPE_COUNTER64;
744 variable->val_len = val_len;
747 * XXX - check for "sprint_realloc_objid()" failure.
750 buf = g_malloc(buf_len);
753 sprint_realloc_value(&buf, &buf_len, &out_len, 1, variable_oid,
754 variable_oid_length, variable);
760 snmp_variable_decode(proto_tree *snmp_tree,
761 subid_t *variable_oid
762 #ifndef HAVE_SOME_SNMP
766 guint variable_oid_length
767 #ifndef HAVE_SOME_SNMP
771 ASN1_SCK *asn1, int offset, guint *lengthp)
782 gint32 vb_integer_value;
783 guint32 vb_uinteger_value;
785 guint8 *vb_octet_string;
790 gchar *vb_display_string;
792 #ifdef HAVE_SOME_SNMP
793 struct variable_list variable;
795 #else /* HAVE_SOME_SNMP */
799 #endif /* HAVE_SOME_SNMP */
801 /* parse the type of the object */
802 start = asn1->offset;
803 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
804 if (ret != ASN1_ERR_NOERROR)
807 return ASN1_ERR_LENGTH_NOT_DEFINITE;
809 /* Convert the class, constructed flag, and tag to a type. */
810 vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
811 if (vb_type_name == NULL) {
814 * Dissect the value as an opaque string of octets.
816 vb_type_name = "unsupported type";
817 vb_type = SNMP_OPAQUE;
820 /* parse the value */
824 ret = asn1_int32_value_decode(asn1, vb_length,
826 if (ret != ASN1_ERR_NOERROR)
828 length = asn1->offset - start;
830 #ifdef HAVE_SOME_SNMP
831 value = vb_integer_value;
832 variable.val.integer = &value;
833 vb_display_string = format_var(&variable,
834 variable_oid, variable_oid_length, vb_type,
836 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
838 "Value: %s", vb_display_string);
839 g_free(vb_display_string);
840 #else /* HAVE_SOME_SNMP */
841 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
843 "Value: %s: %d (%#x)", vb_type_name,
844 vb_integer_value, vb_integer_value);
845 #endif /* HAVE_SOME_SNMP */
852 ret = asn1_uint32_value_decode(asn1, vb_length,
854 if (ret != ASN1_ERR_NOERROR)
856 length = asn1->offset - start;
858 #ifdef HAVE_SOME_SNMP
859 value = vb_uinteger_value;
860 variable.val.integer = &value;
861 vb_display_string = format_var(&variable,
862 variable_oid, variable_oid_length, vb_type,
864 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
866 "Value: %s", vb_display_string);
867 g_free(vb_display_string);
868 #else /* HAVE_SOME_SNMP */
869 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
871 "Value: %s: %u (%#x)", vb_type_name,
872 vb_uinteger_value, vb_uinteger_value);
873 #endif /* HAVE_SOME_SNMP */
883 ret = asn1_string_value_decode (asn1, vb_length,
885 if (ret != ASN1_ERR_NOERROR)
887 length = asn1->offset - start;
889 #ifdef HAVE_SOME_SNMP
890 variable.val.string = vb_octet_string;
891 vb_display_string = format_var(&variable,
892 variable_oid, variable_oid_length, vb_type,
894 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
896 "Value: %s", vb_display_string);
897 g_free(vb_display_string);
898 #else /* HAVE_SOME_SNMP */
900 * If some characters are not printable, display
901 * the string as bytes.
903 for (i = 0; i < vb_length; i++) {
904 if (!(isprint(vb_octet_string[i])
905 || isspace(vb_octet_string[i])))
910 * We stopped, due to a non-printable
911 * character, before we got to the end
914 vb_display_string = g_malloc(4*vb_length);
915 buf = &vb_display_string[0];
916 len = sprintf(buf, "%03u", vb_octet_string[0]);
918 for (i = 1; i < vb_length; i++) {
919 len = sprintf(buf, ".%03u",
923 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
925 "Value: %s: %s", vb_type_name,
927 g_free(vb_display_string);
929 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
931 "Value: %s: %s", vb_type_name,
932 SAFE_STRING(vb_octet_string, vb_length));
934 #endif /* HAVE_SOME_SNMP */
936 g_free(vb_octet_string);
940 ret = asn1_null_decode (asn1, vb_length);
941 if (ret != ASN1_ERR_NOERROR)
943 length = asn1->offset - start;
945 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
946 "Value: %s", vb_type_name);
951 ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
953 if (ret != ASN1_ERR_NOERROR)
955 length = asn1->offset - start;
957 #ifdef HAVE_SOME_SNMP
958 variable.val.objid = vb_oid;
959 vb_display_string = format_var(&variable,
960 variable_oid, variable_oid_length, vb_type,
961 vb_oid_length * sizeof (subid_t));
962 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
964 "Value: %s", vb_display_string);
965 g_free(vb_display_string);
966 #else /* HAVE_SOME_SNMP */
967 vb_display_string = format_oid(vb_oid, vb_oid_length);
968 proto_tree_add_text(snmp_tree, asn1->tvb, offset,
970 "Value: %s: %s", vb_type_name, vb_display_string);
971 g_free(vb_display_string);
972 #endif /* HAVE_SOME_SNMP */
977 case SNMP_NOSUCHOBJECT:
978 length = asn1->offset - start;
980 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
981 "Value: %s: no such object", vb_type_name);
985 case SNMP_NOSUCHINSTANCE:
986 length = asn1->offset - start;
988 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
989 "Value: %s: no such instance", vb_type_name);
993 case SNMP_ENDOFMIBVIEW:
994 length = asn1->offset - start;
996 proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
997 "Value: %s: end of mib view", vb_type_name);
1002 g_assert_not_reached();
1003 return ASN1_ERR_WRONG_TYPE;
1006 return ASN1_ERR_NOERROR;
1010 dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1011 proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
1015 guint sequence_length;
1019 guint32 error_status;
1021 guint32 error_index;
1023 char *pdu_type_string;
1025 subid_t *enterprise;
1026 guint enterprise_length;
1028 guint32 agent_ipaddr;
1030 guint8 *agent_address;
1031 guint agent_address_length;
1035 guint32 specific_type;
1038 guint timestamp_length;
1042 guint variable_bindings_length;
1045 guint variable_length;
1046 subid_t *variable_oid;
1047 guint variable_oid_length;
1050 guint cls, con, tag;
1052 pdu_type_string = val_to_str(pdu_type, pdu_types,
1053 "Unknown PDU type %#x");
1054 if (check_col(pinfo->cinfo, COL_INFO))
1055 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
1056 length = asn1.offset - start;
1058 proto_tree_add_uint(tree, hf_snmp_pdutype, tvb, offset, length,
1063 /* get the fields in the PDU preceeding the variable-bindings sequence */
1067 case SNMP_MSG_GETNEXT:
1068 case SNMP_MSG_RESPONSE:
1070 case SNMP_MSG_GETBULK:
1071 case SNMP_MSG_INFORM:
1072 case SNMP_MSG_TRAP2:
1073 case SNMP_MSG_REPORT:
1075 ret = asn1_uint32_decode (&asn1, &request_id, &length);
1076 if (ret != ASN1_ERR_NOERROR) {
1077 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1082 proto_tree_add_uint(tree, hf_snmp_request_id,
1083 tvb, offset, length, request_id);
1087 /* error status, or getbulk non-repeaters */
1088 ret = asn1_uint32_decode (&asn1, &error_status, &length);
1089 if (ret != ASN1_ERR_NOERROR) {
1090 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1091 (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
1097 if (pdu_type == SNMP_MSG_GETBULK) {
1098 proto_tree_add_text(tree, tvb, offset,
1099 length, "Non-repeaters: %u", error_status);
1101 proto_tree_add_uint(tree,
1102 hf_snmp_error_status,
1104 length, error_status);
1109 /* error index, or getbulk max-repetitions */
1110 ret = asn1_uint32_decode (&asn1, &error_index, &length);
1111 if (ret != ASN1_ERR_NOERROR) {
1112 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1113 (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
1119 if (pdu_type == SNMP_MSG_GETBULK) {
1120 proto_tree_add_text(tree, tvb, offset,
1121 length, "Max repetitions: %u", error_index);
1123 proto_tree_add_text(tree, tvb, offset,
1124 length, "Error Index: %u", error_index);
1132 ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
1134 if (ret != ASN1_ERR_NOERROR) {
1135 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1136 "enterprise OID", ret);
1140 oid_string = format_oid(enterprise, enterprise_length);
1141 proto_tree_add_string(tree, hf_snmp_enterprise, tvb,
1142 offset, length, oid_string);
1149 start = asn1.offset;
1150 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1151 &def, &agent_address_length);
1152 if (ret != ASN1_ERR_NOERROR) {
1153 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1154 "agent address", ret);
1157 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
1158 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
1159 /* GXSNMP 0.0.15 says the latter is "needed for
1161 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1162 "agent_address", ASN1_ERR_WRONG_TYPE);
1165 if (agent_address_length != 4) {
1166 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1167 "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
1170 ret = asn1_string_value_decode (&asn1,
1171 agent_address_length, &agent_address);
1172 if (ret != ASN1_ERR_NOERROR) {
1173 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1174 "agent address", ret);
1177 length = asn1.offset - start;
1179 if (agent_address_length != 4) {
1180 proto_tree_add_text(tree, tvb, offset,
1182 "Agent address: <length is %u, not 4>",
1183 agent_address_length);
1185 memcpy((guint8 *)&agent_ipaddr, agent_address,
1186 agent_address_length);
1187 proto_tree_add_ipv4(tree, hf_snmp_agent, tvb,
1188 offset, length, agent_ipaddr);
1191 g_free(agent_address);
1194 /* generic trap type */
1195 ret = asn1_uint32_decode (&asn1, &trap_type, &length);
1196 if (ret != ASN1_ERR_NOERROR) {
1197 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1198 "generic trap type", ret);
1202 proto_tree_add_uint(tree, hf_snmp_traptype, tvb,
1203 offset, length, trap_type);
1207 /* specific trap type */
1208 ret = asn1_uint32_decode (&asn1, &specific_type, &length);
1209 if (ret != ASN1_ERR_NOERROR) {
1210 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1211 "specific trap type", ret);
1215 proto_tree_add_uint(tree, hf_snmp_spectraptype, tvb,
1216 offset, length, specific_type);
1221 start = asn1.offset;
1222 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1223 &def, ×tamp_length);
1224 if (ret != ASN1_ERR_NOERROR) {
1225 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1229 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
1230 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
1231 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1232 "timestamp", ASN1_ERR_WRONG_TYPE);
1235 ret = asn1_uint32_value_decode(&asn1, timestamp_length,
1237 if (ret != ASN1_ERR_NOERROR) {
1238 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1242 length = asn1.offset - start;
1244 proto_tree_add_uint(tree, hf_snmp_timestamp, tvb,
1245 offset, length, timestamp);
1251 /* variable bindings */
1252 /* get header for variable-bindings sequence */
1253 ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
1254 if (ret != ASN1_ERR_NOERROR) {
1255 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1256 "variable bindings header", ret);
1261 /* loop on variable bindings */
1263 while (variable_bindings_length > 0) {
1265 sequence_length = 0;
1268 ret = asn1_sequence_decode(&asn1, &variable_length, &length);
1269 if (ret != ASN1_ERR_NOERROR) {
1270 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1271 "variable binding header", ret);
1274 sequence_length += length;
1276 /* parse object identifier */
1277 ret = asn1_oid_decode (&asn1, &variable_oid,
1278 &variable_oid_length, &length);
1279 if (ret != ASN1_ERR_NOERROR) {
1280 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1281 "variable binding OID", ret);
1284 sequence_length += length;
1286 if (display_oid || tree) {
1289 gchar *non_decoded_oid;
1291 new_format_oid(variable_oid, variable_oid_length,
1292 &non_decoded_oid, &decoded_oid);
1294 if (display_oid && check_col(pinfo->cinfo, COL_INFO)) {
1295 col_append_fstr(pinfo->cinfo, COL_INFO,
1297 (decoded_oid == NULL) ? non_decoded_oid :
1303 proto_tree_add_string_format(tree, hf_snmp_oid,
1307 "Object identifier %d: %s (%s)",
1311 /* add also the non decoded oid string */
1312 proto_tree_add_string_hidden(tree, hf_snmp_oid,
1317 proto_tree_add_string_format(tree, hf_snmp_oid,
1321 "Object identifier %d: %s",
1327 if (decoded_oid) g_free(decoded_oid);
1328 g_free(non_decoded_oid);
1332 offset += sequence_length;
1333 variable_bindings_length -= sequence_length;
1336 * Register a cleanup function in case one of our
1337 * tvbuff accesses throws an exception. We need
1338 * to clean up variable_oid.
1340 CLEANUP_PUSH(g_free, variable_oid);
1342 /* Parse the variable's value */
1343 ret = snmp_variable_decode(tree, variable_oid,
1344 variable_oid_length, &asn1, offset, &length);
1347 * We're done with variable_oid, so we can call the cleanup
1348 * handler to free* it, and then pop the cleanup handler.
1350 CLEANUP_CALL_AND_POP;
1352 if (ret != ASN1_ERR_NOERROR) {
1353 dissect_snmp_parse_error(tvb, offset, pinfo, tree,
1358 variable_bindings_length -= length;
1362 static const value_string qos_vals[] = {
1363 { 0x0, "No authentication or privacy" },
1364 { 0x1, "Authentication, no privacy" },
1365 { 0x2, "Authentication and privacy" },
1366 { 0x3, "Authentication and privacy" },
1371 dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
1372 guchar *parameters, int parameters_length)
1375 proto_tree *parameters_tree;
1376 proto_tree *qos_tree;
1381 item = proto_tree_add_text(tree, tvb, offset, length,
1383 parameters_tree = proto_item_add_subtree(item, ett_parameters);
1384 offset += length - parameters_length;
1386 if (parameters_length < 1)
1388 model = *parameters;
1389 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1390 "model: %u", model);
1393 parameters_length -= 1;
1395 /* Unknown model. */
1396 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length, "parameters: %s",
1397 bytes_to_str(parameters, parameters_length));
1401 if (parameters_length < 1)
1404 item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
1406 qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
1407 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1408 decode_boolean_bitfield(qos, 0x04,
1409 8, "Generation of report PDU allowed",
1410 "Generation of report PDU not allowed"));
1411 proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
1412 decode_enumerated_bitfield(qos, 0x03,
1413 8, qos_vals, "%s"));
1416 parameters_length -= 1;
1418 if (parameters_length < 12)
1420 proto_tree_add_text(parameters_tree, tvb, offset, 12,
1421 "agentID: %s", bytes_to_str(parameters, 12));
1424 parameters_length -= 12;
1426 if (parameters_length < 4)
1428 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1429 "agentBoots: %u", pntohl(parameters));
1432 parameters_length -= 4;
1434 if (parameters_length < 4)
1436 proto_tree_add_text(parameters_tree, tvb, offset, 4,
1437 "agentTime: %u", pntohl(parameters));
1440 parameters_length -= 4;
1442 if (parameters_length < 2)
1444 proto_tree_add_text(parameters_tree, tvb, offset, 2,
1445 "maxSize: %u", pntohs(parameters));
1448 parameters_length -= 2;
1450 if (parameters_length < 1)
1453 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1454 "userLen: %u", len);
1457 parameters_length -= 1;
1459 if (parameters_length < len)
1461 proto_tree_add_text(parameters_tree, tvb, offset, len,
1462 "userName: %.*s", len, parameters);
1465 parameters_length -= len;
1467 if (parameters_length < 1)
1470 proto_tree_add_text(parameters_tree, tvb, offset, 1,
1471 "authLen: %u", len);
1474 parameters_length -= 1;
1476 if (parameters_length < len)
1478 proto_tree_add_text(parameters_tree, tvb, offset, len,
1479 "authDigest: %s", bytes_to_str(parameters, len));
1482 parameters_length -= len;
1484 if (parameters_length < 1)
1486 proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
1487 "contextSelector: %s", bytes_to_str(parameters, parameters_length));
1491 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1492 proto_tree *tree, int proto, gint ett, gboolean is_tcp)
1494 guint length_remaining;
1500 guint message_length;
1501 guint global_length;
1507 guint32 engineboots;
1521 guint msgflags_length;
1522 guint community_length;
1523 guint secparm_length;
1524 guint cengineid_length;
1526 guint cryptpdu_length;
1527 guint aengineid_length;
1528 guint username_length;
1529 guint authpar_length;
1530 guint privpar_length;
1535 proto_tree *snmp_tree = NULL;
1536 proto_tree *global_tree = NULL;
1537 proto_tree *flags_tree = NULL;
1538 proto_tree *secur_tree = NULL;
1539 proto_item *item = NULL;
1541 guint cls, con, tag;
1544 * This will throw an exception if we don't have any data left.
1545 * That's what we want. (See "tcp_dissect_pdus()", which is
1546 * similar, but doesn't have to deal with ASN.1.
1547 * XXX - can we make "tcp_dissect_pdus()" provide enough
1548 * information to the "get_pdu_len" routine so that we could
1549 * have that routine deal with ASN.1, and just use
1550 * "tcp_dissect_pdus()"?)
1552 length_remaining = tvb_ensure_length_remaining(tvb, offset);
1554 /* NOTE: we have to parse the message piece by piece, since the
1555 * capture length may be less than the message length: a 'global'
1556 * parsing is likely to fail.
1560 * If this is SNMP-over-TCP, we might have to do reassembly
1561 * in order to read the "Sequence Of" header.
1563 if (is_tcp && snmp_desegment && pinfo->can_desegment) {
1565 * This is TCP, and we should, and can, do reassembly.
1567 * Is the "Sequence Of" header split across segment
1568 * boundaries? We requre at least 6 bytes for the
1569 * header, which allows for a 4-byte length (ASN.1
1572 if (length_remaining < 6) {
1573 pinfo->desegment_offset = offset;
1574 pinfo->desegment_len = 6 - length_remaining;
1577 * Return 0, which means "I didn't dissect anything
1578 * because I don't have enough data - we need
1586 * OK, try to read the "Sequence Of" header; this gets the total
1587 * length of the SNMP message.
1589 asn1_open(&asn1, tvb, offset);
1590 ret = asn1_sequence_decode(&asn1, &message_length, &length);
1591 if (ret != ASN1_ERR_NOERROR) {
1593 item = proto_tree_add_item(tree, proto, tvb, offset,
1595 snmp_tree = proto_item_add_subtree(item, ett);
1597 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1598 "message header", ret);
1601 * Return the length remaining in the tvbuff, so
1602 * if this is SNMP-over-TCP, our caller thinks there's
1603 * nothing left to dissect.
1605 return length_remaining;
1609 * Add the length of the "Sequence Of" header to the message
1612 message_length += length;
1613 if (message_length < length) {
1615 * The message length was probably so large that the
1616 * total length overflowed.
1618 * Report this as an error.
1620 show_reported_bounds_error(tvb, pinfo, tree);
1623 * Return the length remaining in the tvbuff, so
1624 * if this is SNMP-over-TCP, our caller thinks there's
1625 * nothing left to dissect.
1627 return length_remaining;
1631 * If this is SNMP-over-TCP, we might have to do reassembly
1632 * to get all of this message.
1634 if (is_tcp && snmp_desegment && pinfo->can_desegment) {
1636 * Yes - is the message split across segment boundaries?
1638 if (length_remaining < message_length) {
1640 * Yes. Tell the TCP dissector where the data
1641 * for this message starts in the data it handed
1642 * us, and how many more bytes we need, and
1645 pinfo->desegment_offset = offset;
1646 pinfo->desegment_len =
1647 message_length - length_remaining;
1650 * Return 0, which means "I didn't dissect anything
1651 * because I don't have enough data - we need
1658 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1659 col_set_str(pinfo->cinfo, COL_PROTOCOL,
1660 proto_get_protocol_short_name(find_protocol_by_id(proto)));
1664 item = proto_tree_add_item(tree, proto, tvb, offset,
1665 message_length, FALSE);
1666 snmp_tree = proto_item_add_subtree(item, ett);
1670 ret = asn1_uint32_decode (&asn1, &version, &length);
1671 if (ret != ASN1_ERR_NOERROR) {
1672 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1673 "version number", ret);
1674 return message_length;
1677 proto_tree_add_uint(snmp_tree, hf_snmp_version, tvb, offset,
1684 case SNMP_VERSION_1:
1685 case SNMP_VERSION_2c:
1686 ret = asn1_octet_string_decode (&asn1, &community,
1687 &community_length, &length);
1688 if (ret != ASN1_ERR_NOERROR) {
1689 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1691 return message_length;
1694 commustr = g_malloc(community_length+1);
1695 memcpy(commustr, community, community_length);
1696 commustr[community_length] = '\0';
1698 proto_tree_add_string(snmp_tree, hf_snmp_community,
1699 tvb, offset, length, commustr);
1705 case SNMP_VERSION_2u:
1706 ret = asn1_octet_string_decode (&asn1, &community,
1707 &community_length, &length);
1708 if (ret != ASN1_ERR_NOERROR) {
1709 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1710 "community (2u)", ret);
1711 return message_length;
1714 dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
1715 community, community_length);
1720 case SNMP_VERSION_3:
1721 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1722 if (ret != ASN1_ERR_NOERROR) {
1723 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1724 "message global header", ret);
1725 return message_length;
1728 item = proto_tree_add_text(snmp_tree, tvb, offset,
1729 global_length + length, "Message Global Header");
1730 global_tree = proto_item_add_subtree(item, ett_global);
1731 proto_tree_add_text(global_tree, tvb, offset,
1733 "Message Global Header Length: %d", global_length);
1736 ret = asn1_uint32_decode (&asn1, &msgid, &length);
1737 if (ret != ASN1_ERR_NOERROR) {
1738 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1740 return message_length;
1743 proto_tree_add_text(global_tree, tvb, offset,
1744 length, "Message ID: %d", msgid);
1747 ret = asn1_uint32_decode (&asn1, &msgmax, &length);
1748 if (ret != ASN1_ERR_NOERROR) {
1749 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1750 "message max size", ret);
1751 return message_length;
1754 proto_tree_add_text(global_tree, tvb, offset,
1755 length, "Message Max Size: %d", msgmax);
1758 ret = asn1_octet_string_decode (&asn1, &msgflags,
1759 &msgflags_length, &length);
1760 if (ret != ASN1_ERR_NOERROR) {
1761 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1762 "message flags", ret);
1763 return message_length;
1765 if (msgflags_length != 1) {
1766 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1767 "message flags wrong length", ret);
1769 return message_length;
1772 item = proto_tree_add_uint_format(global_tree,
1773 hf_snmpv3_flags, tvb, offset, length,
1774 msgflags[0], "Flags: 0x%02x", msgflags[0]);
1775 flags_tree = proto_item_add_subtree(item, ett_flags);
1776 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
1777 tvb, offset, length, msgflags[0]);
1778 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
1779 tvb, offset, length, msgflags[0]);
1780 proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
1781 tvb, offset, length, msgflags[0]);
1783 encrypted = msgflags[0] & TH_CRYPT;
1786 ret = asn1_uint32_decode (&asn1, &msgsec, &length);
1787 if (ret != ASN1_ERR_NOERROR) {
1788 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1789 "message security model", ret);
1790 return message_length;
1793 proto_tree_add_text(global_tree, tvb, offset,
1794 length, "Message Security Model: %s",
1795 val_to_str(msgsec, sec_models,
1796 "Unknown model %#x"));
1801 start = asn1.offset;
1802 ret = asn1_header_decode (&asn1, &cls, &con, &tag,
1803 &def, &secparm_length);
1804 length = asn1.offset - start;
1805 if (cls != ASN1_UNI && con != ASN1_PRI &&
1807 dissect_snmp_parse_error(tvb, offset, pinfo,
1808 snmp_tree, "Message Security Parameters",
1809 ASN1_ERR_WRONG_TYPE);
1810 return message_length;
1813 item = proto_tree_add_text(snmp_tree, tvb,
1814 offset, secparm_length + length,
1815 "Message Security Parameters");
1816 secur_tree = proto_item_add_subtree(item,
1818 proto_tree_add_text(secur_tree, tvb, offset,
1820 "Message Security Parameters Length: %d",
1824 ret = asn1_sequence_decode(&asn1, &secparm_length,
1826 if (ret != ASN1_ERR_NOERROR) {
1827 dissect_snmp_parse_error(tvb, offset, pinfo,
1828 snmp_tree, "USM sequence header", ret);
1829 return message_length;
1832 ret = asn1_octet_string_decode (&asn1, &aengineid,
1833 &aengineid_length, &length);
1834 if (ret != ASN1_ERR_NOERROR) {
1835 dissect_snmp_parse_error(tvb, offset, pinfo,
1836 snmp_tree, "authoritative engine id", ret);
1837 return message_length;
1840 proto_tree_add_text(secur_tree, tvb, offset,
1841 length, "Authoritative Engine ID: %s",
1842 bytes_to_str(aengineid, aengineid_length));
1846 ret = asn1_uint32_decode (&asn1, &engineboots, &length);
1847 if (ret != ASN1_ERR_NOERROR) {
1848 dissect_snmp_parse_error(tvb, offset, pinfo,
1849 snmp_tree, "engine boots", ret);
1850 return message_length;
1853 proto_tree_add_text(secur_tree, tvb,
1854 offset, length, "Engine Boots: %d",
1858 ret = asn1_uint32_decode (&asn1, &enginetime, &length);
1859 if (ret != ASN1_ERR_NOERROR) {
1860 dissect_snmp_parse_error(tvb, offset, pinfo,
1861 snmp_tree, "engine time", ret);
1862 return message_length;
1865 proto_tree_add_text(secur_tree, tvb,
1866 offset, length, "Engine Time: %d",
1870 ret = asn1_octet_string_decode (&asn1, &username,
1871 &username_length, &length);
1872 if (ret != ASN1_ERR_NOERROR) {
1873 dissect_snmp_parse_error(tvb, offset, pinfo,
1874 snmp_tree, "user name", ret);
1875 return message_length;
1878 proto_tree_add_text(secur_tree, tvb, offset,
1879 length, "User Name: %s",
1880 SAFE_STRING(username, username_length));
1884 ret = asn1_octet_string_decode (&asn1, &authpar,
1885 &authpar_length, &length);
1886 if (ret != ASN1_ERR_NOERROR) {
1887 dissect_snmp_parse_error(tvb, offset, pinfo,
1888 snmp_tree, "authentication parameter", ret);
1889 return message_length;
1892 proto_tree_add_text(secur_tree, tvb, offset,
1893 length, "Authentication Parameter: %s",
1894 bytes_to_str(authpar, authpar_length));
1898 ret = asn1_octet_string_decode (&asn1, &privpar,
1899 &privpar_length, &length);
1900 if (ret != ASN1_ERR_NOERROR) {
1901 dissect_snmp_parse_error(tvb, offset, pinfo,
1902 snmp_tree, "privacy parameter", ret);
1903 return message_length;
1906 proto_tree_add_text(secur_tree, tvb, offset,
1907 length, "Privacy Parameter: %s",
1908 bytes_to_str(privpar, privpar_length));
1914 ret = asn1_octet_string_decode (&asn1,
1915 &secparm, &secparm_length, &length);
1916 if (ret != ASN1_ERR_NOERROR) {
1917 dissect_snmp_parse_error(tvb, offset, pinfo,
1918 snmp_tree, "Message Security Parameters",
1920 return message_length;
1923 proto_tree_add_text(snmp_tree, tvb, offset,
1925 "Message Security Parameters Data"
1926 " (%d bytes)", secparm_length);
1932 /* PDU starts here */
1934 ret = asn1_octet_string_decode (&asn1, &cryptpdu,
1935 &cryptpdu_length, &length);
1936 if (ret != ASN1_ERR_NOERROR) {
1937 dissect_snmp_parse_error(tvb, offset, pinfo,
1938 snmp_tree, "encrypted PDU header", ret);
1939 return message_length;
1941 proto_tree_add_text(snmp_tree, tvb, offset, length,
1942 "Encrypted PDU (%d bytes)", length);
1944 if (check_col(pinfo->cinfo, COL_INFO))
1945 col_set_str(pinfo->cinfo, COL_INFO, "Encrypted PDU");
1946 return message_length;
1948 ret = asn1_sequence_decode(&asn1, &global_length, &length);
1949 if (ret != ASN1_ERR_NOERROR) {
1950 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1952 return message_length;
1955 ret = asn1_octet_string_decode (&asn1, &cengineid,
1956 &cengineid_length, &length);
1957 if (ret != ASN1_ERR_NOERROR) {
1958 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1959 "context engine id", ret);
1960 return message_length;
1963 proto_tree_add_text(snmp_tree, tvb, offset, length,
1964 "Context Engine ID: %s",
1965 bytes_to_str(cengineid, cengineid_length));
1969 ret = asn1_octet_string_decode (&asn1, &cname,
1970 &cname_length, &length);
1971 if (ret != ASN1_ERR_NOERROR) {
1972 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1973 "context name", ret);
1974 return message_length;
1977 proto_tree_add_text(snmp_tree, tvb, offset, length,
1979 SAFE_STRING(cname, cname_length));
1985 dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
1986 "PDU for unknown version of SNMP");
1987 return message_length;
1990 start = asn1.offset;
1991 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
1993 if (ret != ASN1_ERR_NOERROR) {
1994 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
1996 return message_length;
1998 if (cls != ASN1_CTX || con != ASN1_CON) {
1999 dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
2000 "PDU type", ASN1_ERR_WRONG_TYPE);
2001 return message_length;
2003 dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
2004 return message_length;
2008 dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
2009 proto_tree *tree, int proto, gint ett)
2017 char *pdu_type_string;
2027 guint password_length;
2029 guchar *application;
2030 guint application_length;
2037 proto_tree *smux_tree = NULL;
2038 proto_item *item = NULL;
2042 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2043 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
2046 item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
2047 smux_tree = proto_item_add_subtree(item, ett);
2050 /* NOTE: we have to parse the message piece by piece, since the
2051 * capture length may be less than the message length: a 'global'
2052 * parsing is likely to fail.
2054 /* parse the SNMP header */
2055 asn1_open(&asn1, tvb, offset);
2056 start = asn1.offset;
2057 ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
2059 if (ret != ASN1_ERR_NOERROR) {
2060 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2065 /* Dissect SMUX here */
2066 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
2067 pdu_type_string = val_to_str(pdu_type, smux_types,
2068 "Unknown PDU type %#x");
2069 if (check_col(pinfo->cinfo, COL_INFO))
2070 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2071 length = asn1.offset - start;
2073 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2074 offset, length, pdu_type);
2077 ret = asn1_uint32_decode (&asn1, &version, &length);
2078 if (ret != ASN1_ERR_NOERROR) {
2079 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2084 proto_tree_add_uint(smux_tree, hf_smux_version, tvb,
2085 offset, length, version);
2089 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
2090 if (ret != ASN1_ERR_NOERROR) {
2091 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2092 "registration OID", ret);
2096 oid_string = format_oid(regid, regid_length);
2097 proto_tree_add_text(smux_tree, tvb, offset, length,
2098 "Registration: %s", oid_string);
2104 ret = asn1_octet_string_decode (&asn1, &application,
2105 &application_length, &length);
2106 if (ret != ASN1_ERR_NOERROR) {
2107 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2108 "application", ret);
2112 proto_tree_add_text(smux_tree, tvb, offset, length,
2114 SAFE_STRING(application, application_length));
2116 g_free(application);
2119 ret = asn1_octet_string_decode (&asn1, &password,
2120 &password_length, &length);
2121 if (ret != ASN1_ERR_NOERROR) {
2122 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2127 proto_tree_add_text(smux_tree, tvb, offset, length,
2129 SAFE_STRING(password, password_length));
2135 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
2136 pdu_type_string = val_to_str(pdu_type, smux_types,
2137 "Unknown PDU type %#x");
2138 if (check_col(pinfo->cinfo, COL_INFO))
2139 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2140 length = asn1.offset - start;
2142 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2143 offset, length, pdu_type);
2146 ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
2147 if (ret != ASN1_ERR_NOERROR) {
2148 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2153 proto_tree_add_text(smux_tree, tvb, offset,
2154 pdu_length, "Cause: %s",
2155 val_to_str(cause, smux_close,
2156 "Unknown cause %#x"));
2158 offset += pdu_length;
2161 if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
2162 pdu_type_string = val_to_str(pdu_type, smux_types,
2163 "Unknown PDU type %#x");
2164 if (check_col(pinfo->cinfo, COL_INFO))
2165 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2166 length = asn1.offset - start;
2168 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2169 offset, length, pdu_type);
2172 ret = asn1_oid_decode (&asn1, ®id, ®id_length, &length);
2173 if (ret != ASN1_ERR_NOERROR) {
2174 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2175 "registration subtree", ret);
2179 oid_string = format_oid(regid, regid_length);
2180 proto_tree_add_text(smux_tree, tvb, offset, length,
2181 "Registration: %s", oid_string);
2187 ret = asn1_uint32_decode (&asn1, &priority, &length);
2188 if (ret != ASN1_ERR_NOERROR) {
2189 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2194 proto_tree_add_text(smux_tree, tvb, offset, length,
2195 "Priority: %d", priority);
2199 ret = asn1_uint32_decode (&asn1, &operation, &length);
2200 if (ret != ASN1_ERR_NOERROR) {
2201 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2206 proto_tree_add_text(smux_tree, tvb, offset, length,
2208 val_to_str(operation, smux_rreq,
2209 "Unknown operation %#x"));
2214 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
2215 pdu_type_string = val_to_str(pdu_type, smux_types,
2216 "Unknown PDU type %#x");
2217 if (check_col(pinfo->cinfo, COL_INFO))
2218 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2219 length = asn1.offset - start;
2221 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2222 offset, length, pdu_type);
2225 ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
2226 if (ret != ASN1_ERR_NOERROR) {
2227 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2232 proto_tree_add_text(smux_tree, tvb, offset,
2234 val_to_str(priority, smux_prio,
2237 offset += pdu_length;
2240 if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
2241 pdu_type_string = val_to_str(pdu_type, smux_types,
2242 "Unknown PDU type %#x");
2243 if (check_col(pinfo->cinfo, COL_INFO))
2244 col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
2245 length = asn1.offset - start;
2247 proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
2248 offset, length, pdu_type);
2251 ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
2252 if (ret != ASN1_ERR_NOERROR) {
2253 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2258 proto_tree_add_text(smux_tree, tvb, offset,
2260 val_to_str(commit, smux_sout,
2261 "Unknown SOUT Value: %#x"));
2263 offset += pdu_length;
2266 if (cls != ASN1_CTX || con != ASN1_CON) {
2267 dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
2268 "PDU type", ASN1_ERR_WRONG_TYPE);
2271 dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
2275 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2277 conversation_t *conversation;
2280 * The first SNMP packet goes to the SNMP port; the second one
2281 * may come from some *other* port, but goes back to the same
2282 * IP address and port as the ones from which the first packet
2283 * came; all subsequent packets presumably go between those two
2284 * IP addresses and ports.
2286 * If this packet went to the SNMP port, we check to see if
2287 * there's already a conversation with one address/port pair
2288 * matching the source IP address and port of this packet,
2289 * the other address matching the destination IP address of this
2290 * packet, and any destination port.
2292 * If not, we create one, with its address 1/port 1 pair being
2293 * the source address/port of this packet, its address 2 being
2294 * the destination address of this packet, and its port 2 being
2295 * wildcarded, and give it the SNMP dissector as a dissector.
2297 if (pinfo->destport == UDP_PORT_SNMP) {
2298 conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
2299 pinfo->srcport, 0, NO_PORT_B);
2300 if (conversation == NULL) {
2301 conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
2302 pinfo->srcport, 0, NO_PORT2);
2303 conversation_set_dissector(conversation, snmp_handle);
2307 dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_snmp, ett_snmp, FALSE);
2311 dissect_snmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2316 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2317 message_len = dissect_snmp_pdu(tvb, 0, pinfo, tree,
2318 proto_snmp, ett_snmp, TRUE);
2319 if (message_len == 0) {
2321 * We don't have all the data for that message,
2322 * so we need to do desegmentation;
2323 * "dissect_snmp_pdu()" has set that up.
2327 offset += message_len;
2332 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2334 dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
2340 #ifdef HAVE_SOME_SNMP
2341 gchar *tmp_mib_modules;
2342 static gboolean mibs_loaded = FALSE;
2346 * Unload the MIBs, as we'll be reloading them based on
2347 * the current preference setting.
2349 shutdown_mib(); /* unload MIBs */
2353 * Cannot check if MIBS is already set, as it could be set by Ethereal.
2355 * If we have a list of modules to load, put that list in MIBS,
2356 * otherwise clear MIBS.
2358 if (mib_modules != NULL) {
2359 tmp_mib_modules = g_strconcat("MIBS=", mib_modules, NULL);
2362 _putenv(tmp_mib_modules);
2364 putenv(tmp_mib_modules);
2377 register_mib_handlers();
2378 read_premib_configs();
2382 #endif /* HAVE_SOME_SNMP */
2386 proto_register_snmp(void)
2388 #if defined(WIN32) && defined(HAVE_SOME_SNMP)
2390 #define MIB_PATH_APPEND "snmp\\mibs"
2392 gchar *tmp_mib_modules;
2394 static hf_register_info hf[] = {
2396 { "Version", "snmp.version", FT_UINT8, BASE_DEC, VALS(versions),
2398 { &hf_snmp_community,
2399 { "Community", "snmp.community", FT_STRING, BASE_NONE, NULL,
2401 { &hf_snmp_request_id,
2402 { "Request Id", "snmp.id", FT_UINT32, BASE_HEX, NULL,
2403 0x0, "Id for this transaction", HFILL }},
2405 { "PDU type", "snmp.pdutype", FT_UINT8, BASE_DEC, VALS(pdu_types),
2408 { "Agent address", "snmp.agent", FT_IPv4, BASE_NONE, NULL,
2410 { &hf_snmp_enterprise,
2411 { "Enterprise", "snmp.enterprise", FT_STRING, BASE_NONE, NULL,
2413 { &hf_snmp_error_status,
2414 { "Error Status", "snmp.error", FT_UINT8, BASE_DEC, VALS(error_statuses),
2417 { "Object identifier", "snmp.oid", FT_STRING, BASE_NONE, NULL,
2419 { &hf_snmp_traptype,
2420 { "Trap type", "snmp.traptype", FT_UINT8, BASE_DEC, VALS(trap_types),
2422 { &hf_snmp_spectraptype,
2423 { "Specific trap type", "snmp.spectraptype", FT_UINT32, BASE_DEC, NULL,
2425 { &hf_snmp_timestamp,
2426 { "Timestamp", "snmp.timestamp", FT_UINT8, BASE_DEC, NULL,
2429 { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
2431 { &hf_snmpv3_flags_auth,
2432 { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
2433 TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
2434 { &hf_snmpv3_flags_crypt,
2435 { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
2436 TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
2437 { &hf_snmpv3_flags_report,
2438 { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
2439 TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
2441 static gint *ett[] = {
2444 &ett_parameters_qos,
2449 module_t *snmp_module;
2451 #ifdef HAVE_SOME_SNMP
2454 /* Set MIBDIRS so that the SNMP library can find its mibs. */
2455 /* XXX - Should we set MIBS or MIBFILES as well? */
2457 mib_path = g_malloc (strlen(get_datafile_dir()) + strlen(MIB_PATH_APPEND) + 20);
2458 sprintf (mib_path, "MIBDIRS=%s\\%s", get_datafile_dir(), MIB_PATH_APPEND);
2459 /* Amazingly enough, Windows does not provide setenv(). */
2460 if (getenv("MIBDIRS") == NULL)
2467 * Suppress warnings about unknown tokens - we aren't initializing
2468 * UCD SNMP in its entirety, we're just initializing the
2469 * MIB-handling part because that's all we're using, which
2470 * means that entries in the configuration file for other
2471 * pars of the library will not be handled, and we don't want
2472 * the config file reading code to whine about that.
2474 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
2475 NETSNMP_DS_LIB_NO_TOKEN_WARNINGS, TRUE);
2476 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
2477 NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 2);
2478 #endif /* HAVE_SOME_SNMP */
2479 proto_snmp = proto_register_protocol("Simple Network Management Protocol",
2481 proto_register_field_array(proto_snmp, hf, array_length(hf));
2482 proto_register_subtree_array(ett, array_length(ett));
2483 snmp_handle = create_dissector_handle(dissect_snmp, proto_snmp);
2485 /* Register configuration preferences */
2486 snmp_module = prefs_register_protocol(proto_snmp, process_prefs);
2487 prefs_register_bool_preference(snmp_module, "display_oid",
2488 "Show SNMP OID in info column",
2489 "Whether the SNMP OID should be shown in the info column",
2493 * Set the default value of "mib_modules".
2495 * If the MIBS environment variable is set, make its value
2496 * the value of "mib_modules", otherwise, set "mib_modules"
2497 * to DEF_MIB_MODULES.
2499 tmp_mib_modules = getenv("MIBS");
2500 if (tmp_mib_modules != NULL)
2501 mib_modules = tmp_mib_modules;
2502 prefs_register_string_preference(snmp_module, "mib_modules",
2503 "MIB modules to load",
2504 "List of MIB modules to load (the list is set to environment variable MIBS if the variable is not already set)",
2506 prefs_register_bool_preference(snmp_module, "desegment",
2507 "Desegment all SNMP-over-TCP messages\nspanning multiple TCP segments",
2508 "Whether the SNMP dissector should desegment all messages "
2509 "spanning multiple TCP segments",
2514 proto_reg_handoff_snmp(void)
2516 dissector_handle_t snmp_tcp_handle;
2518 dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
2519 dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
2520 dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
2521 dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
2522 dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
2523 dissector_add("hpext.dxsap", HPEXT_SNMP, snmp_handle);
2525 snmp_tcp_handle = create_dissector_handle(dissect_snmp_tcp, proto_snmp);
2526 dissector_add("tcp.port", TCP_PORT_SNMP, snmp_tcp_handle);
2527 dissector_add("tcp.port", TCP_PORT_SNMP_TRAP, snmp_tcp_handle);
2529 data_handle = find_dissector("data");
2532 * Process preference settings.
2534 * We can't do this in the register routine, as preferences aren't
2535 * read until all dissector register routines have been called (so
2536 * that all dissector preferences have been registered).
2542 proto_register_smux(void)
2544 static hf_register_info hf[] = {
2546 { "Version", "smux.version", FT_UINT8, BASE_DEC, NULL,
2549 { "PDU type", "smux.pdutype", FT_UINT8, BASE_DEC, VALS(smux_types),
2552 static gint *ett[] = {
2556 proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2558 proto_register_field_array(proto_smux, hf, array_length(hf));
2559 proto_register_subtree_array(ett, array_length(ett));
2563 proto_reg_handoff_smux(void)
2565 dissector_handle_t smux_handle;
2567 smux_handle = create_dissector_handle(dissect_smux, proto_smux);
2568 dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);