xref: /dflybsd-src/contrib/tcpdump/print-snmp.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
141c99275SPeter Avalos /*
241c99275SPeter Avalos  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
341c99275SPeter Avalos  *     John Robert LoVerso. All rights reserved.
441c99275SPeter Avalos  *
541c99275SPeter Avalos  * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos  * modification, are permitted provided that the following conditions
741c99275SPeter Avalos  * are met:
841c99275SPeter Avalos  *
941c99275SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
1041c99275SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
1141c99275SPeter Avalos  *
1241c99275SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
1341c99275SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
1441c99275SPeter Avalos  *    documentation and/or other materials provided with the distribution.
1541c99275SPeter Avalos  *
1641c99275SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1741c99275SPeter Avalos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1841c99275SPeter Avalos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1941c99275SPeter Avalos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2041c99275SPeter Avalos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2141c99275SPeter Avalos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2241c99275SPeter Avalos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2341c99275SPeter Avalos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2441c99275SPeter Avalos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2541c99275SPeter Avalos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2641c99275SPeter Avalos  *
2741c99275SPeter Avalos  *
2841c99275SPeter Avalos  * This implementation has been influenced by the CMU SNMP release,
2941c99275SPeter Avalos  * by Steve Waldbusser.  However, this shares no code with that system.
3041c99275SPeter Avalos  * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_.
3141c99275SPeter Avalos  * Earlier forms of this implementation were derived and/or inspired by an
3241c99275SPeter Avalos  * awk script originally written by C. Philip Wood of LANL (but later
3341c99275SPeter Avalos  * heavily modified by John Robert LoVerso).  The copyright notice for
3441c99275SPeter Avalos  * that work is preserved below, even though it may not rightly apply
3541c99275SPeter Avalos  * to this file.
3641c99275SPeter Avalos  *
3741c99275SPeter Avalos  * Support for SNMPv2c/SNMPv3 and the ability to link the module against
3841c99275SPeter Avalos  * the libsmi was added by J. Schoenwaelder, Copyright (c) 1999.
3941c99275SPeter Avalos  *
4041c99275SPeter Avalos  * This started out as a very simple program, but the incremental decoding
4141c99275SPeter Avalos  * (into the BE structure) complicated things.
4241c99275SPeter Avalos  *
4341c99275SPeter Avalos  #			Los Alamos National Laboratory
4441c99275SPeter Avalos  #
4541c99275SPeter Avalos  #	Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
4641c99275SPeter Avalos  #	This software was produced under a U.S. Government contract
4741c99275SPeter Avalos  #	(W-7405-ENG-36) by Los Alamos National Laboratory, which is
4841c99275SPeter Avalos  #	operated by the	University of California for the U.S. Department
4941c99275SPeter Avalos  #	of Energy.  The U.S. Government is licensed to use, reproduce,
5041c99275SPeter Avalos  #	and distribute this software.  Permission is granted to the
5141c99275SPeter Avalos  #	public to copy and use this software without charge, provided
5241c99275SPeter Avalos  #	that this Notice and any statement of authorship are reproduced
5341c99275SPeter Avalos  #	on all copies.  Neither the Government nor the University makes
5441c99275SPeter Avalos  #	any warranty, express or implied, or assumes any liability or
5541c99275SPeter Avalos  #	responsibility for the use of this software.
5641c99275SPeter Avalos  #	@(#)snmp.awk.x	1.1 (LANL) 1/15/90
5741c99275SPeter Avalos  */
5841c99275SPeter Avalos 
59411677aeSAaron LI /* \summary: Simple Network Management Protocol (SNMP) printer */
6041c99275SPeter Avalos 
6141c99275SPeter Avalos #ifdef HAVE_CONFIG_H
62*ed775ee7SAntonio Huete Jimenez #include <config.h>
6341c99275SPeter Avalos #endif
6441c99275SPeter Avalos 
65*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
6641c99275SPeter Avalos 
6741c99275SPeter Avalos #include <stdio.h>
6841c99275SPeter Avalos #include <string.h>
6941c99275SPeter Avalos 
70411677aeSAaron LI #ifdef USE_LIBSMI
7141c99275SPeter Avalos #include <smi.h>
7241c99275SPeter Avalos #endif
7341c99275SPeter Avalos 
74*ed775ee7SAntonio Huete Jimenez #include "netdissect-ctype.h"
75*ed775ee7SAntonio Huete Jimenez 
76411677aeSAaron LI #include "netdissect.h"
77*ed775ee7SAntonio Huete Jimenez #include "extract.h"
7841c99275SPeter Avalos 
7941c99275SPeter Avalos #undef OPAQUE  /* defined in <wingdi.h> */
8041c99275SPeter Avalos 
81411677aeSAaron LI 
8241c99275SPeter Avalos /*
8341c99275SPeter Avalos  * Universal ASN.1 types
8441c99275SPeter Avalos  * (we only care about the tag values for those allowed in the Internet SMI)
8541c99275SPeter Avalos  */
86411677aeSAaron LI static const char *Universal[] = {
8741c99275SPeter Avalos 	"U-0",
8841c99275SPeter Avalos 	"Boolean",
8941c99275SPeter Avalos 	"Integer",
9041c99275SPeter Avalos #define INTEGER 2
9141c99275SPeter Avalos 	"Bitstring",
9241c99275SPeter Avalos 	"String",
9341c99275SPeter Avalos #define STRING 4
9441c99275SPeter Avalos 	"Null",
9541c99275SPeter Avalos #define ASN_NULL 5
9641c99275SPeter Avalos 	"ObjID",
9741c99275SPeter Avalos #define OBJECTID 6
9841c99275SPeter Avalos 	"ObjectDes",
9941c99275SPeter Avalos 	"U-8","U-9","U-10","U-11",	/* 8-11 */
10041c99275SPeter Avalos 	"U-12","U-13","U-14","U-15",	/* 12-15 */
10141c99275SPeter Avalos 	"Sequence",
10241c99275SPeter Avalos #define SEQUENCE 16
10341c99275SPeter Avalos 	"Set"
10441c99275SPeter Avalos };
10541c99275SPeter Avalos 
10641c99275SPeter Avalos /*
10741c99275SPeter Avalos  * Application-wide ASN.1 types from the Internet SMI and their tags
10841c99275SPeter Avalos  */
109411677aeSAaron LI static const char *Application[] = {
11041c99275SPeter Avalos 	"IpAddress",
11141c99275SPeter Avalos #define IPADDR 0
11241c99275SPeter Avalos 	"Counter",
11341c99275SPeter Avalos #define COUNTER 1
11441c99275SPeter Avalos 	"Gauge",
11541c99275SPeter Avalos #define GAUGE 2
11641c99275SPeter Avalos 	"TimeTicks",
11741c99275SPeter Avalos #define TIMETICKS 3
11841c99275SPeter Avalos 	"Opaque",
11941c99275SPeter Avalos #define OPAQUE 4
12041c99275SPeter Avalos 	"C-5",
12141c99275SPeter Avalos 	"Counter64"
12241c99275SPeter Avalos #define COUNTER64 6
12341c99275SPeter Avalos };
12441c99275SPeter Avalos 
12541c99275SPeter Avalos /*
12641c99275SPeter Avalos  * Context-specific ASN.1 types for the SNMP PDUs and their tags
12741c99275SPeter Avalos  */
128411677aeSAaron LI static const char *Context[] = {
12941c99275SPeter Avalos 	"GetRequest",
13041c99275SPeter Avalos #define GETREQ 0
13141c99275SPeter Avalos 	"GetNextRequest",
13241c99275SPeter Avalos #define GETNEXTREQ 1
13341c99275SPeter Avalos 	"GetResponse",
13441c99275SPeter Avalos #define GETRESP 2
13541c99275SPeter Avalos 	"SetRequest",
13641c99275SPeter Avalos #define SETREQ 3
13741c99275SPeter Avalos 	"Trap",
13841c99275SPeter Avalos #define TRAP 4
13941c99275SPeter Avalos 	"GetBulk",
14041c99275SPeter Avalos #define GETBULKREQ 5
14141c99275SPeter Avalos 	"Inform",
14241c99275SPeter Avalos #define INFORMREQ 6
14341c99275SPeter Avalos 	"V2Trap",
14441c99275SPeter Avalos #define V2TRAP 7
14541c99275SPeter Avalos 	"Report"
14641c99275SPeter Avalos #define REPORT 8
14741c99275SPeter Avalos };
14841c99275SPeter Avalos 
14941c99275SPeter Avalos #define NOTIFY_CLASS(x)	    (x == TRAP || x == V2TRAP || x == INFORMREQ)
15041c99275SPeter Avalos #define READ_CLASS(x)       (x == GETREQ || x == GETNEXTREQ || x == GETBULKREQ)
15141c99275SPeter Avalos #define WRITE_CLASS(x)	    (x == SETREQ)
15241c99275SPeter Avalos #define RESPONSE_CLASS(x)   (x == GETRESP)
15341c99275SPeter Avalos #define INTERNAL_CLASS(x)   (x == REPORT)
15441c99275SPeter Avalos 
15541c99275SPeter Avalos /*
15641c99275SPeter Avalos  * Context-specific ASN.1 types for the SNMP Exceptions and their tags
15741c99275SPeter Avalos  */
158411677aeSAaron LI static const char *Exceptions[] = {
15941c99275SPeter Avalos 	"noSuchObject",
16041c99275SPeter Avalos #define NOSUCHOBJECT 0
16141c99275SPeter Avalos 	"noSuchInstance",
16241c99275SPeter Avalos #define NOSUCHINSTANCE 1
16341c99275SPeter Avalos 	"endOfMibView",
16441c99275SPeter Avalos #define ENDOFMIBVIEW 2
16541c99275SPeter Avalos };
16641c99275SPeter Avalos 
16741c99275SPeter Avalos /*
16841c99275SPeter Avalos  * Private ASN.1 types
16941c99275SPeter Avalos  * The Internet SMI does not specify any
17041c99275SPeter Avalos  */
171411677aeSAaron LI static const char *Private[] = {
17241c99275SPeter Avalos 	"P-0"
17341c99275SPeter Avalos };
17441c99275SPeter Avalos 
17541c99275SPeter Avalos /*
17641c99275SPeter Avalos  * error-status values for any SNMP PDU
17741c99275SPeter Avalos  */
178411677aeSAaron LI static const char *ErrorStatus[] = {
17941c99275SPeter Avalos 	"noError",
18041c99275SPeter Avalos 	"tooBig",
18141c99275SPeter Avalos 	"noSuchName",
18241c99275SPeter Avalos 	"badValue",
18341c99275SPeter Avalos 	"readOnly",
18441c99275SPeter Avalos 	"genErr",
18541c99275SPeter Avalos 	"noAccess",
18641c99275SPeter Avalos 	"wrongType",
18741c99275SPeter Avalos 	"wrongLength",
18841c99275SPeter Avalos 	"wrongEncoding",
18941c99275SPeter Avalos 	"wrongValue",
19041c99275SPeter Avalos 	"noCreation",
19141c99275SPeter Avalos 	"inconsistentValue",
19241c99275SPeter Avalos 	"resourceUnavailable",
19341c99275SPeter Avalos 	"commitFailed",
19441c99275SPeter Avalos 	"undoFailed",
19541c99275SPeter Avalos 	"authorizationError",
19641c99275SPeter Avalos 	"notWritable",
19741c99275SPeter Avalos 	"inconsistentName"
19841c99275SPeter Avalos };
19941c99275SPeter Avalos #define DECODE_ErrorStatus(e) \
20041c99275SPeter Avalos 	( e >= 0 && (size_t)e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
20141c99275SPeter Avalos 		? ErrorStatus[e] \
20241c99275SPeter Avalos 		: (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf))
20341c99275SPeter Avalos 
20441c99275SPeter Avalos /*
20541c99275SPeter Avalos  * generic-trap values in the SNMP Trap-PDU
20641c99275SPeter Avalos  */
207411677aeSAaron LI static const char *GenericTrap[] = {
20841c99275SPeter Avalos 	"coldStart",
20941c99275SPeter Avalos 	"warmStart",
21041c99275SPeter Avalos 	"linkDown",
21141c99275SPeter Avalos 	"linkUp",
21241c99275SPeter Avalos 	"authenticationFailure",
21341c99275SPeter Avalos 	"egpNeighborLoss",
21441c99275SPeter Avalos 	"enterpriseSpecific"
21541c99275SPeter Avalos #define GT_ENTERPRISE 6
21641c99275SPeter Avalos };
21741c99275SPeter Avalos #define DECODE_GenericTrap(t) \
21841c99275SPeter Avalos 	( t >= 0 && (size_t)t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
21941c99275SPeter Avalos 		? GenericTrap[t] \
22041c99275SPeter Avalos 		: (snprintf(buf, sizeof(buf), "gt=%d", t), buf))
22141c99275SPeter Avalos 
22241c99275SPeter Avalos /*
22341c99275SPeter Avalos  * ASN.1 type class table
22441c99275SPeter Avalos  * Ties together the preceding Universal, Application, Context, and Private
22541c99275SPeter Avalos  * type definitions.
22641c99275SPeter Avalos  */
22741c99275SPeter Avalos #define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
228411677aeSAaron LI static const struct {
22941c99275SPeter Avalos 	const char	*name;
23041c99275SPeter Avalos 	const char	**Id;
23141c99275SPeter Avalos 	    int	numIDs;
23241c99275SPeter Avalos     } Class[] = {
23341c99275SPeter Avalos 	defineCLASS(Universal),
23441c99275SPeter Avalos #define	UNIVERSAL	0
23541c99275SPeter Avalos 	defineCLASS(Application),
23641c99275SPeter Avalos #define	APPLICATION	1
23741c99275SPeter Avalos 	defineCLASS(Context),
23841c99275SPeter Avalos #define	CONTEXT		2
23941c99275SPeter Avalos 	defineCLASS(Private),
24041c99275SPeter Avalos #define	PRIVATE		3
24141c99275SPeter Avalos 	defineCLASS(Exceptions),
24241c99275SPeter Avalos #define EXCEPTIONS	4
24341c99275SPeter Avalos };
24441c99275SPeter Avalos 
24541c99275SPeter Avalos /*
24641c99275SPeter Avalos  * defined forms for ASN.1 types
24741c99275SPeter Avalos  */
248411677aeSAaron LI static const char *Form[] = {
24941c99275SPeter Avalos 	"Primitive",
25041c99275SPeter Avalos #define PRIMITIVE	0
25141c99275SPeter Avalos 	"Constructed",
25241c99275SPeter Avalos #define CONSTRUCTED	1
25341c99275SPeter Avalos };
25441c99275SPeter Avalos 
25541c99275SPeter Avalos /*
25641c99275SPeter Avalos  * A structure for the OID tree for the compiled-in MIB.
25741c99275SPeter Avalos  * This is stored as a general-order tree.
25841c99275SPeter Avalos  */
259411677aeSAaron LI static struct obj {
26041c99275SPeter Avalos 	const char	*desc;		/* name of object */
26141c99275SPeter Avalos 	u_char	oid;			/* sub-id following parent */
26241c99275SPeter Avalos 	u_char	type;			/* object type (unused) */
26341c99275SPeter Avalos 	struct obj *child, *next;	/* child and next sibling pointers */
26441c99275SPeter Avalos } *objp = NULL;
26541c99275SPeter Avalos 
26641c99275SPeter Avalos /*
26741c99275SPeter Avalos  * Include the compiled in SNMP MIB.  "mib.h" is produced by feeding
26841c99275SPeter Avalos  * RFC-1156 format files into "makemib".  "mib.h" MUST define at least
26941c99275SPeter Avalos  * a value for `mibroot'.
27041c99275SPeter Avalos  *
27141c99275SPeter Avalos  * In particular, this is gross, as this is including initialized structures,
27241c99275SPeter Avalos  * and by right shouldn't be an "include" file.
27341c99275SPeter Avalos  */
27441c99275SPeter Avalos #include "mib.h"
27541c99275SPeter Avalos 
27641c99275SPeter Avalos /*
27741c99275SPeter Avalos  * This defines a list of OIDs which will be abbreviated on output.
27841c99275SPeter Avalos  * Currently, this includes the prefixes for the Internet MIB, the
27941c99275SPeter Avalos  * private enterprises tree, and the experimental tree.
28041c99275SPeter Avalos  */
281411677aeSAaron LI #define OID_FIRST_OCTET(x, y)	(((x)*40) + (y))	/* X.690 8.19.4 */
282411677aeSAaron LI 
283411677aeSAaron LI #ifndef NO_ABREV_MIB
284411677aeSAaron LI static const uint8_t mib_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 2, 1 };
285411677aeSAaron LI #endif
286411677aeSAaron LI #ifndef NO_ABREV_ENTER
287411677aeSAaron LI static const uint8_t enterprises_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 4, 1 };
288411677aeSAaron LI #endif
289411677aeSAaron LI #ifndef NO_ABREV_EXPERI
290411677aeSAaron LI static const uint8_t experimental_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 3 };
291411677aeSAaron LI #endif
292411677aeSAaron LI #ifndef NO_ABBREV_SNMPMODS
293411677aeSAaron LI static const uint8_t snmpModules_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 6, 3 };
294411677aeSAaron LI #endif
295411677aeSAaron LI 
296411677aeSAaron LI #define OBJ_ABBREV_ENTRY(prefix, obj) \
297411677aeSAaron LI 	{ prefix, &_ ## obj ## _obj, obj ## _oid, sizeof (obj ## _oid) }
298411677aeSAaron LI static const struct obj_abrev {
29941c99275SPeter Avalos 	const char *prefix;		/* prefix for this abrev */
30041c99275SPeter Avalos 	struct obj *node;		/* pointer into object table */
301411677aeSAaron LI 	const uint8_t *oid;		/* ASN.1 encoded OID */
302411677aeSAaron LI 	size_t oid_len;			/* length of OID */
30341c99275SPeter Avalos } obj_abrev_list[] = {
30441c99275SPeter Avalos #ifndef NO_ABREV_MIB
30541c99275SPeter Avalos 	/* .iso.org.dod.internet.mgmt.mib */
306411677aeSAaron LI 	OBJ_ABBREV_ENTRY("",	mib),
30741c99275SPeter Avalos #endif
30841c99275SPeter Avalos #ifndef NO_ABREV_ENTER
30941c99275SPeter Avalos 	/* .iso.org.dod.internet.private.enterprises */
310411677aeSAaron LI 	OBJ_ABBREV_ENTRY("E:",	enterprises),
31141c99275SPeter Avalos #endif
31241c99275SPeter Avalos #ifndef NO_ABREV_EXPERI
31341c99275SPeter Avalos 	/* .iso.org.dod.internet.experimental */
314411677aeSAaron LI 	OBJ_ABBREV_ENTRY("X:",	experimental),
31541c99275SPeter Avalos #endif
31641c99275SPeter Avalos #ifndef NO_ABBREV_SNMPMODS
31741c99275SPeter Avalos 	/* .iso.org.dod.internet.snmpV2.snmpModules */
318411677aeSAaron LI 	OBJ_ABBREV_ENTRY("S:",	snmpModules),
31941c99275SPeter Avalos #endif
320411677aeSAaron LI 	{ 0,0,0,0 }
32141c99275SPeter Avalos };
32241c99275SPeter Avalos 
32341c99275SPeter Avalos /*
32441c99275SPeter Avalos  * This is used in the OID print routine to walk down the object tree
32541c99275SPeter Avalos  * rooted at `mibroot'.
32641c99275SPeter Avalos  */
32741c99275SPeter Avalos #define OBJ_PRINT(o, suppressdot) \
32841c99275SPeter Avalos { \
32941c99275SPeter Avalos 	if (objp) { \
33041c99275SPeter Avalos 		do { \
33141c99275SPeter Avalos 			if ((o) == objp->oid) \
33241c99275SPeter Avalos 				break; \
33341c99275SPeter Avalos 		} while ((objp = objp->next) != NULL); \
33441c99275SPeter Avalos 	} \
33541c99275SPeter Avalos 	if (objp) { \
336*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(suppressdot?"%s":".%s", objp->desc); \
33741c99275SPeter Avalos 		objp = objp->child; \
33841c99275SPeter Avalos 	} else \
339*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(suppressdot?"%u":".%u", (o)); \
34041c99275SPeter Avalos }
34141c99275SPeter Avalos 
34241c99275SPeter Avalos /*
34341c99275SPeter Avalos  * This is the definition for the Any-Data-Type storage used purely for
34441c99275SPeter Avalos  * temporary internal representation while decoding an ASN.1 data stream.
34541c99275SPeter Avalos  */
34641c99275SPeter Avalos struct be {
347411677aeSAaron LI 	uint32_t asnlen;
34841c99275SPeter Avalos 	union {
349411677aeSAaron LI 		const uint8_t *raw;
35041c99275SPeter Avalos 		int32_t integer;
351411677aeSAaron LI 		uint32_t uns;
35241c99275SPeter Avalos 		const u_char *str;
353411677aeSAaron LI 		uint64_t uns64;
35441c99275SPeter Avalos 	} data;
35541c99275SPeter Avalos 	u_short id;
35641c99275SPeter Avalos 	u_char form, class;		/* tag info */
35741c99275SPeter Avalos 	u_char type;
35841c99275SPeter Avalos #define BE_ANY		255
35941c99275SPeter Avalos #define BE_NONE		0
36041c99275SPeter Avalos #define BE_NULL		1
36141c99275SPeter Avalos #define BE_OCTET	2
36241c99275SPeter Avalos #define BE_OID		3
36341c99275SPeter Avalos #define BE_INT		4
36441c99275SPeter Avalos #define BE_UNS		5
36541c99275SPeter Avalos #define BE_STR		6
36641c99275SPeter Avalos #define BE_SEQ		7
36741c99275SPeter Avalos #define BE_INETADDR	8
36841c99275SPeter Avalos #define BE_PDU		9
36941c99275SPeter Avalos #define BE_UNS64	10
37041c99275SPeter Avalos #define BE_NOSUCHOBJECT	128
37141c99275SPeter Avalos #define BE_NOSUCHINST	129
37241c99275SPeter Avalos #define BE_ENDOFMIBVIEW	130
37341c99275SPeter Avalos };
37441c99275SPeter Avalos 
37541c99275SPeter Avalos /*
37641c99275SPeter Avalos  * SNMP versions recognized by this module
37741c99275SPeter Avalos  */
378411677aeSAaron LI static const char *SnmpVersion[] = {
37941c99275SPeter Avalos 	"SNMPv1",
38041c99275SPeter Avalos #define SNMP_VERSION_1	0
38141c99275SPeter Avalos 	"SNMPv2c",
38241c99275SPeter Avalos #define SNMP_VERSION_2	1
38341c99275SPeter Avalos 	"SNMPv2u",
38441c99275SPeter Avalos #define SNMP_VERSION_2U	2
38541c99275SPeter Avalos 	"SNMPv3"
38641c99275SPeter Avalos #define SNMP_VERSION_3	3
38741c99275SPeter Avalos };
38841c99275SPeter Avalos 
38941c99275SPeter Avalos /*
39041c99275SPeter Avalos  * Defaults for SNMP PDU components
39141c99275SPeter Avalos  */
39241c99275SPeter Avalos #define DEF_COMMUNITY "public"
39341c99275SPeter Avalos 
39441c99275SPeter Avalos /*
39541c99275SPeter Avalos  * constants for ASN.1 decoding
39641c99275SPeter Avalos  */
39741c99275SPeter Avalos #define OIDMUX 40
39841c99275SPeter Avalos #define ASNLEN_INETADDR 4
39941c99275SPeter Avalos #define ASN_SHIFT7 7
40041c99275SPeter Avalos #define ASN_SHIFT8 8
40141c99275SPeter Avalos #define ASN_BIT8 0x80
40241c99275SPeter Avalos #define ASN_LONGLEN 0x80
40341c99275SPeter Avalos 
40441c99275SPeter Avalos #define ASN_ID_BITS 0x1f
40541c99275SPeter Avalos #define ASN_FORM_BITS 0x20
40641c99275SPeter Avalos #define ASN_FORM_SHIFT 5
40741c99275SPeter Avalos #define ASN_CLASS_BITS 0xc0
40841c99275SPeter Avalos #define ASN_CLASS_SHIFT 6
40941c99275SPeter Avalos 
41041c99275SPeter Avalos #define ASN_ID_EXT 0x1f		/* extension ID in tag field */
41141c99275SPeter Avalos 
41241c99275SPeter Avalos /*
41341c99275SPeter Avalos  * This decodes the next ASN.1 object in the stream pointed to by "p"
41441c99275SPeter Avalos  * (and of real-length "len") and stores the intermediate data in the
41541c99275SPeter Avalos  * provided BE object.
41641c99275SPeter Avalos  *
41741c99275SPeter Avalos  * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
41841c99275SPeter Avalos  * O/w, this returns the number of bytes parsed from "p".
41941c99275SPeter Avalos  */
42041c99275SPeter Avalos static int
asn1_parse(netdissect_options * ndo,const u_char * p,u_int len,struct be * elem)421411677aeSAaron LI asn1_parse(netdissect_options *ndo,
422*ed775ee7SAntonio Huete Jimenez            const u_char *p, u_int len, struct be *elem)
42341c99275SPeter Avalos {
42441c99275SPeter Avalos 	u_char form, class, id;
425*ed775ee7SAntonio Huete Jimenez 	u_int i, hdr;
42641c99275SPeter Avalos 
42741c99275SPeter Avalos 	elem->asnlen = 0;
42841c99275SPeter Avalos 	elem->type = BE_ANY;
42941c99275SPeter Avalos 	if (len < 1) {
430*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[nothing to parse]");
43141c99275SPeter Avalos 		return -1;
43241c99275SPeter Avalos 	}
43341c99275SPeter Avalos 
43441c99275SPeter Avalos 	/*
43541c99275SPeter Avalos 	 * it would be nice to use a bit field, but you can't depend on them.
43641c99275SPeter Avalos 	 *  +---+---+---+---+---+---+---+---+
43741c99275SPeter Avalos 	 *  + class |frm|        id         |
43841c99275SPeter Avalos 	 *  +---+---+---+---+---+---+---+---+
43941c99275SPeter Avalos 	 *    7   6   5   4   3   2   1   0
44041c99275SPeter Avalos 	 */
441*ed775ee7SAntonio Huete Jimenez 	id = GET_U_1(p) & ASN_ID_BITS;		/* lower 5 bits, range 00-1f */
44241c99275SPeter Avalos #ifdef notdef
443*ed775ee7SAntonio Huete Jimenez 	form = (GET_U_1(p) & 0xe0) >> 5;	/* move upper 3 bits to lower 3 */
44441c99275SPeter Avalos 	class = form >> 1;		/* bits 7&6 -> bits 1&0, range 0-3 */
44541c99275SPeter Avalos 	form &= 0x1;			/* bit 5 -> bit 0, range 0-1 */
44641c99275SPeter Avalos #else
447*ed775ee7SAntonio Huete Jimenez 	form = (u_char)(GET_U_1(p) & ASN_FORM_BITS) >> ASN_FORM_SHIFT;
448*ed775ee7SAntonio Huete Jimenez 	class = (u_char)(GET_U_1(p) & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT;
44941c99275SPeter Avalos #endif
45041c99275SPeter Avalos 	elem->form = form;
45141c99275SPeter Avalos 	elem->class = class;
45241c99275SPeter Avalos 	elem->id = id;
45341c99275SPeter Avalos 	p++; len--; hdr = 1;
45441c99275SPeter Avalos 	/* extended tag field */
45541c99275SPeter Avalos 	if (id == ASN_ID_EXT) {
45641c99275SPeter Avalos 		/*
45741c99275SPeter Avalos 		 * The ID follows, as a sequence of octets with the
45841c99275SPeter Avalos 		 * 8th bit set and the remaining 7 bits being
45941c99275SPeter Avalos 		 * the next 7 bits of the value, terminated with
46041c99275SPeter Avalos 		 * an octet with the 8th bit not set.
46141c99275SPeter Avalos 		 *
46241c99275SPeter Avalos 		 * First, assemble all the octets with the 8th
46341c99275SPeter Avalos 		 * bit set.  XXX - this doesn't handle a value
46441c99275SPeter Avalos 		 * that won't fit in 32 bits.
46541c99275SPeter Avalos 		 */
466411677aeSAaron LI 		id = 0;
467*ed775ee7SAntonio Huete Jimenez 		while (GET_U_1(p) & ASN_BIT8) {
46841c99275SPeter Avalos 			if (len < 1) {
469*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("[Xtagfield?]");
47041c99275SPeter Avalos 				return -1;
47141c99275SPeter Avalos 			}
472*ed775ee7SAntonio Huete Jimenez 			id = (id << 7) | (GET_U_1(p) & ~ASN_BIT8);
473411677aeSAaron LI 			len--;
474411677aeSAaron LI 			hdr++;
475411677aeSAaron LI 			p++;
47641c99275SPeter Avalos 		}
47741c99275SPeter Avalos 		if (len < 1) {
478*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Xtagfield?]");
47941c99275SPeter Avalos 			return -1;
48041c99275SPeter Avalos 		}
481*ed775ee7SAntonio Huete Jimenez 		elem->id = id = (id << 7) | GET_U_1(p);
48241c99275SPeter Avalos 		--len;
48341c99275SPeter Avalos 		++hdr;
48441c99275SPeter Avalos 		++p;
48541c99275SPeter Avalos 	}
48641c99275SPeter Avalos 	if (len < 1) {
487*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[no asnlen]");
48841c99275SPeter Avalos 		return -1;
48941c99275SPeter Avalos 	}
490*ed775ee7SAntonio Huete Jimenez 	elem->asnlen = GET_U_1(p);
49141c99275SPeter Avalos 	p++; len--; hdr++;
49241c99275SPeter Avalos 	if (elem->asnlen & ASN_BIT8) {
493411677aeSAaron LI 		uint32_t noct = elem->asnlen % ASN_BIT8;
49441c99275SPeter Avalos 		elem->asnlen = 0;
49541c99275SPeter Avalos 		if (len < noct) {
496*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[asnlen? %d<%d]", len, noct);
49741c99275SPeter Avalos 			return -1;
49841c99275SPeter Avalos 		}
499*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, noct);
500*ed775ee7SAntonio Huete Jimenez 		for (; noct != 0; len--, hdr++, noct--) {
501*ed775ee7SAntonio Huete Jimenez 			elem->asnlen = (elem->asnlen << ASN_SHIFT8) | GET_U_1(p);
502*ed775ee7SAntonio Huete Jimenez 			p++;
503*ed775ee7SAntonio Huete Jimenez 		}
50441c99275SPeter Avalos 	}
50541c99275SPeter Avalos 	if (len < elem->asnlen) {
506*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[len%d<asnlen%u]", len, elem->asnlen);
50741c99275SPeter Avalos 		return -1;
50841c99275SPeter Avalos 	}
50941c99275SPeter Avalos 	if (form >= sizeof(Form)/sizeof(Form[0])) {
510*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[form?%d]", form);
51141c99275SPeter Avalos 		return -1;
51241c99275SPeter Avalos 	}
51341c99275SPeter Avalos 	if (class >= sizeof(Class)/sizeof(Class[0])) {
514*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[class?%c/%d]", *Form[form], class);
51541c99275SPeter Avalos 		return -1;
51641c99275SPeter Avalos 	}
51741c99275SPeter Avalos 	if ((int)id >= Class[class].numIDs) {
518*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[id?%c/%s/%d]", *Form[form], Class[class].name, id);
51941c99275SPeter Avalos 		return -1;
52041c99275SPeter Avalos 	}
521*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, elem->asnlen);
52241c99275SPeter Avalos 
52341c99275SPeter Avalos 	switch (form) {
52441c99275SPeter Avalos 	case PRIMITIVE:
52541c99275SPeter Avalos 		switch (class) {
52641c99275SPeter Avalos 		case UNIVERSAL:
52741c99275SPeter Avalos 			switch (id) {
52841c99275SPeter Avalos 			case STRING:
52941c99275SPeter Avalos 				elem->type = BE_STR;
53041c99275SPeter Avalos 				elem->data.str = p;
53141c99275SPeter Avalos 				break;
53241c99275SPeter Avalos 
53341c99275SPeter Avalos 			case INTEGER: {
534*ed775ee7SAntonio Huete Jimenez 				int32_t data;
53541c99275SPeter Avalos 				elem->type = BE_INT;
53641c99275SPeter Avalos 				data = 0;
53741c99275SPeter Avalos 
538411677aeSAaron LI 				if (elem->asnlen == 0) {
539*ed775ee7SAntonio Huete Jimenez 					ND_PRINT("[asnlen=0]");
540411677aeSAaron LI 					return -1;
541411677aeSAaron LI 				}
542*ed775ee7SAntonio Huete Jimenez 				if (GET_U_1(p) & ASN_BIT8)	/* negative */
54341c99275SPeter Avalos 					data = -1;
544*ed775ee7SAntonio Huete Jimenez 				for (i = elem->asnlen; i != 0; p++, i--)
545*ed775ee7SAntonio Huete Jimenez 					data = (data << ASN_SHIFT8) | GET_U_1(p);
54641c99275SPeter Avalos 				elem->data.integer = data;
54741c99275SPeter Avalos 				break;
54841c99275SPeter Avalos 			}
54941c99275SPeter Avalos 
55041c99275SPeter Avalos 			case OBJECTID:
55141c99275SPeter Avalos 				elem->type = BE_OID;
552411677aeSAaron LI 				elem->data.raw = (const uint8_t *)p;
55341c99275SPeter Avalos 				break;
55441c99275SPeter Avalos 
55541c99275SPeter Avalos 			case ASN_NULL:
55641c99275SPeter Avalos 				elem->type = BE_NULL;
55741c99275SPeter Avalos 				elem->data.raw = NULL;
55841c99275SPeter Avalos 				break;
55941c99275SPeter Avalos 
56041c99275SPeter Avalos 			default:
56141c99275SPeter Avalos 				elem->type = BE_OCTET;
562411677aeSAaron LI 				elem->data.raw = (const uint8_t *)p;
563*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("[P/U/%s]", Class[class].Id[id]);
56441c99275SPeter Avalos 				break;
56541c99275SPeter Avalos 			}
56641c99275SPeter Avalos 			break;
56741c99275SPeter Avalos 
56841c99275SPeter Avalos 		case APPLICATION:
56941c99275SPeter Avalos 			switch (id) {
57041c99275SPeter Avalos 			case IPADDR:
57141c99275SPeter Avalos 				elem->type = BE_INETADDR;
572411677aeSAaron LI 				elem->data.raw = (const uint8_t *)p;
57341c99275SPeter Avalos 				break;
57441c99275SPeter Avalos 
57541c99275SPeter Avalos 			case COUNTER:
57641c99275SPeter Avalos 			case GAUGE:
57741c99275SPeter Avalos 			case TIMETICKS: {
578*ed775ee7SAntonio Huete Jimenez 				uint32_t data;
57941c99275SPeter Avalos 				elem->type = BE_UNS;
58041c99275SPeter Avalos 				data = 0;
581*ed775ee7SAntonio Huete Jimenez 				for (i = elem->asnlen; i != 0; p++, i--)
582*ed775ee7SAntonio Huete Jimenez 					data = (data << 8) + GET_U_1(p);
58341c99275SPeter Avalos 				elem->data.uns = data;
58441c99275SPeter Avalos 				break;
58541c99275SPeter Avalos 			}
58641c99275SPeter Avalos 
58741c99275SPeter Avalos 			case COUNTER64: {
588*ed775ee7SAntonio Huete Jimenez 				uint64_t data64;
58941c99275SPeter Avalos 			        elem->type = BE_UNS64;
590411677aeSAaron LI 				data64 = 0;
591*ed775ee7SAntonio Huete Jimenez 				for (i = elem->asnlen; i != 0; p++, i--)
592*ed775ee7SAntonio Huete Jimenez 					data64 = (data64 << 8) + GET_U_1(p);
593411677aeSAaron LI 				elem->data.uns64 = data64;
59441c99275SPeter Avalos 				break;
59541c99275SPeter Avalos 			}
59641c99275SPeter Avalos 
59741c99275SPeter Avalos 			default:
59841c99275SPeter Avalos 				elem->type = BE_OCTET;
599411677aeSAaron LI 				elem->data.raw = (const uint8_t *)p;
600*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("[P/A/%s]",
601*ed775ee7SAntonio Huete Jimenez 					Class[class].Id[id]);
60241c99275SPeter Avalos 				break;
60341c99275SPeter Avalos 			}
60441c99275SPeter Avalos 			break;
60541c99275SPeter Avalos 
60641c99275SPeter Avalos 		case CONTEXT:
60741c99275SPeter Avalos 			switch (id) {
60841c99275SPeter Avalos 			case NOSUCHOBJECT:
60941c99275SPeter Avalos 				elem->type = BE_NOSUCHOBJECT;
61041c99275SPeter Avalos 				elem->data.raw = NULL;
61141c99275SPeter Avalos 				break;
61241c99275SPeter Avalos 
61341c99275SPeter Avalos 			case NOSUCHINSTANCE:
61441c99275SPeter Avalos 				elem->type = BE_NOSUCHINST;
61541c99275SPeter Avalos 				elem->data.raw = NULL;
61641c99275SPeter Avalos 				break;
61741c99275SPeter Avalos 
61841c99275SPeter Avalos 			case ENDOFMIBVIEW:
61941c99275SPeter Avalos 				elem->type = BE_ENDOFMIBVIEW;
62041c99275SPeter Avalos 				elem->data.raw = NULL;
62141c99275SPeter Avalos 				break;
62241c99275SPeter Avalos 			}
62341c99275SPeter Avalos 			break;
62441c99275SPeter Avalos 
62541c99275SPeter Avalos 		default:
626*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[P/%s/%s]", Class[class].name, Class[class].Id[id]);
62741c99275SPeter Avalos 			elem->type = BE_OCTET;
628411677aeSAaron LI 			elem->data.raw = (const uint8_t *)p;
62941c99275SPeter Avalos 			break;
63041c99275SPeter Avalos 		}
63141c99275SPeter Avalos 		break;
63241c99275SPeter Avalos 
63341c99275SPeter Avalos 	case CONSTRUCTED:
63441c99275SPeter Avalos 		switch (class) {
63541c99275SPeter Avalos 		case UNIVERSAL:
63641c99275SPeter Avalos 			switch (id) {
63741c99275SPeter Avalos 			case SEQUENCE:
63841c99275SPeter Avalos 				elem->type = BE_SEQ;
639411677aeSAaron LI 				elem->data.raw = (const uint8_t *)p;
64041c99275SPeter Avalos 				break;
64141c99275SPeter Avalos 
64241c99275SPeter Avalos 			default:
64341c99275SPeter Avalos 				elem->type = BE_OCTET;
644411677aeSAaron LI 				elem->data.raw = (const uint8_t *)p;
645*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("C/U/%s", Class[class].Id[id]);
64641c99275SPeter Avalos 				break;
64741c99275SPeter Avalos 			}
64841c99275SPeter Avalos 			break;
64941c99275SPeter Avalos 
65041c99275SPeter Avalos 		case CONTEXT:
65141c99275SPeter Avalos 			elem->type = BE_PDU;
652411677aeSAaron LI 			elem->data.raw = (const uint8_t *)p;
65341c99275SPeter Avalos 			break;
65441c99275SPeter Avalos 
65541c99275SPeter Avalos 		default:
65641c99275SPeter Avalos 			elem->type = BE_OCTET;
657411677aeSAaron LI 			elem->data.raw = (const uint8_t *)p;
658*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("C/%s/%s", Class[class].name, Class[class].Id[id]);
65941c99275SPeter Avalos 			break;
66041c99275SPeter Avalos 		}
66141c99275SPeter Avalos 		break;
66241c99275SPeter Avalos 	}
66341c99275SPeter Avalos 	p += elem->asnlen;
66441c99275SPeter Avalos 	len -= elem->asnlen;
66541c99275SPeter Avalos 	return elem->asnlen + hdr;
66641c99275SPeter Avalos 
66741c99275SPeter Avalos trunc:
668*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
669411677aeSAaron LI 	return -1;
670411677aeSAaron LI }
671411677aeSAaron LI 
672411677aeSAaron LI static int
asn1_print_octets(netdissect_options * ndo,struct be * elem)673411677aeSAaron LI asn1_print_octets(netdissect_options *ndo, struct be *elem)
674411677aeSAaron LI {
675411677aeSAaron LI 	const u_char *p = (const u_char *)elem->data.raw;
676411677aeSAaron LI 	uint32_t asnlen = elem->asnlen;
677411677aeSAaron LI 	uint32_t i;
678411677aeSAaron LI 
679*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, asnlen);
680*ed775ee7SAntonio Huete Jimenez 	for (i = asnlen; i != 0; p++, i--)
681*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("_%.2x", GET_U_1(p));
682411677aeSAaron LI 	return 0;
683411677aeSAaron LI 
684411677aeSAaron LI trunc:
685*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
686411677aeSAaron LI 	return -1;
687411677aeSAaron LI }
688411677aeSAaron LI 
689411677aeSAaron LI static int
asn1_print_string(netdissect_options * ndo,struct be * elem)690411677aeSAaron LI asn1_print_string(netdissect_options *ndo, struct be *elem)
691411677aeSAaron LI {
692*ed775ee7SAntonio Huete Jimenez 	int printable = 1, first = 1;
693411677aeSAaron LI 	const u_char *p;
694411677aeSAaron LI 	uint32_t asnlen = elem->asnlen;
695411677aeSAaron LI 	uint32_t i;
696411677aeSAaron LI 
697411677aeSAaron LI 	p = elem->data.str;
698*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, asnlen);
699*ed775ee7SAntonio Huete Jimenez 	for (i = asnlen; printable && i != 0; p++, i--)
700*ed775ee7SAntonio Huete Jimenez 		printable = ND_ASCII_ISPRINT(GET_U_1(p));
701411677aeSAaron LI 	p = elem->data.str;
702411677aeSAaron LI 	if (printable) {
703*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\"");
704*ed775ee7SAntonio Huete Jimenez 		if (nd_printn(ndo, p, asnlen, ndo->ndo_snapend)) {
705*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\"");
706411677aeSAaron LI 			goto trunc;
707411677aeSAaron LI 		}
708*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\"");
709411677aeSAaron LI 	} else {
710*ed775ee7SAntonio Huete Jimenez 		for (i = asnlen; i != 0; p++, i--) {
711*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(first ? "%.2x" : "_%.2x", GET_U_1(p));
712411677aeSAaron LI 			first = 0;
713411677aeSAaron LI 		}
714411677aeSAaron LI 	}
715411677aeSAaron LI 	return 0;
716411677aeSAaron LI 
717411677aeSAaron LI trunc:
718*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
71941c99275SPeter Avalos 	return -1;
72041c99275SPeter Avalos }
72141c99275SPeter Avalos 
72241c99275SPeter Avalos /*
72341c99275SPeter Avalos  * Display the ASN.1 object represented by the BE object.
72441c99275SPeter Avalos  * This used to be an integral part of asn1_parse() before the intermediate
72541c99275SPeter Avalos  * BE form was added.
72641c99275SPeter Avalos  */
72741c99275SPeter Avalos static int
asn1_print(netdissect_options * ndo,struct be * elem)728411677aeSAaron LI asn1_print(netdissect_options *ndo,
729411677aeSAaron LI            struct be *elem)
73041c99275SPeter Avalos {
731411677aeSAaron LI 	const u_char *p;
732411677aeSAaron LI 	uint32_t asnlen = elem->asnlen;
733411677aeSAaron LI 	uint32_t i;
73441c99275SPeter Avalos 
73541c99275SPeter Avalos 	switch (elem->type) {
73641c99275SPeter Avalos 
73741c99275SPeter Avalos 	case BE_OCTET:
738411677aeSAaron LI 		if (asn1_print_octets(ndo, elem) == -1)
739411677aeSAaron LI 			return -1;
74041c99275SPeter Avalos 		break;
74141c99275SPeter Avalos 
74241c99275SPeter Avalos 	case BE_NULL:
74341c99275SPeter Avalos 		break;
74441c99275SPeter Avalos 
74541c99275SPeter Avalos 	case BE_OID: {
746411677aeSAaron LI 		int o = 0, first = -1;
74741c99275SPeter Avalos 
748411677aeSAaron LI 		p = (const u_char *)elem->data.raw;
749411677aeSAaron LI 		i = asnlen;
750411677aeSAaron LI 		if (!ndo->ndo_nflag && asnlen > 2) {
751411677aeSAaron LI 			const struct obj_abrev *a = &obj_abrev_list[0];
75241c99275SPeter Avalos 			for (; a->node; a++) {
753411677aeSAaron LI 				if (i < a->oid_len)
754411677aeSAaron LI 					continue;
755*ed775ee7SAntonio Huete Jimenez 				if (!ND_TTEST_LEN(p, a->oid_len))
756411677aeSAaron LI 					continue;
757411677aeSAaron LI 				if (memcmp(a->oid, p, a->oid_len) == 0) {
75841c99275SPeter Avalos 					objp = a->node->child;
759411677aeSAaron LI 					i -= a->oid_len;
760411677aeSAaron LI 					p += a->oid_len;
761*ed775ee7SAntonio Huete Jimenez 					ND_PRINT("%s", a->prefix);
76241c99275SPeter Avalos 					first = 1;
76341c99275SPeter Avalos 					break;
76441c99275SPeter Avalos 				}
76541c99275SPeter Avalos 			}
76641c99275SPeter Avalos 		}
76741c99275SPeter Avalos 
768*ed775ee7SAntonio Huete Jimenez 		for (; i != 0; p++, i--) {
769*ed775ee7SAntonio Huete Jimenez 			o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8);
770*ed775ee7SAntonio Huete Jimenez 			if (GET_U_1(p) & ASN_LONGLEN)
77141c99275SPeter Avalos 			        continue;
77241c99275SPeter Avalos 
77341c99275SPeter Avalos 			/*
774411677aeSAaron LI 			 * first subitem encodes two items with
775411677aeSAaron LI 			 * 1st*OIDMUX+2nd
77641c99275SPeter Avalos 			 * (see X.690:1997 clause 8.19 for the details)
77741c99275SPeter Avalos 			 */
77841c99275SPeter Avalos 			if (first < 0) {
77941c99275SPeter Avalos 			        int s;
780411677aeSAaron LI 				if (!ndo->ndo_nflag)
78141c99275SPeter Avalos 					objp = mibroot;
78241c99275SPeter Avalos 				first = 0;
78341c99275SPeter Avalos 				s = o / OIDMUX;
78441c99275SPeter Avalos 				if (s > 2) s = 2;
78541c99275SPeter Avalos 				OBJ_PRINT(s, first);
78641c99275SPeter Avalos 				o -= s * OIDMUX;
78741c99275SPeter Avalos 			}
78841c99275SPeter Avalos 			OBJ_PRINT(o, first);
78941c99275SPeter Avalos 			if (--first < 0)
79041c99275SPeter Avalos 				first = 0;
79141c99275SPeter Avalos 			o = 0;
79241c99275SPeter Avalos 		}
79341c99275SPeter Avalos 		break;
79441c99275SPeter Avalos 	}
79541c99275SPeter Avalos 
79641c99275SPeter Avalos 	case BE_INT:
797*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%d", elem->data.integer);
79841c99275SPeter Avalos 		break;
79941c99275SPeter Avalos 
80041c99275SPeter Avalos 	case BE_UNS:
801*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%u", elem->data.uns);
80241c99275SPeter Avalos 		break;
80341c99275SPeter Avalos 
804411677aeSAaron LI 	case BE_UNS64:
805*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%" PRIu64, elem->data.uns64);
80641c99275SPeter Avalos 		break;
80741c99275SPeter Avalos 
808411677aeSAaron LI 	case BE_STR:
809411677aeSAaron LI 		if (asn1_print_string(ndo, elem) == -1)
810411677aeSAaron LI 			return -1;
81141c99275SPeter Avalos 		break;
81241c99275SPeter Avalos 
81341c99275SPeter Avalos 	case BE_SEQ:
814*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Seq(%u)", elem->asnlen);
81541c99275SPeter Avalos 		break;
81641c99275SPeter Avalos 
81741c99275SPeter Avalos 	case BE_INETADDR:
81841c99275SPeter Avalos 		if (asnlen != ASNLEN_INETADDR)
819*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[inetaddr len!=%d]", ASNLEN_INETADDR);
820411677aeSAaron LI 		p = (const u_char *)elem->data.raw;
821*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, asnlen);
822*ed775ee7SAntonio Huete Jimenez 		for (i = asnlen; i != 0; p++, i--) {
823*ed775ee7SAntonio Huete Jimenez 			ND_PRINT((i == asnlen) ? "%u" : ".%u", GET_U_1(p));
82441c99275SPeter Avalos 		}
82541c99275SPeter Avalos 		break;
82641c99275SPeter Avalos 
82741c99275SPeter Avalos 	case BE_NOSUCHOBJECT:
82841c99275SPeter Avalos 	case BE_NOSUCHINST:
82941c99275SPeter Avalos 	case BE_ENDOFMIBVIEW:
830*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[%s]", Class[EXCEPTIONS].Id[elem->id]);
83141c99275SPeter Avalos 		break;
83241c99275SPeter Avalos 
83341c99275SPeter Avalos 	case BE_PDU:
834*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%s(%u)", Class[CONTEXT].Id[elem->id], elem->asnlen);
83541c99275SPeter Avalos 		break;
83641c99275SPeter Avalos 
83741c99275SPeter Avalos 	case BE_ANY:
838*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[BE_ANY!?]");
83941c99275SPeter Avalos 		break;
84041c99275SPeter Avalos 
84141c99275SPeter Avalos 	default:
842*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[be!?]");
84341c99275SPeter Avalos 		break;
84441c99275SPeter Avalos 	}
84541c99275SPeter Avalos 	return 0;
84641c99275SPeter Avalos 
84741c99275SPeter Avalos trunc:
848*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
84941c99275SPeter Avalos 	return -1;
85041c99275SPeter Avalos }
85141c99275SPeter Avalos 
85241c99275SPeter Avalos #ifdef notdef
85341c99275SPeter Avalos /*
85441c99275SPeter Avalos  * This is a brute force ASN.1 printer: recurses to dump an entire structure.
85541c99275SPeter Avalos  * This will work for any ASN.1 stream, not just an SNMP PDU.
85641c99275SPeter Avalos  *
85741c99275SPeter Avalos  * By adding newlines and spaces at the correct places, this would print in
85841c99275SPeter Avalos  * Rose-Normal-Form.
85941c99275SPeter Avalos  *
86041c99275SPeter Avalos  * This is not currently used.
86141c99275SPeter Avalos  */
86241c99275SPeter Avalos static void
asn1_decode(u_char * p,u_int length)86341c99275SPeter Avalos asn1_decode(u_char *p, u_int length)
86441c99275SPeter Avalos {
86541c99275SPeter Avalos 	struct be elem;
86641c99275SPeter Avalos 	int i = 0;
86741c99275SPeter Avalos 
86841c99275SPeter Avalos 	while (i >= 0 && length > 0) {
869411677aeSAaron LI 		i = asn1_parse(ndo, p, length, &elem);
87041c99275SPeter Avalos 		if (i >= 0) {
871*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" ");
872411677aeSAaron LI 			if (asn1_print(ndo, &elem) < 0)
87341c99275SPeter Avalos 				return;
87441c99275SPeter Avalos 			if (elem.type == BE_SEQ || elem.type == BE_PDU) {
875*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" {");
87641c99275SPeter Avalos 				asn1_decode(elem.data.raw, elem.asnlen);
877*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" }");
87841c99275SPeter Avalos 			}
87941c99275SPeter Avalos 			length -= i;
88041c99275SPeter Avalos 			p += i;
88141c99275SPeter Avalos 		}
88241c99275SPeter Avalos 	}
88341c99275SPeter Avalos }
88441c99275SPeter Avalos #endif
88541c99275SPeter Avalos 
886411677aeSAaron LI #ifdef USE_LIBSMI
88741c99275SPeter Avalos 
88841c99275SPeter Avalos struct smi2be {
88941c99275SPeter Avalos     SmiBasetype basetype;
89041c99275SPeter Avalos     int be;
89141c99275SPeter Avalos };
89241c99275SPeter Avalos 
893411677aeSAaron LI static const struct smi2be smi2betab[] = {
89441c99275SPeter Avalos     { SMI_BASETYPE_INTEGER32,		BE_INT },
89541c99275SPeter Avalos     { SMI_BASETYPE_OCTETSTRING,		BE_STR },
89641c99275SPeter Avalos     { SMI_BASETYPE_OCTETSTRING,		BE_INETADDR },
89741c99275SPeter Avalos     { SMI_BASETYPE_OBJECTIDENTIFIER,	BE_OID },
89841c99275SPeter Avalos     { SMI_BASETYPE_UNSIGNED32,		BE_UNS },
89941c99275SPeter Avalos     { SMI_BASETYPE_INTEGER64,		BE_NONE },
90041c99275SPeter Avalos     { SMI_BASETYPE_UNSIGNED64,		BE_UNS64 },
90141c99275SPeter Avalos     { SMI_BASETYPE_FLOAT32,		BE_NONE },
90241c99275SPeter Avalos     { SMI_BASETYPE_FLOAT64,		BE_NONE },
90341c99275SPeter Avalos     { SMI_BASETYPE_FLOAT128,		BE_NONE },
90441c99275SPeter Avalos     { SMI_BASETYPE_ENUM,		BE_INT },
90541c99275SPeter Avalos     { SMI_BASETYPE_BITS,		BE_STR },
90641c99275SPeter Avalos     { SMI_BASETYPE_UNKNOWN,		BE_NONE }
90741c99275SPeter Avalos };
90841c99275SPeter Avalos 
90941c99275SPeter Avalos static int
smi_decode_oid(netdissect_options * ndo,struct be * elem,unsigned int * oid,unsigned int oidsize,unsigned int * oidlen)910411677aeSAaron LI smi_decode_oid(netdissect_options *ndo,
911411677aeSAaron LI                struct be *elem, unsigned int *oid,
91241c99275SPeter Avalos                unsigned int oidsize, unsigned int *oidlen)
91341c99275SPeter Avalos {
914411677aeSAaron LI 	const u_char *p = (const u_char *)elem->data.raw;
915411677aeSAaron LI 	uint32_t asnlen = elem->asnlen;
916*ed775ee7SAntonio Huete Jimenez 	uint32_t i = asnlen;
917*ed775ee7SAntonio Huete Jimenez 	int o = 0, first = -1;
918411677aeSAaron LI 	unsigned int firstval;
91941c99275SPeter Avalos 
920*ed775ee7SAntonio Huete Jimenez 	for (*oidlen = 0; i != 0; p++, i--) {
921*ed775ee7SAntonio Huete Jimenez 	        o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8);
922*ed775ee7SAntonio Huete Jimenez 		if (GET_U_1(p) & ASN_LONGLEN)
92341c99275SPeter Avalos 		    continue;
92441c99275SPeter Avalos 
92541c99275SPeter Avalos 		/*
92641c99275SPeter Avalos 		 * first subitem encodes two items with 1st*OIDMUX+2nd
92741c99275SPeter Avalos 		 * (see X.690:1997 clause 8.19 for the details)
92841c99275SPeter Avalos 		 */
92941c99275SPeter Avalos 		if (first < 0) {
93041c99275SPeter Avalos 			first = 0;
931411677aeSAaron LI 			firstval = o / OIDMUX;
932411677aeSAaron LI 			if (firstval > 2) firstval = 2;
933411677aeSAaron LI 			o -= firstval * OIDMUX;
93441c99275SPeter Avalos 			if (*oidlen < oidsize) {
935411677aeSAaron LI 			    oid[(*oidlen)++] = firstval;
93641c99275SPeter Avalos 			}
93741c99275SPeter Avalos 		}
93841c99275SPeter Avalos 		if (*oidlen < oidsize) {
93941c99275SPeter Avalos 			oid[(*oidlen)++] = o;
94041c99275SPeter Avalos 		}
94141c99275SPeter Avalos 		o = 0;
94241c99275SPeter Avalos 	}
94341c99275SPeter Avalos 	return 0;
94441c99275SPeter Avalos }
94541c99275SPeter Avalos 
smi_check_type(SmiBasetype basetype,int be)94641c99275SPeter Avalos static int smi_check_type(SmiBasetype basetype, int be)
94741c99275SPeter Avalos {
94841c99275SPeter Avalos     int i;
94941c99275SPeter Avalos 
95041c99275SPeter Avalos     for (i = 0; smi2betab[i].basetype != SMI_BASETYPE_UNKNOWN; i++) {
95141c99275SPeter Avalos 	if (smi2betab[i].basetype == basetype && smi2betab[i].be == be) {
95241c99275SPeter Avalos 	    return 1;
95341c99275SPeter Avalos 	}
95441c99275SPeter Avalos     }
95541c99275SPeter Avalos 
95641c99275SPeter Avalos     return 0;
95741c99275SPeter Avalos }
95841c99275SPeter Avalos 
smi_check_a_range(SmiType * smiType,SmiRange * smiRange,struct be * elem)95941c99275SPeter Avalos static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange,
96041c99275SPeter Avalos 			     struct be *elem)
96141c99275SPeter Avalos {
96241c99275SPeter Avalos     int ok = 1;
96341c99275SPeter Avalos 
96441c99275SPeter Avalos     switch (smiType->basetype) {
96541c99275SPeter Avalos     case SMI_BASETYPE_OBJECTIDENTIFIER:
96641c99275SPeter Avalos     case SMI_BASETYPE_OCTETSTRING:
96741c99275SPeter Avalos 	if (smiRange->minValue.value.unsigned32
96841c99275SPeter Avalos 	    == smiRange->maxValue.value.unsigned32) {
96941c99275SPeter Avalos 	    ok = (elem->asnlen == smiRange->minValue.value.unsigned32);
97041c99275SPeter Avalos 	} else {
97141c99275SPeter Avalos 	    ok = (elem->asnlen >= smiRange->minValue.value.unsigned32
97241c99275SPeter Avalos 		  && elem->asnlen <= smiRange->maxValue.value.unsigned32);
97341c99275SPeter Avalos 	}
97441c99275SPeter Avalos 	break;
97541c99275SPeter Avalos 
97641c99275SPeter Avalos     case SMI_BASETYPE_INTEGER32:
97741c99275SPeter Avalos 	ok = (elem->data.integer >= smiRange->minValue.value.integer32
97841c99275SPeter Avalos 	      && elem->data.integer <= smiRange->maxValue.value.integer32);
97941c99275SPeter Avalos 	break;
98041c99275SPeter Avalos 
98141c99275SPeter Avalos     case SMI_BASETYPE_UNSIGNED32:
98241c99275SPeter Avalos 	ok = (elem->data.uns >= smiRange->minValue.value.unsigned32
98341c99275SPeter Avalos 	      && elem->data.uns <= smiRange->maxValue.value.unsigned32);
98441c99275SPeter Avalos 	break;
98541c99275SPeter Avalos 
98641c99275SPeter Avalos     case SMI_BASETYPE_UNSIGNED64:
98741c99275SPeter Avalos 	/* XXX */
98841c99275SPeter Avalos 	break;
98941c99275SPeter Avalos 
99041c99275SPeter Avalos 	/* case SMI_BASETYPE_INTEGER64: SMIng */
99141c99275SPeter Avalos 	/* case SMI_BASETYPE_FLOAT32: SMIng */
99241c99275SPeter Avalos 	/* case SMI_BASETYPE_FLOAT64: SMIng */
99341c99275SPeter Avalos 	/* case SMI_BASETYPE_FLOAT128: SMIng */
99441c99275SPeter Avalos 
99541c99275SPeter Avalos     case SMI_BASETYPE_ENUM:
99641c99275SPeter Avalos     case SMI_BASETYPE_BITS:
99741c99275SPeter Avalos     case SMI_BASETYPE_UNKNOWN:
99841c99275SPeter Avalos 	ok = 1;
99941c99275SPeter Avalos 	break;
100041c99275SPeter Avalos 
100141c99275SPeter Avalos     default:
100241c99275SPeter Avalos 	ok = 0;
100341c99275SPeter Avalos 	break;
100441c99275SPeter Avalos     }
100541c99275SPeter Avalos 
100641c99275SPeter Avalos     return ok;
100741c99275SPeter Avalos }
100841c99275SPeter Avalos 
smi_check_range(SmiType * smiType,struct be * elem)100941c99275SPeter Avalos static int smi_check_range(SmiType *smiType, struct be *elem)
101041c99275SPeter Avalos {
101141c99275SPeter Avalos         SmiRange *smiRange;
101241c99275SPeter Avalos 	int ok = 1;
101341c99275SPeter Avalos 
101441c99275SPeter Avalos 	for (smiRange = smiGetFirstRange(smiType);
101541c99275SPeter Avalos 	     smiRange;
101641c99275SPeter Avalos 	     smiRange = smiGetNextRange(smiRange)) {
101741c99275SPeter Avalos 
101841c99275SPeter Avalos 	    ok = smi_check_a_range(smiType, smiRange, elem);
101941c99275SPeter Avalos 
102041c99275SPeter Avalos 	    if (ok) {
102141c99275SPeter Avalos 		break;
102241c99275SPeter Avalos 	    }
102341c99275SPeter Avalos 	}
102441c99275SPeter Avalos 
102541c99275SPeter Avalos 	if (ok) {
102641c99275SPeter Avalos 	    SmiType *parentType;
102741c99275SPeter Avalos 	    parentType = smiGetParentType(smiType);
102841c99275SPeter Avalos 	    if (parentType) {
102941c99275SPeter Avalos 		ok = smi_check_range(parentType, elem);
103041c99275SPeter Avalos 	    }
103141c99275SPeter Avalos 	}
103241c99275SPeter Avalos 
103341c99275SPeter Avalos 	return ok;
103441c99275SPeter Avalos }
103541c99275SPeter Avalos 
1036411677aeSAaron LI static SmiNode *
smi_print_variable(netdissect_options * ndo,struct be * elem,int * status)1037411677aeSAaron LI smi_print_variable(netdissect_options *ndo,
1038411677aeSAaron LI                    struct be *elem, int *status)
103941c99275SPeter Avalos {
104041c99275SPeter Avalos 	unsigned int oid[128], oidlen;
104141c99275SPeter Avalos 	SmiNode *smiNode = NULL;
104241c99275SPeter Avalos 	unsigned int i;
104341c99275SPeter Avalos 
1044411677aeSAaron LI 	if (!nd_smi_module_loaded) {
1045411677aeSAaron LI 		*status = asn1_print(ndo, elem);
1046411677aeSAaron LI 		return NULL;
1047411677aeSAaron LI 	}
1048411677aeSAaron LI 	*status = smi_decode_oid(ndo, elem, oid, sizeof(oid) / sizeof(unsigned int),
104941c99275SPeter Avalos 	    &oidlen);
105041c99275SPeter Avalos 	if (*status < 0)
105141c99275SPeter Avalos 		return NULL;
105241c99275SPeter Avalos 	smiNode = smiGetNodeByOID(oidlen, oid);
105341c99275SPeter Avalos 	if (! smiNode) {
1054411677aeSAaron LI 		*status = asn1_print(ndo, elem);
105541c99275SPeter Avalos 		return NULL;
105641c99275SPeter Avalos 	}
1057411677aeSAaron LI 	if (ndo->ndo_vflag) {
1058*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%s::", smiGetNodeModule(smiNode)->name);
105941c99275SPeter Avalos 	}
1060*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%s", smiNode->name);
106141c99275SPeter Avalos 	if (smiNode->oidlen < oidlen) {
106241c99275SPeter Avalos 		for (i = smiNode->oidlen; i < oidlen; i++) {
1063*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(".%u", oid[i]);
106441c99275SPeter Avalos 		}
106541c99275SPeter Avalos 	}
106641c99275SPeter Avalos 	*status = 0;
106741c99275SPeter Avalos 	return smiNode;
106841c99275SPeter Avalos }
106941c99275SPeter Avalos 
107041c99275SPeter Avalos static int
smi_print_value(netdissect_options * ndo,SmiNode * smiNode,u_short pduid,struct be * elem)1071411677aeSAaron LI smi_print_value(netdissect_options *ndo,
1072411677aeSAaron LI                 SmiNode *smiNode, u_short pduid, struct be *elem)
107341c99275SPeter Avalos {
107441c99275SPeter Avalos 	unsigned int i, oid[128], oidlen;
107541c99275SPeter Avalos 	SmiType *smiType;
107641c99275SPeter Avalos 	SmiNamedNumber *nn;
107741c99275SPeter Avalos 	int done = 0;
107841c99275SPeter Avalos 
107941c99275SPeter Avalos 	if (! smiNode || ! (smiNode->nodekind
108041c99275SPeter Avalos 			    & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) {
1081411677aeSAaron LI 	    return asn1_print(ndo, elem);
108241c99275SPeter Avalos 	}
108341c99275SPeter Avalos 
108441c99275SPeter Avalos 	if (elem->type == BE_NOSUCHOBJECT
108541c99275SPeter Avalos 	    || elem->type == BE_NOSUCHINST
108641c99275SPeter Avalos 	    || elem->type == BE_ENDOFMIBVIEW) {
1087411677aeSAaron LI 	    return asn1_print(ndo, elem);
108841c99275SPeter Avalos 	}
108941c99275SPeter Avalos 
109041c99275SPeter Avalos 	if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) {
1091*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("[notNotifyable]");
109241c99275SPeter Avalos 	}
109341c99275SPeter Avalos 
109441c99275SPeter Avalos 	if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) {
1095*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("[notReadable]");
109641c99275SPeter Avalos 	}
109741c99275SPeter Avalos 
109841c99275SPeter Avalos 	if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) {
1099*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("[notWritable]");
110041c99275SPeter Avalos 	}
110141c99275SPeter Avalos 
110241c99275SPeter Avalos 	if (RESPONSE_CLASS(pduid)
110341c99275SPeter Avalos 	    && smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) {
1104*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("[noAccess]");
110541c99275SPeter Avalos 	}
110641c99275SPeter Avalos 
110741c99275SPeter Avalos 	smiType = smiGetNodeType(smiNode);
110841c99275SPeter Avalos 	if (! smiType) {
1109411677aeSAaron LI 	    return asn1_print(ndo, elem);
111041c99275SPeter Avalos 	}
111141c99275SPeter Avalos 
111241c99275SPeter Avalos 	if (! smi_check_type(smiType->basetype, elem->type)) {
1113*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("[wrongType]");
111441c99275SPeter Avalos 	}
111541c99275SPeter Avalos 
111641c99275SPeter Avalos 	if (! smi_check_range(smiType, elem)) {
1117*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("[outOfRange]");
111841c99275SPeter Avalos 	}
111941c99275SPeter Avalos 
112041c99275SPeter Avalos 	/* resolve bits to named bits */
112141c99275SPeter Avalos 
112241c99275SPeter Avalos 	/* check whether instance identifier is valid */
112341c99275SPeter Avalos 
112441c99275SPeter Avalos 	/* apply display hints (integer, octetstring) */
112541c99275SPeter Avalos 
112641c99275SPeter Avalos 	/* convert instance identifier to index type values */
112741c99275SPeter Avalos 
112841c99275SPeter Avalos 	switch (elem->type) {
112941c99275SPeter Avalos 	case BE_OID:
113041c99275SPeter Avalos 	        if (smiType->basetype == SMI_BASETYPE_BITS) {
113141c99275SPeter Avalos 		        /* print bit labels */
113241c99275SPeter Avalos 		} else {
1133411677aeSAaron LI 			if (nd_smi_module_loaded &&
1134411677aeSAaron LI 			    smi_decode_oid(ndo, elem, oid,
113541c99275SPeter Avalos 					   sizeof(oid)/sizeof(unsigned int),
1136411677aeSAaron LI 					   &oidlen) == 0) {
113741c99275SPeter Avalos 				smiNode = smiGetNodeByOID(oidlen, oid);
113841c99275SPeter Avalos 				if (smiNode) {
1139411677aeSAaron LI 				        if (ndo->ndo_vflag) {
1140*ed775ee7SAntonio Huete Jimenez 						ND_PRINT("%s::", smiGetNodeModule(smiNode)->name);
114141c99275SPeter Avalos 					}
1142*ed775ee7SAntonio Huete Jimenez 					ND_PRINT("%s", smiNode->name);
114341c99275SPeter Avalos 					if (smiNode->oidlen < oidlen) {
114441c99275SPeter Avalos 					        for (i = smiNode->oidlen;
114541c99275SPeter Avalos 						     i < oidlen; i++) {
1146*ed775ee7SAntonio Huete Jimenez 						        ND_PRINT(".%u", oid[i]);
114741c99275SPeter Avalos 						}
114841c99275SPeter Avalos 					}
114941c99275SPeter Avalos 					done++;
115041c99275SPeter Avalos 				}
115141c99275SPeter Avalos 			}
1152411677aeSAaron LI 		}
115341c99275SPeter Avalos 		break;
115441c99275SPeter Avalos 
115541c99275SPeter Avalos 	case BE_INT:
115641c99275SPeter Avalos 	        if (smiType->basetype == SMI_BASETYPE_ENUM) {
115741c99275SPeter Avalos 		        for (nn = smiGetFirstNamedNumber(smiType);
115841c99275SPeter Avalos 			     nn;
115941c99275SPeter Avalos 			     nn = smiGetNextNamedNumber(nn)) {
116041c99275SPeter Avalos 			         if (nn->value.value.integer32
116141c99275SPeter Avalos 				     == elem->data.integer) {
1162*ed775ee7SAntonio Huete Jimenez 				         ND_PRINT("%s", nn->name);
1163*ed775ee7SAntonio Huete Jimenez 					 ND_PRINT("(%d)", elem->data.integer);
116441c99275SPeter Avalos 					 done++;
116541c99275SPeter Avalos 					 break;
116641c99275SPeter Avalos 				}
116741c99275SPeter Avalos 			}
116841c99275SPeter Avalos 		}
116941c99275SPeter Avalos 		break;
117041c99275SPeter Avalos 	}
117141c99275SPeter Avalos 
117241c99275SPeter Avalos 	if (! done) {
1173411677aeSAaron LI 		return asn1_print(ndo, elem);
117441c99275SPeter Avalos 	}
117541c99275SPeter Avalos 	return 0;
117641c99275SPeter Avalos }
117741c99275SPeter Avalos #endif
117841c99275SPeter Avalos 
117941c99275SPeter Avalos /*
118041c99275SPeter Avalos  * General SNMP header
118141c99275SPeter Avalos  *	SEQUENCE {
118241c99275SPeter Avalos  *		version INTEGER {version-1(0)},
118341c99275SPeter Avalos  *		community OCTET STRING,
118441c99275SPeter Avalos  *		data ANY	-- PDUs
118541c99275SPeter Avalos  *	}
118641c99275SPeter Avalos  * PDUs for all but Trap: (see rfc1157 from page 15 on)
118741c99275SPeter Avalos  *	SEQUENCE {
118841c99275SPeter Avalos  *		request-id INTEGER,
118941c99275SPeter Avalos  *		error-status INTEGER,
119041c99275SPeter Avalos  *		error-index INTEGER,
119141c99275SPeter Avalos  *		varbindlist SEQUENCE OF
119241c99275SPeter Avalos  *			SEQUENCE {
119341c99275SPeter Avalos  *				name ObjectName,
119441c99275SPeter Avalos  *				value ObjectValue
119541c99275SPeter Avalos  *			}
119641c99275SPeter Avalos  *	}
119741c99275SPeter Avalos  * PDU for Trap:
119841c99275SPeter Avalos  *	SEQUENCE {
119941c99275SPeter Avalos  *		enterprise OBJECT IDENTIFIER,
120041c99275SPeter Avalos  *		agent-addr NetworkAddress,
120141c99275SPeter Avalos  *		generic-trap INTEGER,
120241c99275SPeter Avalos  *		specific-trap INTEGER,
120341c99275SPeter Avalos  *		time-stamp TimeTicks,
120441c99275SPeter Avalos  *		varbindlist SEQUENCE OF
120541c99275SPeter Avalos  *			SEQUENCE {
120641c99275SPeter Avalos  *				name ObjectName,
120741c99275SPeter Avalos  *				value ObjectValue
120841c99275SPeter Avalos  *			}
120941c99275SPeter Avalos  *	}
121041c99275SPeter Avalos  */
121141c99275SPeter Avalos 
121241c99275SPeter Avalos /*
121341c99275SPeter Avalos  * Decode SNMP varBind
121441c99275SPeter Avalos  */
121541c99275SPeter Avalos static void
varbind_print(netdissect_options * ndo,u_short pduid,const u_char * np,u_int length)1216411677aeSAaron LI varbind_print(netdissect_options *ndo,
1217411677aeSAaron LI               u_short pduid, const u_char *np, u_int length)
121841c99275SPeter Avalos {
121941c99275SPeter Avalos 	struct be elem;
122041c99275SPeter Avalos 	int count = 0, ind;
1221411677aeSAaron LI #ifdef USE_LIBSMI
122241c99275SPeter Avalos 	SmiNode *smiNode = NULL;
122341c99275SPeter Avalos #endif
122441c99275SPeter Avalos 	int status;
122541c99275SPeter Avalos 
122641c99275SPeter Avalos 	/* Sequence of varBind */
1227411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
122841c99275SPeter Avalos 		return;
122941c99275SPeter Avalos 	if (elem.type != BE_SEQ) {
1230*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[!SEQ of varbind]");
1231411677aeSAaron LI 		asn1_print(ndo, &elem);
123241c99275SPeter Avalos 		return;
123341c99275SPeter Avalos 	}
123441c99275SPeter Avalos 	if ((u_int)count < length)
1235*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[%d extra after SEQ of varbind]", length - count);
123641c99275SPeter Avalos 	/* descend */
123741c99275SPeter Avalos 	length = elem.asnlen;
1238411677aeSAaron LI 	np = (const u_char *)elem.data.raw;
123941c99275SPeter Avalos 
124041c99275SPeter Avalos 	for (ind = 1; length > 0; ind++) {
124141c99275SPeter Avalos 		const u_char *vbend;
124241c99275SPeter Avalos 		u_int vblength;
124341c99275SPeter Avalos 
1244*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" ");
124541c99275SPeter Avalos 
124641c99275SPeter Avalos 		/* Sequence */
1247411677aeSAaron LI 		if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
124841c99275SPeter Avalos 			return;
124941c99275SPeter Avalos 		if (elem.type != BE_SEQ) {
1250*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[!varbind]");
1251411677aeSAaron LI 			asn1_print(ndo, &elem);
125241c99275SPeter Avalos 			return;
125341c99275SPeter Avalos 		}
125441c99275SPeter Avalos 		vbend = np + count;
125541c99275SPeter Avalos 		vblength = length - count;
125641c99275SPeter Avalos 		/* descend */
125741c99275SPeter Avalos 		length = elem.asnlen;
1258411677aeSAaron LI 		np = (const u_char *)elem.data.raw;
125941c99275SPeter Avalos 
126041c99275SPeter Avalos 		/* objName (OID) */
1261411677aeSAaron LI 		if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
126241c99275SPeter Avalos 			return;
126341c99275SPeter Avalos 		if (elem.type != BE_OID) {
1264*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[objName!=OID]");
1265411677aeSAaron LI 			asn1_print(ndo, &elem);
126641c99275SPeter Avalos 			return;
126741c99275SPeter Avalos 		}
1268411677aeSAaron LI #ifdef USE_LIBSMI
1269411677aeSAaron LI 		smiNode = smi_print_variable(ndo, &elem, &status);
127041c99275SPeter Avalos #else
1271411677aeSAaron LI 		status = asn1_print(ndo, &elem);
127241c99275SPeter Avalos #endif
127341c99275SPeter Avalos 		if (status < 0)
127441c99275SPeter Avalos 			return;
127541c99275SPeter Avalos 		length -= count;
127641c99275SPeter Avalos 		np += count;
127741c99275SPeter Avalos 
127841c99275SPeter Avalos 		if (pduid != GETREQ && pduid != GETNEXTREQ
127941c99275SPeter Avalos 		    && pduid != GETBULKREQ)
1280*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("=");
128141c99275SPeter Avalos 
128241c99275SPeter Avalos 		/* objVal (ANY) */
1283411677aeSAaron LI 		if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
128441c99275SPeter Avalos 			return;
128541c99275SPeter Avalos 		if (pduid == GETREQ || pduid == GETNEXTREQ
128641c99275SPeter Avalos 		    || pduid == GETBULKREQ) {
128741c99275SPeter Avalos 			if (elem.type != BE_NULL) {
1288*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("[objVal!=NULL]");
1289411677aeSAaron LI 				if (asn1_print(ndo, &elem) < 0)
129041c99275SPeter Avalos 					return;
129141c99275SPeter Avalos 			}
129241c99275SPeter Avalos 		} else {
129341c99275SPeter Avalos 		        if (elem.type != BE_NULL) {
1294411677aeSAaron LI #ifdef USE_LIBSMI
1295411677aeSAaron LI 				status = smi_print_value(ndo, smiNode, pduid, &elem);
129641c99275SPeter Avalos #else
1297411677aeSAaron LI 				status = asn1_print(ndo, &elem);
129841c99275SPeter Avalos #endif
129941c99275SPeter Avalos 			}
130041c99275SPeter Avalos 			if (status < 0)
130141c99275SPeter Avalos 				return;
130241c99275SPeter Avalos 		}
130341c99275SPeter Avalos 		length = vblength;
130441c99275SPeter Avalos 		np = vbend;
130541c99275SPeter Avalos 	}
130641c99275SPeter Avalos }
130741c99275SPeter Avalos 
130841c99275SPeter Avalos /*
130941c99275SPeter Avalos  * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest,
131041c99275SPeter Avalos  * GetBulk, Inform, V2Trap, and Report
131141c99275SPeter Avalos  */
131241c99275SPeter Avalos static void
snmppdu_print(netdissect_options * ndo,u_short pduid,const u_char * np,u_int length)1313411677aeSAaron LI snmppdu_print(netdissect_options *ndo,
1314411677aeSAaron LI               u_short pduid, const u_char *np, u_int length)
131541c99275SPeter Avalos {
131641c99275SPeter Avalos 	struct be elem;
1317411677aeSAaron LI 	int count = 0, error_status;
131841c99275SPeter Avalos 
131941c99275SPeter Avalos 	/* reqId (Integer) */
1320411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
132141c99275SPeter Avalos 		return;
132241c99275SPeter Avalos 	if (elem.type != BE_INT) {
1323*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[reqId!=INT]");
1324411677aeSAaron LI 		asn1_print(ndo, &elem);
132541c99275SPeter Avalos 		return;
132641c99275SPeter Avalos 	}
1327411677aeSAaron LI 	if (ndo->ndo_vflag)
1328*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("R=%d ", elem.data.integer);
132941c99275SPeter Avalos 	length -= count;
133041c99275SPeter Avalos 	np += count;
133141c99275SPeter Avalos 
133241c99275SPeter Avalos 	/* errorStatus (Integer) */
1333411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
133441c99275SPeter Avalos 		return;
133541c99275SPeter Avalos 	if (elem.type != BE_INT) {
1336*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[errorStatus!=INT]");
1337411677aeSAaron LI 		asn1_print(ndo, &elem);
133841c99275SPeter Avalos 		return;
133941c99275SPeter Avalos 	}
1340411677aeSAaron LI 	error_status = 0;
134141c99275SPeter Avalos 	if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
134241c99275SPeter Avalos 	    || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
134341c99275SPeter Avalos 	    && elem.data.integer != 0) {
134441c99275SPeter Avalos 		char errbuf[20];
1345*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[errorStatus(%s)!=0]",
1346*ed775ee7SAntonio Huete Jimenez 			DECODE_ErrorStatus(elem.data.integer));
134741c99275SPeter Avalos 	} else if (pduid == GETBULKREQ) {
1348*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" N=%d", elem.data.integer);
134941c99275SPeter Avalos 	} else if (elem.data.integer != 0) {
135041c99275SPeter Avalos 		char errbuf[20];
1351*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" %s", DECODE_ErrorStatus(elem.data.integer));
1352411677aeSAaron LI 		error_status = elem.data.integer;
135341c99275SPeter Avalos 	}
135441c99275SPeter Avalos 	length -= count;
135541c99275SPeter Avalos 	np += count;
135641c99275SPeter Avalos 
135741c99275SPeter Avalos 	/* errorIndex (Integer) */
1358411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
135941c99275SPeter Avalos 		return;
136041c99275SPeter Avalos 	if (elem.type != BE_INT) {
1361*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[errorIndex!=INT]");
1362411677aeSAaron LI 		asn1_print(ndo, &elem);
136341c99275SPeter Avalos 		return;
136441c99275SPeter Avalos 	}
136541c99275SPeter Avalos 	if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
136641c99275SPeter Avalos 	    || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
136741c99275SPeter Avalos 	    && elem.data.integer != 0)
1368*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[errorIndex(%d)!=0]", elem.data.integer);
136941c99275SPeter Avalos 	else if (pduid == GETBULKREQ)
1370*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" M=%d", elem.data.integer);
137141c99275SPeter Avalos 	else if (elem.data.integer != 0) {
1372411677aeSAaron LI 		if (!error_status)
1373*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[errorIndex(%d) w/o errorStatus]", elem.data.integer);
1374411677aeSAaron LI 		else
1375*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("@%d", elem.data.integer);
1376411677aeSAaron LI 	} else if (error_status) {
1377*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[errorIndex==0]");
137841c99275SPeter Avalos 	}
137941c99275SPeter Avalos 	length -= count;
138041c99275SPeter Avalos 	np += count;
138141c99275SPeter Avalos 
1382411677aeSAaron LI 	varbind_print(ndo, pduid, np, length);
138341c99275SPeter Avalos }
138441c99275SPeter Avalos 
138541c99275SPeter Avalos /*
138641c99275SPeter Avalos  * Decode SNMP Trap PDU
138741c99275SPeter Avalos  */
138841c99275SPeter Avalos static void
trappdu_print(netdissect_options * ndo,const u_char * np,u_int length)1389411677aeSAaron LI trappdu_print(netdissect_options *ndo,
1390411677aeSAaron LI               const u_char *np, u_int length)
139141c99275SPeter Avalos {
139241c99275SPeter Avalos 	struct be elem;
139341c99275SPeter Avalos 	int count = 0, generic;
139441c99275SPeter Avalos 
1395*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" ");
139641c99275SPeter Avalos 
139741c99275SPeter Avalos 	/* enterprise (oid) */
1398411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
139941c99275SPeter Avalos 		return;
140041c99275SPeter Avalos 	if (elem.type != BE_OID) {
1401*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[enterprise!=OID]");
1402411677aeSAaron LI 		asn1_print(ndo, &elem);
140341c99275SPeter Avalos 		return;
140441c99275SPeter Avalos 	}
1405411677aeSAaron LI 	if (asn1_print(ndo, &elem) < 0)
140641c99275SPeter Avalos 		return;
140741c99275SPeter Avalos 	length -= count;
140841c99275SPeter Avalos 	np += count;
140941c99275SPeter Avalos 
1410*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" ");
141141c99275SPeter Avalos 
141241c99275SPeter Avalos 	/* agent-addr (inetaddr) */
1413411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
141441c99275SPeter Avalos 		return;
141541c99275SPeter Avalos 	if (elem.type != BE_INETADDR) {
1416*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[agent-addr!=INETADDR]");
1417411677aeSAaron LI 		asn1_print(ndo, &elem);
141841c99275SPeter Avalos 		return;
141941c99275SPeter Avalos 	}
1420411677aeSAaron LI 	if (asn1_print(ndo, &elem) < 0)
142141c99275SPeter Avalos 		return;
142241c99275SPeter Avalos 	length -= count;
142341c99275SPeter Avalos 	np += count;
142441c99275SPeter Avalos 
142541c99275SPeter Avalos 	/* generic-trap (Integer) */
1426411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
142741c99275SPeter Avalos 		return;
142841c99275SPeter Avalos 	if (elem.type != BE_INT) {
1429*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[generic-trap!=INT]");
1430411677aeSAaron LI 		asn1_print(ndo, &elem);
143141c99275SPeter Avalos 		return;
143241c99275SPeter Avalos 	}
143341c99275SPeter Avalos 	generic = elem.data.integer;
143441c99275SPeter Avalos 	{
143541c99275SPeter Avalos 		char buf[20];
1436*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" %s", DECODE_GenericTrap(generic));
143741c99275SPeter Avalos 	}
143841c99275SPeter Avalos 	length -= count;
143941c99275SPeter Avalos 	np += count;
144041c99275SPeter Avalos 
144141c99275SPeter Avalos 	/* specific-trap (Integer) */
1442411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
144341c99275SPeter Avalos 		return;
144441c99275SPeter Avalos 	if (elem.type != BE_INT) {
1445*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[specific-trap!=INT]");
1446411677aeSAaron LI 		asn1_print(ndo, &elem);
144741c99275SPeter Avalos 		return;
144841c99275SPeter Avalos 	}
144941c99275SPeter Avalos 	if (generic != GT_ENTERPRISE) {
145041c99275SPeter Avalos 		if (elem.data.integer != 0)
1451*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[specific-trap(%d)!=0]", elem.data.integer);
145241c99275SPeter Avalos 	} else
1453*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" s=%d", elem.data.integer);
145441c99275SPeter Avalos 	length -= count;
145541c99275SPeter Avalos 	np += count;
145641c99275SPeter Avalos 
1457*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" ");
145841c99275SPeter Avalos 
145941c99275SPeter Avalos 	/* time-stamp (TimeTicks) */
1460411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
146141c99275SPeter Avalos 		return;
146241c99275SPeter Avalos 	if (elem.type != BE_UNS) {			/* XXX */
1463*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[time-stamp!=TIMETICKS]");
1464411677aeSAaron LI 		asn1_print(ndo, &elem);
146541c99275SPeter Avalos 		return;
146641c99275SPeter Avalos 	}
1467411677aeSAaron LI 	if (asn1_print(ndo, &elem) < 0)
146841c99275SPeter Avalos 		return;
146941c99275SPeter Avalos 	length -= count;
147041c99275SPeter Avalos 	np += count;
147141c99275SPeter Avalos 
1472411677aeSAaron LI 	varbind_print(ndo, TRAP, np, length);
147341c99275SPeter Avalos }
147441c99275SPeter Avalos 
147541c99275SPeter Avalos /*
147641c99275SPeter Avalos  * Decode arbitrary SNMP PDUs.
147741c99275SPeter Avalos  */
147841c99275SPeter Avalos static void
pdu_print(netdissect_options * ndo,const u_char * np,u_int length,int version)1479411677aeSAaron LI pdu_print(netdissect_options *ndo,
1480411677aeSAaron LI           const u_char *np, u_int length, int version)
148141c99275SPeter Avalos {
148241c99275SPeter Avalos 	struct be pdu;
148341c99275SPeter Avalos 	int count = 0;
148441c99275SPeter Avalos 
148541c99275SPeter Avalos 	/* PDU (Context) */
1486411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &pdu)) < 0)
148741c99275SPeter Avalos 		return;
148841c99275SPeter Avalos 	if (pdu.type != BE_PDU) {
1489*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[no PDU]");
149041c99275SPeter Avalos 		return;
149141c99275SPeter Avalos 	}
149241c99275SPeter Avalos 	if ((u_int)count < length)
1493*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[%d extra after PDU]", length - count);
1494411677aeSAaron LI 	if (ndo->ndo_vflag) {
1495*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("{ ");
149641c99275SPeter Avalos 	}
1497411677aeSAaron LI 	if (asn1_print(ndo, &pdu) < 0)
149841c99275SPeter Avalos 		return;
1499*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" ");
150041c99275SPeter Avalos 	/* descend into PDU */
150141c99275SPeter Avalos 	length = pdu.asnlen;
1502411677aeSAaron LI 	np = (const u_char *)pdu.data.raw;
150341c99275SPeter Avalos 
150441c99275SPeter Avalos 	if (version == SNMP_VERSION_1 &&
150541c99275SPeter Avalos 	    (pdu.id == GETBULKREQ || pdu.id == INFORMREQ ||
150641c99275SPeter Avalos 	     pdu.id == V2TRAP || pdu.id == REPORT)) {
1507*ed775ee7SAntonio Huete Jimenez 	        ND_PRINT("[v2 PDU in v1 message]");
150841c99275SPeter Avalos 		return;
150941c99275SPeter Avalos 	}
151041c99275SPeter Avalos 
151141c99275SPeter Avalos 	if (version == SNMP_VERSION_2 && pdu.id == TRAP) {
1512*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[v1 PDU in v2 message]");
151341c99275SPeter Avalos 		return;
151441c99275SPeter Avalos 	}
151541c99275SPeter Avalos 
151641c99275SPeter Avalos 	switch (pdu.id) {
151741c99275SPeter Avalos 	case TRAP:
1518411677aeSAaron LI 		trappdu_print(ndo, np, length);
151941c99275SPeter Avalos 		break;
152041c99275SPeter Avalos 	case GETREQ:
152141c99275SPeter Avalos 	case GETNEXTREQ:
152241c99275SPeter Avalos 	case GETRESP:
152341c99275SPeter Avalos 	case SETREQ:
152441c99275SPeter Avalos 	case GETBULKREQ:
152541c99275SPeter Avalos 	case INFORMREQ:
152641c99275SPeter Avalos 	case V2TRAP:
152741c99275SPeter Avalos 	case REPORT:
1528411677aeSAaron LI 		snmppdu_print(ndo, pdu.id, np, length);
152941c99275SPeter Avalos 		break;
153041c99275SPeter Avalos 	}
153141c99275SPeter Avalos 
1532411677aeSAaron LI 	if (ndo->ndo_vflag) {
1533*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" } ");
153441c99275SPeter Avalos 	}
153541c99275SPeter Avalos }
153641c99275SPeter Avalos 
153741c99275SPeter Avalos /*
153841c99275SPeter Avalos  * Decode a scoped SNMP PDU.
153941c99275SPeter Avalos  */
154041c99275SPeter Avalos static void
scopedpdu_print(netdissect_options * ndo,const u_char * np,u_int length,int version)1541411677aeSAaron LI scopedpdu_print(netdissect_options *ndo,
1542411677aeSAaron LI                 const u_char *np, u_int length, int version)
154341c99275SPeter Avalos {
154441c99275SPeter Avalos 	struct be elem;
1545411677aeSAaron LI 	int count = 0;
154641c99275SPeter Avalos 
154741c99275SPeter Avalos 	/* Sequence */
1548411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
154941c99275SPeter Avalos 		return;
155041c99275SPeter Avalos 	if (elem.type != BE_SEQ) {
1551*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[!scoped PDU]");
1552411677aeSAaron LI 		asn1_print(ndo, &elem);
155341c99275SPeter Avalos 		return;
155441c99275SPeter Avalos 	}
155541c99275SPeter Avalos 	length = elem.asnlen;
1556411677aeSAaron LI 	np = (const u_char *)elem.data.raw;
155741c99275SPeter Avalos 
155841c99275SPeter Avalos 	/* contextEngineID (OCTET STRING) */
1559411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
156041c99275SPeter Avalos 		return;
156141c99275SPeter Avalos 	if (elem.type != BE_STR) {
1562*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[contextEngineID!=STR]");
1563411677aeSAaron LI 		asn1_print(ndo, &elem);
156441c99275SPeter Avalos 		return;
156541c99275SPeter Avalos 	}
156641c99275SPeter Avalos 	length -= count;
156741c99275SPeter Avalos 	np += count;
156841c99275SPeter Avalos 
1569*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("E=");
1570411677aeSAaron LI 	if (asn1_print_octets(ndo, &elem) == -1)
1571411677aeSAaron LI 		return;
1572*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" ");
157341c99275SPeter Avalos 
157441c99275SPeter Avalos 	/* contextName (OCTET STRING) */
1575411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
157641c99275SPeter Avalos 		return;
157741c99275SPeter Avalos 	if (elem.type != BE_STR) {
1578*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[contextName!=STR]");
1579411677aeSAaron LI 		asn1_print(ndo, &elem);
158041c99275SPeter Avalos 		return;
158141c99275SPeter Avalos 	}
158241c99275SPeter Avalos 	length -= count;
158341c99275SPeter Avalos 	np += count;
158441c99275SPeter Avalos 
1585*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("C=");
1586411677aeSAaron LI 	if (asn1_print_string(ndo, &elem) == -1)
1587411677aeSAaron LI 		return;
1588*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" ");
158941c99275SPeter Avalos 
1590411677aeSAaron LI 	pdu_print(ndo, np, length, version);
159141c99275SPeter Avalos }
159241c99275SPeter Avalos 
159341c99275SPeter Avalos /*
159441c99275SPeter Avalos  * Decode SNMP Community Header (SNMPv1 and SNMPv2c)
159541c99275SPeter Avalos  */
159641c99275SPeter Avalos static void
community_print(netdissect_options * ndo,const u_char * np,u_int length,int version)1597411677aeSAaron LI community_print(netdissect_options *ndo,
1598411677aeSAaron LI                 const u_char *np, u_int length, int version)
159941c99275SPeter Avalos {
160041c99275SPeter Avalos 	struct be elem;
160141c99275SPeter Avalos 	int count = 0;
160241c99275SPeter Avalos 
160341c99275SPeter Avalos 	/* Community (String) */
1604411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
160541c99275SPeter Avalos 		return;
160641c99275SPeter Avalos 	if (elem.type != BE_STR) {
1607*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[comm!=STR]");
1608411677aeSAaron LI 		asn1_print(ndo, &elem);
160941c99275SPeter Avalos 		return;
161041c99275SPeter Avalos 	}
161141c99275SPeter Avalos 	/* default community */
161241c99275SPeter Avalos 	if (!(elem.asnlen == sizeof(DEF_COMMUNITY) - 1 &&
1613411677aeSAaron LI 	    strncmp((const char *)elem.data.str, DEF_COMMUNITY,
1614411677aeSAaron LI 	            sizeof(DEF_COMMUNITY) - 1) == 0)) {
161541c99275SPeter Avalos 		/* ! "public" */
1616*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("C=");
1617411677aeSAaron LI 		if (asn1_print_string(ndo, &elem) == -1)
1618411677aeSAaron LI 			return;
1619*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" ");
1620411677aeSAaron LI 	}
162141c99275SPeter Avalos 	length -= count;
162241c99275SPeter Avalos 	np += count;
162341c99275SPeter Avalos 
1624411677aeSAaron LI 	pdu_print(ndo, np, length, version);
162541c99275SPeter Avalos }
162641c99275SPeter Avalos 
162741c99275SPeter Avalos /*
162841c99275SPeter Avalos  * Decode SNMPv3 User-based Security Message Header (SNMPv3)
162941c99275SPeter Avalos  */
163041c99275SPeter Avalos static void
usm_print(netdissect_options * ndo,const u_char * np,u_int length)1631411677aeSAaron LI usm_print(netdissect_options *ndo,
1632411677aeSAaron LI           const u_char *np, u_int length)
163341c99275SPeter Avalos {
163441c99275SPeter Avalos         struct be elem;
163541c99275SPeter Avalos 	int count = 0;
163641c99275SPeter Avalos 
163741c99275SPeter Avalos 	/* Sequence */
1638411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
163941c99275SPeter Avalos 		return;
164041c99275SPeter Avalos 	if (elem.type != BE_SEQ) {
1641*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[!usm]");
1642411677aeSAaron LI 		asn1_print(ndo, &elem);
164341c99275SPeter Avalos 		return;
164441c99275SPeter Avalos 	}
164541c99275SPeter Avalos 	length = elem.asnlen;
1646411677aeSAaron LI 	np = (const u_char *)elem.data.raw;
164741c99275SPeter Avalos 
164841c99275SPeter Avalos 	/* msgAuthoritativeEngineID (OCTET STRING) */
1649411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
165041c99275SPeter Avalos 		return;
165141c99275SPeter Avalos 	if (elem.type != BE_STR) {
1652*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgAuthoritativeEngineID!=STR]");
1653411677aeSAaron LI 		asn1_print(ndo, &elem);
165441c99275SPeter Avalos 		return;
165541c99275SPeter Avalos 	}
165641c99275SPeter Avalos 	length -= count;
165741c99275SPeter Avalos 	np += count;
165841c99275SPeter Avalos 
165941c99275SPeter Avalos 	/* msgAuthoritativeEngineBoots (INTEGER) */
1660411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
166141c99275SPeter Avalos 		return;
166241c99275SPeter Avalos 	if (elem.type != BE_INT) {
1663*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgAuthoritativeEngineBoots!=INT]");
1664411677aeSAaron LI 		asn1_print(ndo, &elem);
166541c99275SPeter Avalos 		return;
166641c99275SPeter Avalos 	}
1667411677aeSAaron LI 	if (ndo->ndo_vflag)
1668*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("B=%d ", elem.data.integer);
166941c99275SPeter Avalos 	length -= count;
167041c99275SPeter Avalos 	np += count;
167141c99275SPeter Avalos 
167241c99275SPeter Avalos 	/* msgAuthoritativeEngineTime (INTEGER) */
1673411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
167441c99275SPeter Avalos 		return;
167541c99275SPeter Avalos 	if (elem.type != BE_INT) {
1676*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgAuthoritativeEngineTime!=INT]");
1677411677aeSAaron LI 		asn1_print(ndo, &elem);
167841c99275SPeter Avalos 		return;
167941c99275SPeter Avalos 	}
1680411677aeSAaron LI 	if (ndo->ndo_vflag)
1681*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("T=%d ", elem.data.integer);
168241c99275SPeter Avalos 	length -= count;
168341c99275SPeter Avalos 	np += count;
168441c99275SPeter Avalos 
168541c99275SPeter Avalos 	/* msgUserName (OCTET STRING) */
1686411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
168741c99275SPeter Avalos 		return;
168841c99275SPeter Avalos 	if (elem.type != BE_STR) {
1689*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgUserName!=STR]");
1690411677aeSAaron LI 		asn1_print(ndo, &elem);
169141c99275SPeter Avalos 		return;
169241c99275SPeter Avalos 	}
169341c99275SPeter Avalos 	length -= count;
169441c99275SPeter Avalos         np += count;
169541c99275SPeter Avalos 
1696*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("U=");
1697411677aeSAaron LI 	if (asn1_print_string(ndo, &elem) == -1)
1698411677aeSAaron LI 		return;
1699*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" ");
170041c99275SPeter Avalos 
170141c99275SPeter Avalos 	/* msgAuthenticationParameters (OCTET STRING) */
1702411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
170341c99275SPeter Avalos 		return;
170441c99275SPeter Avalos 	if (elem.type != BE_STR) {
1705*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgAuthenticationParameters!=STR]");
1706411677aeSAaron LI 		asn1_print(ndo, &elem);
170741c99275SPeter Avalos 		return;
170841c99275SPeter Avalos 	}
170941c99275SPeter Avalos 	length -= count;
171041c99275SPeter Avalos         np += count;
171141c99275SPeter Avalos 
171241c99275SPeter Avalos 	/* msgPrivacyParameters (OCTET STRING) */
1713411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
171441c99275SPeter Avalos 		return;
171541c99275SPeter Avalos 	if (elem.type != BE_STR) {
1716*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgPrivacyParameters!=STR]");
1717411677aeSAaron LI 		asn1_print(ndo, &elem);
171841c99275SPeter Avalos 		return;
171941c99275SPeter Avalos 	}
172041c99275SPeter Avalos 	length -= count;
172141c99275SPeter Avalos         np += count;
172241c99275SPeter Avalos 
172341c99275SPeter Avalos 	if ((u_int)count < length)
1724*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[%d extra after usm SEQ]", length - count);
172541c99275SPeter Avalos }
172641c99275SPeter Avalos 
172741c99275SPeter Avalos /*
172841c99275SPeter Avalos  * Decode SNMPv3 Message Header (SNMPv3)
172941c99275SPeter Avalos  */
173041c99275SPeter Avalos static void
v3msg_print(netdissect_options * ndo,const u_char * np,u_int length)1731411677aeSAaron LI v3msg_print(netdissect_options *ndo,
1732411677aeSAaron LI             const u_char *np, u_int length)
173341c99275SPeter Avalos {
173441c99275SPeter Avalos 	struct be elem;
173541c99275SPeter Avalos 	int count = 0;
173641c99275SPeter Avalos 	u_char flags;
173741c99275SPeter Avalos 	int model;
173841c99275SPeter Avalos 	const u_char *xnp = np;
173941c99275SPeter Avalos 	int xlength = length;
174041c99275SPeter Avalos 
174141c99275SPeter Avalos 	/* Sequence */
1742411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
174341c99275SPeter Avalos 		return;
174441c99275SPeter Avalos 	if (elem.type != BE_SEQ) {
1745*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[!message]");
1746411677aeSAaron LI 		asn1_print(ndo, &elem);
174741c99275SPeter Avalos 		return;
174841c99275SPeter Avalos 	}
174941c99275SPeter Avalos 	length = elem.asnlen;
1750411677aeSAaron LI 	np = (const u_char *)elem.data.raw;
175141c99275SPeter Avalos 
1752411677aeSAaron LI 	if (ndo->ndo_vflag) {
1753*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("{ ");
175441c99275SPeter Avalos 	}
175541c99275SPeter Avalos 
175641c99275SPeter Avalos 	/* msgID (INTEGER) */
1757411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
175841c99275SPeter Avalos 		return;
175941c99275SPeter Avalos 	if (elem.type != BE_INT) {
1760*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgID!=INT]");
1761411677aeSAaron LI 		asn1_print(ndo, &elem);
176241c99275SPeter Avalos 		return;
176341c99275SPeter Avalos 	}
176441c99275SPeter Avalos 	length -= count;
176541c99275SPeter Avalos 	np += count;
176641c99275SPeter Avalos 
176741c99275SPeter Avalos 	/* msgMaxSize (INTEGER) */
1768411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
176941c99275SPeter Avalos 		return;
177041c99275SPeter Avalos 	if (elem.type != BE_INT) {
1771*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgMaxSize!=INT]");
1772411677aeSAaron LI 		asn1_print(ndo, &elem);
177341c99275SPeter Avalos 		return;
177441c99275SPeter Avalos 	}
177541c99275SPeter Avalos 	length -= count;
177641c99275SPeter Avalos 	np += count;
177741c99275SPeter Avalos 
177841c99275SPeter Avalos 	/* msgFlags (OCTET STRING) */
1779411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
178041c99275SPeter Avalos 		return;
178141c99275SPeter Avalos 	if (elem.type != BE_STR) {
1782*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgFlags!=STR]");
1783411677aeSAaron LI 		asn1_print(ndo, &elem);
178441c99275SPeter Avalos 		return;
178541c99275SPeter Avalos 	}
178641c99275SPeter Avalos 	if (elem.asnlen != 1) {
1787*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgFlags size %d]", elem.asnlen);
178841c99275SPeter Avalos 		return;
178941c99275SPeter Avalos 	}
1790*ed775ee7SAntonio Huete Jimenez 	flags = GET_U_1(elem.data.str);
179141c99275SPeter Avalos 	if (flags != 0x00 && flags != 0x01 && flags != 0x03
179241c99275SPeter Avalos 	    && flags != 0x04 && flags != 0x05 && flags != 0x07) {
1793*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgFlags=0x%02X]", flags);
179441c99275SPeter Avalos 		return;
179541c99275SPeter Avalos 	}
179641c99275SPeter Avalos 	length -= count;
179741c99275SPeter Avalos 	np += count;
179841c99275SPeter Avalos 
1799*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("F=%s%s%s ",
1800411677aeSAaron LI 	          flags & 0x01 ? "a" : "",
1801411677aeSAaron LI 	          flags & 0x02 ? "p" : "",
1802*ed775ee7SAntonio Huete Jimenez 	          flags & 0x04 ? "r" : "");
180341c99275SPeter Avalos 
180441c99275SPeter Avalos 	/* msgSecurityModel (INTEGER) */
1805411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
180641c99275SPeter Avalos 		return;
180741c99275SPeter Avalos 	if (elem.type != BE_INT) {
1808*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgSecurityModel!=INT]");
1809411677aeSAaron LI 		asn1_print(ndo, &elem);
181041c99275SPeter Avalos 		return;
181141c99275SPeter Avalos 	}
181241c99275SPeter Avalos 	model = elem.data.integer;
181341c99275SPeter Avalos 	length -= count;
181441c99275SPeter Avalos 	np += count;
181541c99275SPeter Avalos 
181641c99275SPeter Avalos 	if ((u_int)count < length)
1817*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[%d extra after message SEQ]", length - count);
181841c99275SPeter Avalos 
1819411677aeSAaron LI 	if (ndo->ndo_vflag) {
1820*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("} ");
182141c99275SPeter Avalos 	}
182241c99275SPeter Avalos 
182341c99275SPeter Avalos 	if (model == 3) {
1824411677aeSAaron LI 	    if (ndo->ndo_vflag) {
1825*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("{ USM ");
182641c99275SPeter Avalos 	    }
182741c99275SPeter Avalos 	} else {
1828*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("[security model %d]", model);
182941c99275SPeter Avalos             return;
183041c99275SPeter Avalos 	}
183141c99275SPeter Avalos 
183241c99275SPeter Avalos 	np = xnp + (np - xnp);
183341c99275SPeter Avalos 	length = xlength - (np - xnp);
183441c99275SPeter Avalos 
183541c99275SPeter Avalos 	/* msgSecurityParameters (OCTET STRING) */
1836411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
183741c99275SPeter Avalos 		return;
183841c99275SPeter Avalos 	if (elem.type != BE_STR) {
1839*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[msgSecurityParameters!=STR]");
1840411677aeSAaron LI 		asn1_print(ndo, &elem);
184141c99275SPeter Avalos 		return;
184241c99275SPeter Avalos 	}
184341c99275SPeter Avalos 	length -= count;
184441c99275SPeter Avalos 	np += count;
184541c99275SPeter Avalos 
184641c99275SPeter Avalos 	if (model == 3) {
1847411677aeSAaron LI 	    usm_print(ndo, elem.data.str, elem.asnlen);
1848411677aeSAaron LI 	    if (ndo->ndo_vflag) {
1849*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("} ");
185041c99275SPeter Avalos 	    }
185141c99275SPeter Avalos 	}
185241c99275SPeter Avalos 
1853411677aeSAaron LI 	if (ndo->ndo_vflag) {
1854*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("{ ScopedPDU ");
185541c99275SPeter Avalos 	}
185641c99275SPeter Avalos 
1857411677aeSAaron LI 	scopedpdu_print(ndo, np, length, 3);
185841c99275SPeter Avalos 
1859411677aeSAaron LI 	if (ndo->ndo_vflag) {
1860*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("} ");
186141c99275SPeter Avalos 	}
186241c99275SPeter Avalos }
186341c99275SPeter Avalos 
186441c99275SPeter Avalos /*
186541c99275SPeter Avalos  * Decode SNMP header and pass on to PDU printing routines
186641c99275SPeter Avalos  */
186741c99275SPeter Avalos void
snmp_print(netdissect_options * ndo,const u_char * np,u_int length)1868411677aeSAaron LI snmp_print(netdissect_options *ndo,
1869411677aeSAaron LI            const u_char *np, u_int length)
187041c99275SPeter Avalos {
187141c99275SPeter Avalos 	struct be elem;
187241c99275SPeter Avalos 	int count = 0;
187341c99275SPeter Avalos 	int version = 0;
187441c99275SPeter Avalos 
1875*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "snmp";
1876*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" ");
187741c99275SPeter Avalos 
187841c99275SPeter Avalos 	/* initial Sequence */
1879411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
188041c99275SPeter Avalos 		return;
188141c99275SPeter Avalos 	if (elem.type != BE_SEQ) {
1882*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[!init SEQ]");
1883411677aeSAaron LI 		asn1_print(ndo, &elem);
188441c99275SPeter Avalos 		return;
188541c99275SPeter Avalos 	}
188641c99275SPeter Avalos 	if ((u_int)count < length)
1887*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[%d extra after iSEQ]", length - count);
188841c99275SPeter Avalos 	/* descend */
188941c99275SPeter Avalos 	length = elem.asnlen;
1890411677aeSAaron LI 	np = (const u_char *)elem.data.raw;
189141c99275SPeter Avalos 
189241c99275SPeter Avalos 	/* Version (INTEGER) */
1893411677aeSAaron LI 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
189441c99275SPeter Avalos 		return;
189541c99275SPeter Avalos 	if (elem.type != BE_INT) {
1896*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[version!=INT]");
1897411677aeSAaron LI 		asn1_print(ndo, &elem);
189841c99275SPeter Avalos 		return;
189941c99275SPeter Avalos 	}
190041c99275SPeter Avalos 
190141c99275SPeter Avalos 	switch (elem.data.integer) {
190241c99275SPeter Avalos 	case SNMP_VERSION_1:
190341c99275SPeter Avalos 	case SNMP_VERSION_2:
190441c99275SPeter Avalos 	case SNMP_VERSION_3:
1905411677aeSAaron LI 		if (ndo->ndo_vflag)
1906*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("{ %s ", SnmpVersion[elem.data.integer]);
190741c99275SPeter Avalos 		break;
190841c99275SPeter Avalos 	default:
1909*ed775ee7SAntonio Huete Jimenez 	        ND_PRINT("SNMP [version = %d]", elem.data.integer);
191041c99275SPeter Avalos 		return;
191141c99275SPeter Avalos 	}
191241c99275SPeter Avalos 	version = elem.data.integer;
191341c99275SPeter Avalos 	length -= count;
191441c99275SPeter Avalos 	np += count;
191541c99275SPeter Avalos 
191641c99275SPeter Avalos 	switch (version) {
191741c99275SPeter Avalos 	case SNMP_VERSION_1:
191841c99275SPeter Avalos         case SNMP_VERSION_2:
1919411677aeSAaron LI 		community_print(ndo, np, length, version);
192041c99275SPeter Avalos 		break;
192141c99275SPeter Avalos 	case SNMP_VERSION_3:
1922411677aeSAaron LI 		v3msg_print(ndo, np, length);
192341c99275SPeter Avalos 		break;
192441c99275SPeter Avalos 	default:
1925*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[version = %d]", elem.data.integer);
192641c99275SPeter Avalos 		break;
192741c99275SPeter Avalos 	}
192841c99275SPeter Avalos 
1929411677aeSAaron LI 	if (ndo->ndo_vflag) {
1930*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("} ");
193141c99275SPeter Avalos 	}
193241c99275SPeter Avalos }
1933