xref: /minix3/external/bsd/tcpdump/dist/print-snmp.c (revision b636d99d91c3d54204248f643c14627405d4afd1)
1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3*b636d99dSDavid van Moolenbroek  *     John Robert LoVerso. All rights reserved.
4*b636d99dSDavid van Moolenbroek  *
5*b636d99dSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
6*b636d99dSDavid van Moolenbroek  * modification, are permitted provided that the following conditions
7*b636d99dSDavid van Moolenbroek  * are met:
8*b636d99dSDavid van Moolenbroek  *
9*b636d99dSDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
10*b636d99dSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
11*b636d99dSDavid van Moolenbroek  *
12*b636d99dSDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
13*b636d99dSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
14*b636d99dSDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
15*b636d99dSDavid van Moolenbroek  *
16*b636d99dSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*b636d99dSDavid van Moolenbroek  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*b636d99dSDavid van Moolenbroek  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*b636d99dSDavid van Moolenbroek  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*b636d99dSDavid van Moolenbroek  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*b636d99dSDavid van Moolenbroek  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*b636d99dSDavid van Moolenbroek  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*b636d99dSDavid van Moolenbroek  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*b636d99dSDavid van Moolenbroek  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*b636d99dSDavid van Moolenbroek  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*b636d99dSDavid van Moolenbroek  *
27*b636d99dSDavid van Moolenbroek  *
28*b636d99dSDavid van Moolenbroek  * This implementation has been influenced by the CMU SNMP release,
29*b636d99dSDavid van Moolenbroek  * by Steve Waldbusser.  However, this shares no code with that system.
30*b636d99dSDavid van Moolenbroek  * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_.
31*b636d99dSDavid van Moolenbroek  * Earlier forms of this implementation were derived and/or inspired by an
32*b636d99dSDavid van Moolenbroek  * awk script originally written by C. Philip Wood of LANL (but later
33*b636d99dSDavid van Moolenbroek  * heavily modified by John Robert LoVerso).  The copyright notice for
34*b636d99dSDavid van Moolenbroek  * that work is preserved below, even though it may not rightly apply
35*b636d99dSDavid van Moolenbroek  * to this file.
36*b636d99dSDavid van Moolenbroek  *
37*b636d99dSDavid van Moolenbroek  * Support for SNMPv2c/SNMPv3 and the ability to link the module against
38*b636d99dSDavid van Moolenbroek  * the libsmi was added by J. Schoenwaelder, Copyright (c) 1999.
39*b636d99dSDavid van Moolenbroek  *
40*b636d99dSDavid van Moolenbroek  * This started out as a very simple program, but the incremental decoding
41*b636d99dSDavid van Moolenbroek  * (into the BE structure) complicated things.
42*b636d99dSDavid van Moolenbroek  *
43*b636d99dSDavid van Moolenbroek  #			Los Alamos National Laboratory
44*b636d99dSDavid van Moolenbroek  #
45*b636d99dSDavid van Moolenbroek  #	Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
46*b636d99dSDavid van Moolenbroek  #	This software was produced under a U.S. Government contract
47*b636d99dSDavid van Moolenbroek  #	(W-7405-ENG-36) by Los Alamos National Laboratory, which is
48*b636d99dSDavid van Moolenbroek  #	operated by the	University of California for the U.S. Department
49*b636d99dSDavid van Moolenbroek  #	of Energy.  The U.S. Government is licensed to use, reproduce,
50*b636d99dSDavid van Moolenbroek  #	and distribute this software.  Permission is granted to the
51*b636d99dSDavid van Moolenbroek  #	public to copy and use this software without charge, provided
52*b636d99dSDavid van Moolenbroek  #	that this Notice and any statement of authorship are reproduced
53*b636d99dSDavid van Moolenbroek  #	on all copies.  Neither the Government nor the University makes
54*b636d99dSDavid van Moolenbroek  #	any warranty, express or implied, or assumes any liability or
55*b636d99dSDavid van Moolenbroek  #	responsibility for the use of this software.
56*b636d99dSDavid van Moolenbroek  #	@(#)snmp.awk.x	1.1 (LANL) 1/15/90
57*b636d99dSDavid van Moolenbroek  */
58*b636d99dSDavid van Moolenbroek 
59*b636d99dSDavid van Moolenbroek #include <sys/cdefs.h>
60*b636d99dSDavid van Moolenbroek #ifndef lint
61*b636d99dSDavid van Moolenbroek __RCSID("$NetBSD: print-snmp.c,v 1.4 2014/11/20 03:05:03 christos Exp $");
62*b636d99dSDavid van Moolenbroek #endif
63*b636d99dSDavid van Moolenbroek 
64*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
65*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
66*b636d99dSDavid van Moolenbroek #include "config.h"
67*b636d99dSDavid van Moolenbroek #endif
68*b636d99dSDavid van Moolenbroek 
69*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
70*b636d99dSDavid van Moolenbroek 
71*b636d99dSDavid van Moolenbroek #include <stdio.h>
72*b636d99dSDavid van Moolenbroek #include <string.h>
73*b636d99dSDavid van Moolenbroek 
74*b636d99dSDavid van Moolenbroek #ifdef USE_LIBSMI
75*b636d99dSDavid van Moolenbroek #include <smi.h>
76*b636d99dSDavid van Moolenbroek #endif
77*b636d99dSDavid van Moolenbroek 
78*b636d99dSDavid van Moolenbroek #include "interface.h"
79*b636d99dSDavid van Moolenbroek 
80*b636d99dSDavid van Moolenbroek #undef OPAQUE  /* defined in <wingdi.h> */
81*b636d99dSDavid van Moolenbroek 
82*b636d99dSDavid van Moolenbroek static const char tstr[] = "[|snmp]";
83*b636d99dSDavid van Moolenbroek 
84*b636d99dSDavid van Moolenbroek /*
85*b636d99dSDavid van Moolenbroek  * Universal ASN.1 types
86*b636d99dSDavid van Moolenbroek  * (we only care about the tag values for those allowed in the Internet SMI)
87*b636d99dSDavid van Moolenbroek  */
88*b636d99dSDavid van Moolenbroek static const char *Universal[] = {
89*b636d99dSDavid van Moolenbroek 	"U-0",
90*b636d99dSDavid van Moolenbroek 	"Boolean",
91*b636d99dSDavid van Moolenbroek 	"Integer",
92*b636d99dSDavid van Moolenbroek #define INTEGER 2
93*b636d99dSDavid van Moolenbroek 	"Bitstring",
94*b636d99dSDavid van Moolenbroek 	"String",
95*b636d99dSDavid van Moolenbroek #define STRING 4
96*b636d99dSDavid van Moolenbroek 	"Null",
97*b636d99dSDavid van Moolenbroek #define ASN_NULL 5
98*b636d99dSDavid van Moolenbroek 	"ObjID",
99*b636d99dSDavid van Moolenbroek #define OBJECTID 6
100*b636d99dSDavid van Moolenbroek 	"ObjectDes",
101*b636d99dSDavid van Moolenbroek 	"U-8","U-9","U-10","U-11",	/* 8-11 */
102*b636d99dSDavid van Moolenbroek 	"U-12","U-13","U-14","U-15",	/* 12-15 */
103*b636d99dSDavid van Moolenbroek 	"Sequence",
104*b636d99dSDavid van Moolenbroek #define SEQUENCE 16
105*b636d99dSDavid van Moolenbroek 	"Set"
106*b636d99dSDavid van Moolenbroek };
107*b636d99dSDavid van Moolenbroek 
108*b636d99dSDavid van Moolenbroek /*
109*b636d99dSDavid van Moolenbroek  * Application-wide ASN.1 types from the Internet SMI and their tags
110*b636d99dSDavid van Moolenbroek  */
111*b636d99dSDavid van Moolenbroek static const char *Application[] = {
112*b636d99dSDavid van Moolenbroek 	"IpAddress",
113*b636d99dSDavid van Moolenbroek #define IPADDR 0
114*b636d99dSDavid van Moolenbroek 	"Counter",
115*b636d99dSDavid van Moolenbroek #define COUNTER 1
116*b636d99dSDavid van Moolenbroek 	"Gauge",
117*b636d99dSDavid van Moolenbroek #define GAUGE 2
118*b636d99dSDavid van Moolenbroek 	"TimeTicks",
119*b636d99dSDavid van Moolenbroek #define TIMETICKS 3
120*b636d99dSDavid van Moolenbroek 	"Opaque",
121*b636d99dSDavid van Moolenbroek #define OPAQUE 4
122*b636d99dSDavid van Moolenbroek 	"C-5",
123*b636d99dSDavid van Moolenbroek 	"Counter64"
124*b636d99dSDavid van Moolenbroek #define COUNTER64 6
125*b636d99dSDavid van Moolenbroek };
126*b636d99dSDavid van Moolenbroek 
127*b636d99dSDavid van Moolenbroek /*
128*b636d99dSDavid van Moolenbroek  * Context-specific ASN.1 types for the SNMP PDUs and their tags
129*b636d99dSDavid van Moolenbroek  */
130*b636d99dSDavid van Moolenbroek static const char *Context[] = {
131*b636d99dSDavid van Moolenbroek 	"GetRequest",
132*b636d99dSDavid van Moolenbroek #define GETREQ 0
133*b636d99dSDavid van Moolenbroek 	"GetNextRequest",
134*b636d99dSDavid van Moolenbroek #define GETNEXTREQ 1
135*b636d99dSDavid van Moolenbroek 	"GetResponse",
136*b636d99dSDavid van Moolenbroek #define GETRESP 2
137*b636d99dSDavid van Moolenbroek 	"SetRequest",
138*b636d99dSDavid van Moolenbroek #define SETREQ 3
139*b636d99dSDavid van Moolenbroek 	"Trap",
140*b636d99dSDavid van Moolenbroek #define TRAP 4
141*b636d99dSDavid van Moolenbroek 	"GetBulk",
142*b636d99dSDavid van Moolenbroek #define GETBULKREQ 5
143*b636d99dSDavid van Moolenbroek 	"Inform",
144*b636d99dSDavid van Moolenbroek #define INFORMREQ 6
145*b636d99dSDavid van Moolenbroek 	"V2Trap",
146*b636d99dSDavid van Moolenbroek #define V2TRAP 7
147*b636d99dSDavid van Moolenbroek 	"Report"
148*b636d99dSDavid van Moolenbroek #define REPORT 8
149*b636d99dSDavid van Moolenbroek };
150*b636d99dSDavid van Moolenbroek 
151*b636d99dSDavid van Moolenbroek #define NOTIFY_CLASS(x)	    (x == TRAP || x == V2TRAP || x == INFORMREQ)
152*b636d99dSDavid van Moolenbroek #define READ_CLASS(x)       (x == GETREQ || x == GETNEXTREQ || x == GETBULKREQ)
153*b636d99dSDavid van Moolenbroek #define WRITE_CLASS(x)	    (x == SETREQ)
154*b636d99dSDavid van Moolenbroek #define RESPONSE_CLASS(x)   (x == GETRESP)
155*b636d99dSDavid van Moolenbroek #define INTERNAL_CLASS(x)   (x == REPORT)
156*b636d99dSDavid van Moolenbroek 
157*b636d99dSDavid van Moolenbroek /*
158*b636d99dSDavid van Moolenbroek  * Context-specific ASN.1 types for the SNMP Exceptions and their tags
159*b636d99dSDavid van Moolenbroek  */
160*b636d99dSDavid van Moolenbroek static const char *Exceptions[] = {
161*b636d99dSDavid van Moolenbroek 	"noSuchObject",
162*b636d99dSDavid van Moolenbroek #define NOSUCHOBJECT 0
163*b636d99dSDavid van Moolenbroek 	"noSuchInstance",
164*b636d99dSDavid van Moolenbroek #define NOSUCHINSTANCE 1
165*b636d99dSDavid van Moolenbroek 	"endOfMibView",
166*b636d99dSDavid van Moolenbroek #define ENDOFMIBVIEW 2
167*b636d99dSDavid van Moolenbroek };
168*b636d99dSDavid van Moolenbroek 
169*b636d99dSDavid van Moolenbroek /*
170*b636d99dSDavid van Moolenbroek  * Private ASN.1 types
171*b636d99dSDavid van Moolenbroek  * The Internet SMI does not specify any
172*b636d99dSDavid van Moolenbroek  */
173*b636d99dSDavid van Moolenbroek static const char *Private[] = {
174*b636d99dSDavid van Moolenbroek 	"P-0"
175*b636d99dSDavid van Moolenbroek };
176*b636d99dSDavid van Moolenbroek 
177*b636d99dSDavid van Moolenbroek /*
178*b636d99dSDavid van Moolenbroek  * error-status values for any SNMP PDU
179*b636d99dSDavid van Moolenbroek  */
180*b636d99dSDavid van Moolenbroek static const char *ErrorStatus[] = {
181*b636d99dSDavid van Moolenbroek 	"noError",
182*b636d99dSDavid van Moolenbroek 	"tooBig",
183*b636d99dSDavid van Moolenbroek 	"noSuchName",
184*b636d99dSDavid van Moolenbroek 	"badValue",
185*b636d99dSDavid van Moolenbroek 	"readOnly",
186*b636d99dSDavid van Moolenbroek 	"genErr",
187*b636d99dSDavid van Moolenbroek 	"noAccess",
188*b636d99dSDavid van Moolenbroek 	"wrongType",
189*b636d99dSDavid van Moolenbroek 	"wrongLength",
190*b636d99dSDavid van Moolenbroek 	"wrongEncoding",
191*b636d99dSDavid van Moolenbroek 	"wrongValue",
192*b636d99dSDavid van Moolenbroek 	"noCreation",
193*b636d99dSDavid van Moolenbroek 	"inconsistentValue",
194*b636d99dSDavid van Moolenbroek 	"resourceUnavailable",
195*b636d99dSDavid van Moolenbroek 	"commitFailed",
196*b636d99dSDavid van Moolenbroek 	"undoFailed",
197*b636d99dSDavid van Moolenbroek 	"authorizationError",
198*b636d99dSDavid van Moolenbroek 	"notWritable",
199*b636d99dSDavid van Moolenbroek 	"inconsistentName"
200*b636d99dSDavid van Moolenbroek };
201*b636d99dSDavid van Moolenbroek #define DECODE_ErrorStatus(e) \
202*b636d99dSDavid van Moolenbroek 	( e >= 0 && (size_t)e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
203*b636d99dSDavid van Moolenbroek 		? ErrorStatus[e] \
204*b636d99dSDavid van Moolenbroek 		: (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf))
205*b636d99dSDavid van Moolenbroek 
206*b636d99dSDavid van Moolenbroek /*
207*b636d99dSDavid van Moolenbroek  * generic-trap values in the SNMP Trap-PDU
208*b636d99dSDavid van Moolenbroek  */
209*b636d99dSDavid van Moolenbroek static const char *GenericTrap[] = {
210*b636d99dSDavid van Moolenbroek 	"coldStart",
211*b636d99dSDavid van Moolenbroek 	"warmStart",
212*b636d99dSDavid van Moolenbroek 	"linkDown",
213*b636d99dSDavid van Moolenbroek 	"linkUp",
214*b636d99dSDavid van Moolenbroek 	"authenticationFailure",
215*b636d99dSDavid van Moolenbroek 	"egpNeighborLoss",
216*b636d99dSDavid van Moolenbroek 	"enterpriseSpecific"
217*b636d99dSDavid van Moolenbroek #define GT_ENTERPRISE 6
218*b636d99dSDavid van Moolenbroek };
219*b636d99dSDavid van Moolenbroek #define DECODE_GenericTrap(t) \
220*b636d99dSDavid van Moolenbroek 	( t >= 0 && (size_t)t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
221*b636d99dSDavid van Moolenbroek 		? GenericTrap[t] \
222*b636d99dSDavid van Moolenbroek 		: (snprintf(buf, sizeof(buf), "gt=%d", t), buf))
223*b636d99dSDavid van Moolenbroek 
224*b636d99dSDavid van Moolenbroek /*
225*b636d99dSDavid van Moolenbroek  * ASN.1 type class table
226*b636d99dSDavid van Moolenbroek  * Ties together the preceding Universal, Application, Context, and Private
227*b636d99dSDavid van Moolenbroek  * type definitions.
228*b636d99dSDavid van Moolenbroek  */
229*b636d99dSDavid van Moolenbroek #define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
230*b636d99dSDavid van Moolenbroek static const struct {
231*b636d99dSDavid van Moolenbroek 	const char	*name;
232*b636d99dSDavid van Moolenbroek 	const char	**Id;
233*b636d99dSDavid van Moolenbroek 	    int	numIDs;
234*b636d99dSDavid van Moolenbroek     } Class[] = {
235*b636d99dSDavid van Moolenbroek 	defineCLASS(Universal),
236*b636d99dSDavid van Moolenbroek #define	UNIVERSAL	0
237*b636d99dSDavid van Moolenbroek 	defineCLASS(Application),
238*b636d99dSDavid van Moolenbroek #define	APPLICATION	1
239*b636d99dSDavid van Moolenbroek 	defineCLASS(Context),
240*b636d99dSDavid van Moolenbroek #define	CONTEXT		2
241*b636d99dSDavid van Moolenbroek 	defineCLASS(Private),
242*b636d99dSDavid van Moolenbroek #define	PRIVATE		3
243*b636d99dSDavid van Moolenbroek 	defineCLASS(Exceptions),
244*b636d99dSDavid van Moolenbroek #define EXCEPTIONS	4
245*b636d99dSDavid van Moolenbroek };
246*b636d99dSDavid van Moolenbroek 
247*b636d99dSDavid van Moolenbroek /*
248*b636d99dSDavid van Moolenbroek  * defined forms for ASN.1 types
249*b636d99dSDavid van Moolenbroek  */
250*b636d99dSDavid van Moolenbroek static const char *Form[] = {
251*b636d99dSDavid van Moolenbroek 	"Primitive",
252*b636d99dSDavid van Moolenbroek #define PRIMITIVE	0
253*b636d99dSDavid van Moolenbroek 	"Constructed",
254*b636d99dSDavid van Moolenbroek #define CONSTRUCTED	1
255*b636d99dSDavid van Moolenbroek };
256*b636d99dSDavid van Moolenbroek 
257*b636d99dSDavid van Moolenbroek /*
258*b636d99dSDavid van Moolenbroek  * A structure for the OID tree for the compiled-in MIB.
259*b636d99dSDavid van Moolenbroek  * This is stored as a general-order tree.
260*b636d99dSDavid van Moolenbroek  */
261*b636d99dSDavid van Moolenbroek struct obj {
262*b636d99dSDavid van Moolenbroek 	const char	*desc;		/* name of object */
263*b636d99dSDavid van Moolenbroek 	u_char	oid;			/* sub-id following parent */
264*b636d99dSDavid van Moolenbroek 	u_char	type;			/* object type (unused) */
265*b636d99dSDavid van Moolenbroek 	struct obj *child, *next;	/* child and next sibling pointers */
266*b636d99dSDavid van Moolenbroek } *objp = NULL;
267*b636d99dSDavid van Moolenbroek 
268*b636d99dSDavid van Moolenbroek /*
269*b636d99dSDavid van Moolenbroek  * Include the compiled in SNMP MIB.  "mib.h" is produced by feeding
270*b636d99dSDavid van Moolenbroek  * RFC-1156 format files into "makemib".  "mib.h" MUST define at least
271*b636d99dSDavid van Moolenbroek  * a value for `mibroot'.
272*b636d99dSDavid van Moolenbroek  *
273*b636d99dSDavid van Moolenbroek  * In particular, this is gross, as this is including initialized structures,
274*b636d99dSDavid van Moolenbroek  * and by right shouldn't be an "include" file.
275*b636d99dSDavid van Moolenbroek  */
276*b636d99dSDavid van Moolenbroek #include "mib.h"
277*b636d99dSDavid van Moolenbroek 
278*b636d99dSDavid van Moolenbroek /*
279*b636d99dSDavid van Moolenbroek  * This defines a list of OIDs which will be abbreviated on output.
280*b636d99dSDavid van Moolenbroek  * Currently, this includes the prefixes for the Internet MIB, the
281*b636d99dSDavid van Moolenbroek  * private enterprises tree, and the experimental tree.
282*b636d99dSDavid van Moolenbroek  */
283*b636d99dSDavid van Moolenbroek static const struct obj_abrev {
284*b636d99dSDavid van Moolenbroek 	const char *prefix;		/* prefix for this abrev */
285*b636d99dSDavid van Moolenbroek 	struct obj *node;		/* pointer into object table */
286*b636d99dSDavid van Moolenbroek 	const char *oid;		/* ASN.1 encoded OID */
287*b636d99dSDavid van Moolenbroek } obj_abrev_list[] = {
288*b636d99dSDavid van Moolenbroek #ifndef NO_ABREV_MIB
289*b636d99dSDavid van Moolenbroek 	/* .iso.org.dod.internet.mgmt.mib */
290*b636d99dSDavid van Moolenbroek 	{ "",	&_mib_obj,		"\53\6\1\2\1" },
291*b636d99dSDavid van Moolenbroek #endif
292*b636d99dSDavid van Moolenbroek #ifndef NO_ABREV_ENTER
293*b636d99dSDavid van Moolenbroek 	/* .iso.org.dod.internet.private.enterprises */
294*b636d99dSDavid van Moolenbroek 	{ "E:",	&_enterprises_obj,	"\53\6\1\4\1" },
295*b636d99dSDavid van Moolenbroek #endif
296*b636d99dSDavid van Moolenbroek #ifndef NO_ABREV_EXPERI
297*b636d99dSDavid van Moolenbroek 	/* .iso.org.dod.internet.experimental */
298*b636d99dSDavid van Moolenbroek 	{ "X:",	&_experimental_obj,	"\53\6\1\3" },
299*b636d99dSDavid van Moolenbroek #endif
300*b636d99dSDavid van Moolenbroek #ifndef NO_ABBREV_SNMPMODS
301*b636d99dSDavid van Moolenbroek 	/* .iso.org.dod.internet.snmpV2.snmpModules */
302*b636d99dSDavid van Moolenbroek         { "S:", &_snmpModules_obj,      "\53\6\1\6\3" },
303*b636d99dSDavid van Moolenbroek #endif
304*b636d99dSDavid van Moolenbroek 	{ 0,0,0 }
305*b636d99dSDavid van Moolenbroek };
306*b636d99dSDavid van Moolenbroek 
307*b636d99dSDavid van Moolenbroek /*
308*b636d99dSDavid van Moolenbroek  * This is used in the OID print routine to walk down the object tree
309*b636d99dSDavid van Moolenbroek  * rooted at `mibroot'.
310*b636d99dSDavid van Moolenbroek  */
311*b636d99dSDavid van Moolenbroek #define OBJ_PRINT(o, suppressdot) \
312*b636d99dSDavid van Moolenbroek { \
313*b636d99dSDavid van Moolenbroek 	if (objp) { \
314*b636d99dSDavid van Moolenbroek 		do { \
315*b636d99dSDavid van Moolenbroek 			if ((o) == objp->oid) \
316*b636d99dSDavid van Moolenbroek 				break; \
317*b636d99dSDavid van Moolenbroek 		} while ((objp = objp->next) != NULL); \
318*b636d99dSDavid van Moolenbroek 	} \
319*b636d99dSDavid van Moolenbroek 	if (objp) { \
320*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, suppressdot?"%s":".%s", objp->desc)); \
321*b636d99dSDavid van Moolenbroek 		objp = objp->child; \
322*b636d99dSDavid van Moolenbroek 	} else \
323*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, suppressdot?"%u":".%u", (o))); \
324*b636d99dSDavid van Moolenbroek }
325*b636d99dSDavid van Moolenbroek 
326*b636d99dSDavid van Moolenbroek /*
327*b636d99dSDavid van Moolenbroek  * This is the definition for the Any-Data-Type storage used purely for
328*b636d99dSDavid van Moolenbroek  * temporary internal representation while decoding an ASN.1 data stream.
329*b636d99dSDavid van Moolenbroek  */
330*b636d99dSDavid van Moolenbroek struct be {
331*b636d99dSDavid van Moolenbroek 	uint32_t asnlen;
332*b636d99dSDavid van Moolenbroek 	union {
333*b636d99dSDavid van Moolenbroek 		caddr_t raw;
334*b636d99dSDavid van Moolenbroek 		int32_t integer;
335*b636d99dSDavid van Moolenbroek 		uint32_t uns;
336*b636d99dSDavid van Moolenbroek 		const u_char *str;
337*b636d99dSDavid van Moolenbroek 	        struct {
338*b636d99dSDavid van Moolenbroek 		        uint32_t high;
339*b636d99dSDavid van Moolenbroek 		        uint32_t low;
340*b636d99dSDavid van Moolenbroek 		} uns64;
341*b636d99dSDavid van Moolenbroek 	} data;
342*b636d99dSDavid van Moolenbroek 	u_short id;
343*b636d99dSDavid van Moolenbroek 	u_char form, class;		/* tag info */
344*b636d99dSDavid van Moolenbroek 	u_char type;
345*b636d99dSDavid van Moolenbroek #define BE_ANY		255
346*b636d99dSDavid van Moolenbroek #define BE_NONE		0
347*b636d99dSDavid van Moolenbroek #define BE_NULL		1
348*b636d99dSDavid van Moolenbroek #define BE_OCTET	2
349*b636d99dSDavid van Moolenbroek #define BE_OID		3
350*b636d99dSDavid van Moolenbroek #define BE_INT		4
351*b636d99dSDavid van Moolenbroek #define BE_UNS		5
352*b636d99dSDavid van Moolenbroek #define BE_STR		6
353*b636d99dSDavid van Moolenbroek #define BE_SEQ		7
354*b636d99dSDavid van Moolenbroek #define BE_INETADDR	8
355*b636d99dSDavid van Moolenbroek #define BE_PDU		9
356*b636d99dSDavid van Moolenbroek #define BE_UNS64	10
357*b636d99dSDavid van Moolenbroek #define BE_NOSUCHOBJECT	128
358*b636d99dSDavid van Moolenbroek #define BE_NOSUCHINST	129
359*b636d99dSDavid van Moolenbroek #define BE_ENDOFMIBVIEW	130
360*b636d99dSDavid van Moolenbroek };
361*b636d99dSDavid van Moolenbroek 
362*b636d99dSDavid van Moolenbroek /*
363*b636d99dSDavid van Moolenbroek  * SNMP versions recognized by this module
364*b636d99dSDavid van Moolenbroek  */
365*b636d99dSDavid van Moolenbroek static const char *SnmpVersion[] = {
366*b636d99dSDavid van Moolenbroek 	"SNMPv1",
367*b636d99dSDavid van Moolenbroek #define SNMP_VERSION_1	0
368*b636d99dSDavid van Moolenbroek 	"SNMPv2c",
369*b636d99dSDavid van Moolenbroek #define SNMP_VERSION_2	1
370*b636d99dSDavid van Moolenbroek 	"SNMPv2u",
371*b636d99dSDavid van Moolenbroek #define SNMP_VERSION_2U	2
372*b636d99dSDavid van Moolenbroek 	"SNMPv3"
373*b636d99dSDavid van Moolenbroek #define SNMP_VERSION_3	3
374*b636d99dSDavid van Moolenbroek };
375*b636d99dSDavid van Moolenbroek 
376*b636d99dSDavid van Moolenbroek /*
377*b636d99dSDavid van Moolenbroek  * Defaults for SNMP PDU components
378*b636d99dSDavid van Moolenbroek  */
379*b636d99dSDavid van Moolenbroek #define DEF_COMMUNITY "public"
380*b636d99dSDavid van Moolenbroek 
381*b636d99dSDavid van Moolenbroek /*
382*b636d99dSDavid van Moolenbroek  * constants for ASN.1 decoding
383*b636d99dSDavid van Moolenbroek  */
384*b636d99dSDavid van Moolenbroek #define OIDMUX 40
385*b636d99dSDavid van Moolenbroek #define ASNLEN_INETADDR 4
386*b636d99dSDavid van Moolenbroek #define ASN_SHIFT7 7
387*b636d99dSDavid van Moolenbroek #define ASN_SHIFT8 8
388*b636d99dSDavid van Moolenbroek #define ASN_BIT8 0x80
389*b636d99dSDavid van Moolenbroek #define ASN_LONGLEN 0x80
390*b636d99dSDavid van Moolenbroek 
391*b636d99dSDavid van Moolenbroek #define ASN_ID_BITS 0x1f
392*b636d99dSDavid van Moolenbroek #define ASN_FORM_BITS 0x20
393*b636d99dSDavid van Moolenbroek #define ASN_FORM_SHIFT 5
394*b636d99dSDavid van Moolenbroek #define ASN_CLASS_BITS 0xc0
395*b636d99dSDavid van Moolenbroek #define ASN_CLASS_SHIFT 6
396*b636d99dSDavid van Moolenbroek 
397*b636d99dSDavid van Moolenbroek #define ASN_ID_EXT 0x1f		/* extension ID in tag field */
398*b636d99dSDavid van Moolenbroek 
399*b636d99dSDavid van Moolenbroek /*
400*b636d99dSDavid van Moolenbroek  * This decodes the next ASN.1 object in the stream pointed to by "p"
401*b636d99dSDavid van Moolenbroek  * (and of real-length "len") and stores the intermediate data in the
402*b636d99dSDavid van Moolenbroek  * provided BE object.
403*b636d99dSDavid van Moolenbroek  *
404*b636d99dSDavid van Moolenbroek  * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
405*b636d99dSDavid van Moolenbroek  * O/w, this returns the number of bytes parsed from "p".
406*b636d99dSDavid van Moolenbroek  */
407*b636d99dSDavid van Moolenbroek static int
asn1_parse(netdissect_options * ndo,register const u_char * p,u_int len,struct be * elem)408*b636d99dSDavid van Moolenbroek asn1_parse(netdissect_options *ndo,
409*b636d99dSDavid van Moolenbroek            register const u_char *p, u_int len, struct be *elem)
410*b636d99dSDavid van Moolenbroek {
411*b636d99dSDavid van Moolenbroek 	u_char form, class, id;
412*b636d99dSDavid van Moolenbroek 	int i, hdr;
413*b636d99dSDavid van Moolenbroek 
414*b636d99dSDavid van Moolenbroek 	elem->asnlen = 0;
415*b636d99dSDavid van Moolenbroek 	elem->type = BE_ANY;
416*b636d99dSDavid van Moolenbroek 	if (len < 1) {
417*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[nothing to parse]"));
418*b636d99dSDavid van Moolenbroek 		return -1;
419*b636d99dSDavid van Moolenbroek 	}
420*b636d99dSDavid van Moolenbroek 	ND_TCHECK(*p);
421*b636d99dSDavid van Moolenbroek 
422*b636d99dSDavid van Moolenbroek 	/*
423*b636d99dSDavid van Moolenbroek 	 * it would be nice to use a bit field, but you can't depend on them.
424*b636d99dSDavid van Moolenbroek 	 *  +---+---+---+---+---+---+---+---+
425*b636d99dSDavid van Moolenbroek 	 *  + class |frm|        id         |
426*b636d99dSDavid van Moolenbroek 	 *  +---+---+---+---+---+---+---+---+
427*b636d99dSDavid van Moolenbroek 	 *    7   6   5   4   3   2   1   0
428*b636d99dSDavid van Moolenbroek 	 */
429*b636d99dSDavid van Moolenbroek 	id = *p & ASN_ID_BITS;		/* lower 5 bits, range 00-1f */
430*b636d99dSDavid van Moolenbroek #ifdef notdef
431*b636d99dSDavid van Moolenbroek 	form = (*p & 0xe0) >> 5;	/* move upper 3 bits to lower 3 */
432*b636d99dSDavid van Moolenbroek 	class = form >> 1;		/* bits 7&6 -> bits 1&0, range 0-3 */
433*b636d99dSDavid van Moolenbroek 	form &= 0x1;			/* bit 5 -> bit 0, range 0-1 */
434*b636d99dSDavid van Moolenbroek #else
435*b636d99dSDavid van Moolenbroek 	form = (u_char)(*p & ASN_FORM_BITS) >> ASN_FORM_SHIFT;
436*b636d99dSDavid van Moolenbroek 	class = (u_char)(*p & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT;
437*b636d99dSDavid van Moolenbroek #endif
438*b636d99dSDavid van Moolenbroek 	elem->form = form;
439*b636d99dSDavid van Moolenbroek 	elem->class = class;
440*b636d99dSDavid van Moolenbroek 	elem->id = id;
441*b636d99dSDavid van Moolenbroek 	p++; len--; hdr = 1;
442*b636d99dSDavid van Moolenbroek 	/* extended tag field */
443*b636d99dSDavid van Moolenbroek 	if (id == ASN_ID_EXT) {
444*b636d99dSDavid van Moolenbroek 		/*
445*b636d99dSDavid van Moolenbroek 		 * The ID follows, as a sequence of octets with the
446*b636d99dSDavid van Moolenbroek 		 * 8th bit set and the remaining 7 bits being
447*b636d99dSDavid van Moolenbroek 		 * the next 7 bits of the value, terminated with
448*b636d99dSDavid van Moolenbroek 		 * an octet with the 8th bit not set.
449*b636d99dSDavid van Moolenbroek 		 *
450*b636d99dSDavid van Moolenbroek 		 * First, assemble all the octets with the 8th
451*b636d99dSDavid van Moolenbroek 		 * bit set.  XXX - this doesn't handle a value
452*b636d99dSDavid van Moolenbroek 		 * that won't fit in 32 bits.
453*b636d99dSDavid van Moolenbroek 		 */
454*b636d99dSDavid van Moolenbroek 		for (id = 0; *p & ASN_BIT8; len--, hdr++, p++) {
455*b636d99dSDavid van Moolenbroek 			if (len < 1) {
456*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "[Xtagfield?]"));
457*b636d99dSDavid van Moolenbroek 				return -1;
458*b636d99dSDavid van Moolenbroek 			}
459*b636d99dSDavid van Moolenbroek 			ND_TCHECK(*p);
460*b636d99dSDavid van Moolenbroek 			id = (id << 7) | (*p & ~ASN_BIT8);
461*b636d99dSDavid van Moolenbroek 		}
462*b636d99dSDavid van Moolenbroek 		if (len < 1) {
463*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[Xtagfield?]"));
464*b636d99dSDavid van Moolenbroek 			return -1;
465*b636d99dSDavid van Moolenbroek 		}
466*b636d99dSDavid van Moolenbroek 		ND_TCHECK(*p);
467*b636d99dSDavid van Moolenbroek 		elem->id = id = (id << 7) | *p;
468*b636d99dSDavid van Moolenbroek 		--len;
469*b636d99dSDavid van Moolenbroek 		++hdr;
470*b636d99dSDavid van Moolenbroek 		++p;
471*b636d99dSDavid van Moolenbroek 	}
472*b636d99dSDavid van Moolenbroek 	if (len < 1) {
473*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[no asnlen]"));
474*b636d99dSDavid van Moolenbroek 		return -1;
475*b636d99dSDavid van Moolenbroek 	}
476*b636d99dSDavid van Moolenbroek 	ND_TCHECK(*p);
477*b636d99dSDavid van Moolenbroek 	elem->asnlen = *p;
478*b636d99dSDavid van Moolenbroek 	p++; len--; hdr++;
479*b636d99dSDavid van Moolenbroek 	if (elem->asnlen & ASN_BIT8) {
480*b636d99dSDavid van Moolenbroek 		uint32_t noct = elem->asnlen % ASN_BIT8;
481*b636d99dSDavid van Moolenbroek 		elem->asnlen = 0;
482*b636d99dSDavid van Moolenbroek 		if (len < noct) {
483*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[asnlen? %d<%d]", len, noct));
484*b636d99dSDavid van Moolenbroek 			return -1;
485*b636d99dSDavid van Moolenbroek 		}
486*b636d99dSDavid van Moolenbroek 		ND_TCHECK2(*p, noct);
487*b636d99dSDavid van Moolenbroek 		for (; noct-- > 0; len--, hdr++)
488*b636d99dSDavid van Moolenbroek 			elem->asnlen = (elem->asnlen << ASN_SHIFT8) | *p++;
489*b636d99dSDavid van Moolenbroek 	}
490*b636d99dSDavid van Moolenbroek 	if (len < elem->asnlen) {
491*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[len%d<asnlen%u]", len, elem->asnlen));
492*b636d99dSDavid van Moolenbroek 		return -1;
493*b636d99dSDavid van Moolenbroek 	}
494*b636d99dSDavid van Moolenbroek 	if (form >= sizeof(Form)/sizeof(Form[0])) {
495*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[form?%d]", form));
496*b636d99dSDavid van Moolenbroek 		return -1;
497*b636d99dSDavid van Moolenbroek 	}
498*b636d99dSDavid van Moolenbroek 	if (class >= sizeof(Class)/sizeof(Class[0])) {
499*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[class?%c/%d]", *Form[form], class));
500*b636d99dSDavid van Moolenbroek 		return -1;
501*b636d99dSDavid van Moolenbroek 	}
502*b636d99dSDavid van Moolenbroek 	if ((int)id >= Class[class].numIDs) {
503*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[id?%c/%s/%d]", *Form[form], Class[class].name, id));
504*b636d99dSDavid van Moolenbroek 		return -1;
505*b636d99dSDavid van Moolenbroek 	}
506*b636d99dSDavid van Moolenbroek 
507*b636d99dSDavid van Moolenbroek 	switch (form) {
508*b636d99dSDavid van Moolenbroek 	case PRIMITIVE:
509*b636d99dSDavid van Moolenbroek 		switch (class) {
510*b636d99dSDavid van Moolenbroek 		case UNIVERSAL:
511*b636d99dSDavid van Moolenbroek 			switch (id) {
512*b636d99dSDavid van Moolenbroek 			case STRING:
513*b636d99dSDavid van Moolenbroek 				elem->type = BE_STR;
514*b636d99dSDavid van Moolenbroek 				elem->data.str = p;
515*b636d99dSDavid van Moolenbroek 				break;
516*b636d99dSDavid van Moolenbroek 
517*b636d99dSDavid van Moolenbroek 			case INTEGER: {
518*b636d99dSDavid van Moolenbroek 				register int32_t data;
519*b636d99dSDavid van Moolenbroek 				elem->type = BE_INT;
520*b636d99dSDavid van Moolenbroek 				data = 0;
521*b636d99dSDavid van Moolenbroek 
522*b636d99dSDavid van Moolenbroek 				ND_TCHECK2(*p, elem->asnlen);
523*b636d99dSDavid van Moolenbroek 				if (*p & ASN_BIT8)	/* negative */
524*b636d99dSDavid van Moolenbroek 					data = -1;
525*b636d99dSDavid van Moolenbroek 				for (i = elem->asnlen; i-- > 0; p++)
526*b636d99dSDavid van Moolenbroek 					data = (data << ASN_SHIFT8) | *p;
527*b636d99dSDavid van Moolenbroek 				elem->data.integer = data;
528*b636d99dSDavid van Moolenbroek 				break;
529*b636d99dSDavid van Moolenbroek 			}
530*b636d99dSDavid van Moolenbroek 
531*b636d99dSDavid van Moolenbroek 			case OBJECTID:
532*b636d99dSDavid van Moolenbroek 				elem->type = BE_OID;
533*b636d99dSDavid van Moolenbroek 				elem->data.raw = (caddr_t)p;
534*b636d99dSDavid van Moolenbroek 				break;
535*b636d99dSDavid van Moolenbroek 
536*b636d99dSDavid van Moolenbroek 			case ASN_NULL:
537*b636d99dSDavid van Moolenbroek 				elem->type = BE_NULL;
538*b636d99dSDavid van Moolenbroek 				elem->data.raw = NULL;
539*b636d99dSDavid van Moolenbroek 				break;
540*b636d99dSDavid van Moolenbroek 
541*b636d99dSDavid van Moolenbroek 			default:
542*b636d99dSDavid van Moolenbroek 				elem->type = BE_OCTET;
543*b636d99dSDavid van Moolenbroek 				elem->data.raw = (caddr_t)p;
544*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "[P/U/%s]", Class[class].Id[id]));
545*b636d99dSDavid van Moolenbroek 				break;
546*b636d99dSDavid van Moolenbroek 			}
547*b636d99dSDavid van Moolenbroek 			break;
548*b636d99dSDavid van Moolenbroek 
549*b636d99dSDavid van Moolenbroek 		case APPLICATION:
550*b636d99dSDavid van Moolenbroek 			switch (id) {
551*b636d99dSDavid van Moolenbroek 			case IPADDR:
552*b636d99dSDavid van Moolenbroek 				elem->type = BE_INETADDR;
553*b636d99dSDavid van Moolenbroek 				elem->data.raw = (caddr_t)p;
554*b636d99dSDavid van Moolenbroek 				break;
555*b636d99dSDavid van Moolenbroek 
556*b636d99dSDavid van Moolenbroek 			case COUNTER:
557*b636d99dSDavid van Moolenbroek 			case GAUGE:
558*b636d99dSDavid van Moolenbroek 			case TIMETICKS: {
559*b636d99dSDavid van Moolenbroek 				register uint32_t data;
560*b636d99dSDavid van Moolenbroek 				ND_TCHECK2(*p, elem->asnlen);
561*b636d99dSDavid van Moolenbroek 				elem->type = BE_UNS;
562*b636d99dSDavid van Moolenbroek 				data = 0;
563*b636d99dSDavid van Moolenbroek 				for (i = elem->asnlen; i-- > 0; p++)
564*b636d99dSDavid van Moolenbroek 					data = (data << 8) + *p;
565*b636d99dSDavid van Moolenbroek 				elem->data.uns = data;
566*b636d99dSDavid van Moolenbroek 				break;
567*b636d99dSDavid van Moolenbroek 			}
568*b636d99dSDavid van Moolenbroek 
569*b636d99dSDavid van Moolenbroek 			case COUNTER64: {
570*b636d99dSDavid van Moolenbroek 				register uint32_t high, low;
571*b636d99dSDavid van Moolenbroek 				ND_TCHECK2(*p, elem->asnlen);
572*b636d99dSDavid van Moolenbroek 			        elem->type = BE_UNS64;
573*b636d99dSDavid van Moolenbroek 				high = 0, low = 0;
574*b636d99dSDavid van Moolenbroek 				for (i = elem->asnlen; i-- > 0; p++) {
575*b636d99dSDavid van Moolenbroek 				        high = (high << 8) |
576*b636d99dSDavid van Moolenbroek 					    ((low & 0xFF000000) >> 24);
577*b636d99dSDavid van Moolenbroek 					low = (low << 8) | *p;
578*b636d99dSDavid van Moolenbroek 				}
579*b636d99dSDavid van Moolenbroek 				elem->data.uns64.high = high;
580*b636d99dSDavid van Moolenbroek 				elem->data.uns64.low = low;
581*b636d99dSDavid van Moolenbroek 				break;
582*b636d99dSDavid van Moolenbroek 			}
583*b636d99dSDavid van Moolenbroek 
584*b636d99dSDavid van Moolenbroek 			default:
585*b636d99dSDavid van Moolenbroek 				elem->type = BE_OCTET;
586*b636d99dSDavid van Moolenbroek 				elem->data.raw = (caddr_t)p;
587*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "[P/A/%s]",
588*b636d99dSDavid van Moolenbroek 					Class[class].Id[id]));
589*b636d99dSDavid van Moolenbroek 				break;
590*b636d99dSDavid van Moolenbroek 			}
591*b636d99dSDavid van Moolenbroek 			break;
592*b636d99dSDavid van Moolenbroek 
593*b636d99dSDavid van Moolenbroek 		case CONTEXT:
594*b636d99dSDavid van Moolenbroek 			switch (id) {
595*b636d99dSDavid van Moolenbroek 			case NOSUCHOBJECT:
596*b636d99dSDavid van Moolenbroek 				elem->type = BE_NOSUCHOBJECT;
597*b636d99dSDavid van Moolenbroek 				elem->data.raw = NULL;
598*b636d99dSDavid van Moolenbroek 				break;
599*b636d99dSDavid van Moolenbroek 
600*b636d99dSDavid van Moolenbroek 			case NOSUCHINSTANCE:
601*b636d99dSDavid van Moolenbroek 				elem->type = BE_NOSUCHINST;
602*b636d99dSDavid van Moolenbroek 				elem->data.raw = NULL;
603*b636d99dSDavid van Moolenbroek 				break;
604*b636d99dSDavid van Moolenbroek 
605*b636d99dSDavid van Moolenbroek 			case ENDOFMIBVIEW:
606*b636d99dSDavid van Moolenbroek 				elem->type = BE_ENDOFMIBVIEW;
607*b636d99dSDavid van Moolenbroek 				elem->data.raw = NULL;
608*b636d99dSDavid van Moolenbroek 				break;
609*b636d99dSDavid van Moolenbroek 			}
610*b636d99dSDavid van Moolenbroek 			break;
611*b636d99dSDavid van Moolenbroek 
612*b636d99dSDavid van Moolenbroek 		default:
613*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[P/%s/%s]", Class[class].name, Class[class].Id[id]));
614*b636d99dSDavid van Moolenbroek 			ND_TCHECK2(*p, elem->asnlen);
615*b636d99dSDavid van Moolenbroek 			elem->type = BE_OCTET;
616*b636d99dSDavid van Moolenbroek 			elem->data.raw = (caddr_t)p;
617*b636d99dSDavid van Moolenbroek 			break;
618*b636d99dSDavid van Moolenbroek 		}
619*b636d99dSDavid van Moolenbroek 		break;
620*b636d99dSDavid van Moolenbroek 
621*b636d99dSDavid van Moolenbroek 	case CONSTRUCTED:
622*b636d99dSDavid van Moolenbroek 		switch (class) {
623*b636d99dSDavid van Moolenbroek 		case UNIVERSAL:
624*b636d99dSDavid van Moolenbroek 			switch (id) {
625*b636d99dSDavid van Moolenbroek 			case SEQUENCE:
626*b636d99dSDavid van Moolenbroek 				elem->type = BE_SEQ;
627*b636d99dSDavid van Moolenbroek 				elem->data.raw = (caddr_t)p;
628*b636d99dSDavid van Moolenbroek 				break;
629*b636d99dSDavid van Moolenbroek 
630*b636d99dSDavid van Moolenbroek 			default:
631*b636d99dSDavid van Moolenbroek 				elem->type = BE_OCTET;
632*b636d99dSDavid van Moolenbroek 				elem->data.raw = (caddr_t)p;
633*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "C/U/%s", Class[class].Id[id]));
634*b636d99dSDavid van Moolenbroek 				break;
635*b636d99dSDavid van Moolenbroek 			}
636*b636d99dSDavid van Moolenbroek 			break;
637*b636d99dSDavid van Moolenbroek 
638*b636d99dSDavid van Moolenbroek 		case CONTEXT:
639*b636d99dSDavid van Moolenbroek 			elem->type = BE_PDU;
640*b636d99dSDavid van Moolenbroek 			elem->data.raw = (caddr_t)p;
641*b636d99dSDavid van Moolenbroek 			break;
642*b636d99dSDavid van Moolenbroek 
643*b636d99dSDavid van Moolenbroek 		default:
644*b636d99dSDavid van Moolenbroek 			elem->type = BE_OCTET;
645*b636d99dSDavid van Moolenbroek 			elem->data.raw = (caddr_t)p;
646*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "C/%s/%s", Class[class].name, Class[class].Id[id]));
647*b636d99dSDavid van Moolenbroek 			break;
648*b636d99dSDavid van Moolenbroek 		}
649*b636d99dSDavid van Moolenbroek 		break;
650*b636d99dSDavid van Moolenbroek 	}
651*b636d99dSDavid van Moolenbroek 	p += elem->asnlen;
652*b636d99dSDavid van Moolenbroek 	len -= elem->asnlen;
653*b636d99dSDavid van Moolenbroek 	return elem->asnlen + hdr;
654*b636d99dSDavid van Moolenbroek 
655*b636d99dSDavid van Moolenbroek trunc:
656*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "%s", tstr));
657*b636d99dSDavid van Moolenbroek 	return -1;
658*b636d99dSDavid van Moolenbroek }
659*b636d99dSDavid van Moolenbroek 
660*b636d99dSDavid van Moolenbroek /*
661*b636d99dSDavid van Moolenbroek  * Display the ASN.1 object represented by the BE object.
662*b636d99dSDavid van Moolenbroek  * This used to be an integral part of asn1_parse() before the intermediate
663*b636d99dSDavid van Moolenbroek  * BE form was added.
664*b636d99dSDavid van Moolenbroek  */
665*b636d99dSDavid van Moolenbroek static int
asn1_print(netdissect_options * ndo,struct be * elem)666*b636d99dSDavid van Moolenbroek asn1_print(netdissect_options *ndo,
667*b636d99dSDavid van Moolenbroek            struct be *elem)
668*b636d99dSDavid van Moolenbroek {
669*b636d99dSDavid van Moolenbroek 	u_char *p = (u_char *)elem->data.raw;
670*b636d99dSDavid van Moolenbroek 	uint32_t asnlen = elem->asnlen;
671*b636d99dSDavid van Moolenbroek 	uint32_t i;
672*b636d99dSDavid van Moolenbroek 
673*b636d99dSDavid van Moolenbroek 	switch (elem->type) {
674*b636d99dSDavid van Moolenbroek 
675*b636d99dSDavid van Moolenbroek 	case BE_OCTET:
676*b636d99dSDavid van Moolenbroek 		ND_TCHECK2(*p, asnlen);
677*b636d99dSDavid van Moolenbroek 		for (i = asnlen; i-- > 0; p++)
678*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "_%.2x", *p));
679*b636d99dSDavid van Moolenbroek 		break;
680*b636d99dSDavid van Moolenbroek 
681*b636d99dSDavid van Moolenbroek 	case BE_NULL:
682*b636d99dSDavid van Moolenbroek 		break;
683*b636d99dSDavid van Moolenbroek 
684*b636d99dSDavid van Moolenbroek 	case BE_OID: {
685*b636d99dSDavid van Moolenbroek 		int o = 0, first = -1, i = asnlen;
686*b636d99dSDavid van Moolenbroek 
687*b636d99dSDavid van Moolenbroek 		if (!ndo->ndo_sflag && !ndo->ndo_nflag && asnlen > 2) {
688*b636d99dSDavid van Moolenbroek 			const struct obj_abrev *a = &obj_abrev_list[0];
689*b636d99dSDavid van Moolenbroek 			size_t a_len = strlen(a->oid);
690*b636d99dSDavid van Moolenbroek 			for (; a->node; a++) {
691*b636d99dSDavid van Moolenbroek 				ND_TCHECK2(*p, a_len);
692*b636d99dSDavid van Moolenbroek 				if (memcmp(a->oid, (char *)p, a_len) == 0) {
693*b636d99dSDavid van Moolenbroek 					objp = a->node->child;
694*b636d99dSDavid van Moolenbroek 					i -= strlen(a->oid);
695*b636d99dSDavid van Moolenbroek 					p += strlen(a->oid);
696*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, "%s", a->prefix));
697*b636d99dSDavid van Moolenbroek 					first = 1;
698*b636d99dSDavid van Moolenbroek 					break;
699*b636d99dSDavid van Moolenbroek 				}
700*b636d99dSDavid van Moolenbroek 			}
701*b636d99dSDavid van Moolenbroek 		}
702*b636d99dSDavid van Moolenbroek 
703*b636d99dSDavid van Moolenbroek 		for (; !ndo->ndo_sflag && i-- > 0; p++) {
704*b636d99dSDavid van Moolenbroek 			ND_TCHECK(*p);
705*b636d99dSDavid van Moolenbroek 			o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
706*b636d99dSDavid van Moolenbroek 			if (*p & ASN_LONGLEN)
707*b636d99dSDavid van Moolenbroek 			        continue;
708*b636d99dSDavid van Moolenbroek 
709*b636d99dSDavid van Moolenbroek 			/*
710*b636d99dSDavid van Moolenbroek 			 * first subitem encodes two items with 1st*OIDMUX+2nd
711*b636d99dSDavid van Moolenbroek 			 * (see X.690:1997 clause 8.19 for the details)
712*b636d99dSDavid van Moolenbroek 			 */
713*b636d99dSDavid van Moolenbroek 			if (first < 0) {
714*b636d99dSDavid van Moolenbroek 			        int s;
715*b636d99dSDavid van Moolenbroek 				if (!ndo->ndo_nflag)
716*b636d99dSDavid van Moolenbroek 					objp = mibroot;
717*b636d99dSDavid van Moolenbroek 				first = 0;
718*b636d99dSDavid van Moolenbroek 				s = o / OIDMUX;
719*b636d99dSDavid van Moolenbroek 				if (s > 2) s = 2;
720*b636d99dSDavid van Moolenbroek 				OBJ_PRINT(s, first);
721*b636d99dSDavid van Moolenbroek 				o -= s * OIDMUX;
722*b636d99dSDavid van Moolenbroek 			}
723*b636d99dSDavid van Moolenbroek 			OBJ_PRINT(o, first);
724*b636d99dSDavid van Moolenbroek 			if (--first < 0)
725*b636d99dSDavid van Moolenbroek 				first = 0;
726*b636d99dSDavid van Moolenbroek 			o = 0;
727*b636d99dSDavid van Moolenbroek 		}
728*b636d99dSDavid van Moolenbroek 		break;
729*b636d99dSDavid van Moolenbroek 	}
730*b636d99dSDavid van Moolenbroek 
731*b636d99dSDavid van Moolenbroek 	case BE_INT:
732*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%d", elem->data.integer));
733*b636d99dSDavid van Moolenbroek 		break;
734*b636d99dSDavid van Moolenbroek 
735*b636d99dSDavid van Moolenbroek 	case BE_UNS:
736*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%u", elem->data.uns));
737*b636d99dSDavid van Moolenbroek 		break;
738*b636d99dSDavid van Moolenbroek 
739*b636d99dSDavid van Moolenbroek 	case BE_UNS64: {	/* idea borrowed from by Marshall Rose */
740*b636d99dSDavid van Moolenbroek 	        double d;
741*b636d99dSDavid van Moolenbroek 		int j, carry;
742*b636d99dSDavid van Moolenbroek 		char *cpf, *cpl, last[6], first[30];
743*b636d99dSDavid van Moolenbroek 		if (elem->data.uns64.high == 0) {
744*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "%u", elem->data.uns64.low));
745*b636d99dSDavid van Moolenbroek 			break;
746*b636d99dSDavid van Moolenbroek 		}
747*b636d99dSDavid van Moolenbroek 		d = elem->data.uns64.high * 4294967296.0;	/* 2^32 */
748*b636d99dSDavid van Moolenbroek 		if (elem->data.uns64.high <= 0x1fffff) {
749*b636d99dSDavid van Moolenbroek 		        d += elem->data.uns64.low;
750*b636d99dSDavid van Moolenbroek #if 0 /*is looks illegal, but what is the intention?*/
751*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "%.f", d));
752*b636d99dSDavid van Moolenbroek #else
753*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "%f", d));
754*b636d99dSDavid van Moolenbroek #endif
755*b636d99dSDavid van Moolenbroek 			break;
756*b636d99dSDavid van Moolenbroek 		}
757*b636d99dSDavid van Moolenbroek 		d += (elem->data.uns64.low & 0xfffff000);
758*b636d99dSDavid van Moolenbroek #if 0 /*is looks illegal, but what is the intention?*/
759*b636d99dSDavid van Moolenbroek 		snprintf(first, sizeof(first), "%.f", d);
760*b636d99dSDavid van Moolenbroek #else
761*b636d99dSDavid van Moolenbroek 		snprintf(first, sizeof(first), "%f", d);
762*b636d99dSDavid van Moolenbroek #endif
763*b636d99dSDavid van Moolenbroek 		snprintf(last, sizeof(last), "%5.5d",
764*b636d99dSDavid van Moolenbroek 		    elem->data.uns64.low & 0xfff);
765*b636d99dSDavid van Moolenbroek 		for (carry = 0, cpf = first+strlen(first)-1, cpl = last+4;
766*b636d99dSDavid van Moolenbroek 		     cpl >= last;
767*b636d99dSDavid van Moolenbroek 		     cpf--, cpl--) {
768*b636d99dSDavid van Moolenbroek 		        j = carry + (*cpf - '0') + (*cpl - '0');
769*b636d99dSDavid van Moolenbroek 			if (j > 9) {
770*b636d99dSDavid van Moolenbroek 			        j -= 10;
771*b636d99dSDavid van Moolenbroek 				carry = 1;
772*b636d99dSDavid van Moolenbroek 			} else {
773*b636d99dSDavid van Moolenbroek 			        carry = 0;
774*b636d99dSDavid van Moolenbroek 		        }
775*b636d99dSDavid van Moolenbroek 			*cpf = j + '0';
776*b636d99dSDavid van Moolenbroek 		}
777*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%s", first));
778*b636d99dSDavid van Moolenbroek 		break;
779*b636d99dSDavid van Moolenbroek 	}
780*b636d99dSDavid van Moolenbroek 
781*b636d99dSDavid van Moolenbroek 	case BE_STR: {
782*b636d99dSDavid van Moolenbroek 		register int printable = 1, first = 1;
783*b636d99dSDavid van Moolenbroek 		const u_char *p = elem->data.str;
784*b636d99dSDavid van Moolenbroek 		ND_TCHECK2(*p, asnlen);
785*b636d99dSDavid van Moolenbroek 		for (i = asnlen; printable && i-- > 0; p++)
786*b636d99dSDavid van Moolenbroek 			printable = ND_ISPRINT(*p);
787*b636d99dSDavid van Moolenbroek 		p = elem->data.str;
788*b636d99dSDavid van Moolenbroek 		if (printable) {
789*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "\""));
790*b636d99dSDavid van Moolenbroek 			if (fn_printn(ndo, p, asnlen, ndo->ndo_snapend)) {
791*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "\""));
792*b636d99dSDavid van Moolenbroek 				goto trunc;
793*b636d99dSDavid van Moolenbroek 			}
794*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "\""));
795*b636d99dSDavid van Moolenbroek 		} else
796*b636d99dSDavid van Moolenbroek 			for (i = asnlen; i-- > 0; p++) {
797*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, first ? "%.2x" : "_%.2x", *p));
798*b636d99dSDavid van Moolenbroek 				first = 0;
799*b636d99dSDavid van Moolenbroek 			}
800*b636d99dSDavid van Moolenbroek 		break;
801*b636d99dSDavid van Moolenbroek 	}
802*b636d99dSDavid van Moolenbroek 
803*b636d99dSDavid van Moolenbroek 	case BE_SEQ:
804*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "Seq(%u)", elem->asnlen));
805*b636d99dSDavid van Moolenbroek 		break;
806*b636d99dSDavid van Moolenbroek 
807*b636d99dSDavid van Moolenbroek 	case BE_INETADDR:
808*b636d99dSDavid van Moolenbroek 		if (asnlen != ASNLEN_INETADDR)
809*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[inetaddr len!=%d]", ASNLEN_INETADDR));
810*b636d99dSDavid van Moolenbroek 		ND_TCHECK2(*p, asnlen);
811*b636d99dSDavid van Moolenbroek 		for (i = asnlen; i-- != 0; p++) {
812*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, (i == asnlen-1) ? "%u" : ".%u", *p));
813*b636d99dSDavid van Moolenbroek 		}
814*b636d99dSDavid van Moolenbroek 		break;
815*b636d99dSDavid van Moolenbroek 
816*b636d99dSDavid van Moolenbroek 	case BE_NOSUCHOBJECT:
817*b636d99dSDavid van Moolenbroek 	case BE_NOSUCHINST:
818*b636d99dSDavid van Moolenbroek 	case BE_ENDOFMIBVIEW:
819*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[%s]", Class[EXCEPTIONS].Id[elem->id]));
820*b636d99dSDavid van Moolenbroek 		break;
821*b636d99dSDavid van Moolenbroek 
822*b636d99dSDavid van Moolenbroek 	case BE_PDU:
823*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%s(%u)", Class[CONTEXT].Id[elem->id], elem->asnlen));
824*b636d99dSDavid van Moolenbroek 		break;
825*b636d99dSDavid van Moolenbroek 
826*b636d99dSDavid van Moolenbroek 	case BE_ANY:
827*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[BE_ANY!?]"));
828*b636d99dSDavid van Moolenbroek 		break;
829*b636d99dSDavid van Moolenbroek 
830*b636d99dSDavid van Moolenbroek 	default:
831*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[be!?]"));
832*b636d99dSDavid van Moolenbroek 		break;
833*b636d99dSDavid van Moolenbroek 	}
834*b636d99dSDavid van Moolenbroek 	return 0;
835*b636d99dSDavid van Moolenbroek 
836*b636d99dSDavid van Moolenbroek trunc:
837*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "%s", tstr));
838*b636d99dSDavid van Moolenbroek 	return -1;
839*b636d99dSDavid van Moolenbroek }
840*b636d99dSDavid van Moolenbroek 
841*b636d99dSDavid van Moolenbroek #ifdef notdef
842*b636d99dSDavid van Moolenbroek /*
843*b636d99dSDavid van Moolenbroek  * This is a brute force ASN.1 printer: recurses to dump an entire structure.
844*b636d99dSDavid van Moolenbroek  * This will work for any ASN.1 stream, not just an SNMP PDU.
845*b636d99dSDavid van Moolenbroek  *
846*b636d99dSDavid van Moolenbroek  * By adding newlines and spaces at the correct places, this would print in
847*b636d99dSDavid van Moolenbroek  * Rose-Normal-Form.
848*b636d99dSDavid van Moolenbroek  *
849*b636d99dSDavid van Moolenbroek  * This is not currently used.
850*b636d99dSDavid van Moolenbroek  */
851*b636d99dSDavid van Moolenbroek static void
asn1_decode(u_char * p,u_int length)852*b636d99dSDavid van Moolenbroek asn1_decode(u_char *p, u_int length)
853*b636d99dSDavid van Moolenbroek {
854*b636d99dSDavid van Moolenbroek 	struct be elem;
855*b636d99dSDavid van Moolenbroek 	int i = 0;
856*b636d99dSDavid van Moolenbroek 
857*b636d99dSDavid van Moolenbroek 	while (i >= 0 && length > 0) {
858*b636d99dSDavid van Moolenbroek 		i = asn1_parse(ndo, p, length, &elem);
859*b636d99dSDavid van Moolenbroek 		if (i >= 0) {
860*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " "));
861*b636d99dSDavid van Moolenbroek 			if (asn1_print(ndo, &elem) < 0)
862*b636d99dSDavid van Moolenbroek 				return;
863*b636d99dSDavid van Moolenbroek 			if (elem.type == BE_SEQ || elem.type == BE_PDU) {
864*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " {"));
865*b636d99dSDavid van Moolenbroek 				asn1_decode(elem.data.raw, elem.asnlen);
866*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " }"));
867*b636d99dSDavid van Moolenbroek 			}
868*b636d99dSDavid van Moolenbroek 			length -= i;
869*b636d99dSDavid van Moolenbroek 			p += i;
870*b636d99dSDavid van Moolenbroek 		}
871*b636d99dSDavid van Moolenbroek 	}
872*b636d99dSDavid van Moolenbroek }
873*b636d99dSDavid van Moolenbroek #endif
874*b636d99dSDavid van Moolenbroek 
875*b636d99dSDavid van Moolenbroek #ifdef USE_LIBSMI
876*b636d99dSDavid van Moolenbroek 
877*b636d99dSDavid van Moolenbroek struct smi2be {
878*b636d99dSDavid van Moolenbroek     SmiBasetype basetype;
879*b636d99dSDavid van Moolenbroek     int be;
880*b636d99dSDavid van Moolenbroek };
881*b636d99dSDavid van Moolenbroek 
882*b636d99dSDavid van Moolenbroek static const struct smi2be smi2betab[] = {
883*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_INTEGER32,		BE_INT },
884*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_OCTETSTRING,		BE_STR },
885*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_OCTETSTRING,		BE_INETADDR },
886*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_OBJECTIDENTIFIER,	BE_OID },
887*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_UNSIGNED32,		BE_UNS },
888*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_INTEGER64,		BE_NONE },
889*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_UNSIGNED64,		BE_UNS64 },
890*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_FLOAT32,		BE_NONE },
891*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_FLOAT64,		BE_NONE },
892*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_FLOAT128,		BE_NONE },
893*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_ENUM,		BE_INT },
894*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_BITS,		BE_STR },
895*b636d99dSDavid van Moolenbroek     { SMI_BASETYPE_UNKNOWN,		BE_NONE }
896*b636d99dSDavid van Moolenbroek };
897*b636d99dSDavid van Moolenbroek 
898*b636d99dSDavid van Moolenbroek static int
smi_decode_oid(netdissect_options * ndo,struct be * elem,unsigned int * oid,unsigned int oidsize,unsigned int * oidlen)899*b636d99dSDavid van Moolenbroek smi_decode_oid(netdissect_options *ndo,
900*b636d99dSDavid van Moolenbroek                struct be *elem, unsigned int *oid,
901*b636d99dSDavid van Moolenbroek                unsigned int oidsize, unsigned int *oidlen)
902*b636d99dSDavid van Moolenbroek {
903*b636d99dSDavid van Moolenbroek 	u_char *p = (u_char *)elem->data.raw;
904*b636d99dSDavid van Moolenbroek 	uint32_t asnlen = elem->asnlen;
905*b636d99dSDavid van Moolenbroek 	int o = 0, first = -1, i = asnlen;
906*b636d99dSDavid van Moolenbroek 	unsigned int firstval;
907*b636d99dSDavid van Moolenbroek 
908*b636d99dSDavid van Moolenbroek 	for (*oidlen = 0; ndo->ndo_sflag && i-- > 0; p++) {
909*b636d99dSDavid van Moolenbroek 		ND_TCHECK(*p);
910*b636d99dSDavid van Moolenbroek 	        o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
911*b636d99dSDavid van Moolenbroek 		if (*p & ASN_LONGLEN)
912*b636d99dSDavid van Moolenbroek 		    continue;
913*b636d99dSDavid van Moolenbroek 
914*b636d99dSDavid van Moolenbroek 		/*
915*b636d99dSDavid van Moolenbroek 		 * first subitem encodes two items with 1st*OIDMUX+2nd
916*b636d99dSDavid van Moolenbroek 		 * (see X.690:1997 clause 8.19 for the details)
917*b636d99dSDavid van Moolenbroek 		 */
918*b636d99dSDavid van Moolenbroek 		if (first < 0) {
919*b636d99dSDavid van Moolenbroek 		        first = 0;
920*b636d99dSDavid van Moolenbroek 			firstval = o / OIDMUX;
921*b636d99dSDavid van Moolenbroek 			if (firstval > 2) firstval = 2;
922*b636d99dSDavid van Moolenbroek 			o -= firstval * OIDMUX;
923*b636d99dSDavid van Moolenbroek 			if (*oidlen < oidsize) {
924*b636d99dSDavid van Moolenbroek 			    oid[(*oidlen)++] = firstval;
925*b636d99dSDavid van Moolenbroek 			}
926*b636d99dSDavid van Moolenbroek 		}
927*b636d99dSDavid van Moolenbroek 		if (*oidlen < oidsize) {
928*b636d99dSDavid van Moolenbroek 			oid[(*oidlen)++] = o;
929*b636d99dSDavid van Moolenbroek 		}
930*b636d99dSDavid van Moolenbroek 		o = 0;
931*b636d99dSDavid van Moolenbroek 	}
932*b636d99dSDavid van Moolenbroek 	return 0;
933*b636d99dSDavid van Moolenbroek 
934*b636d99dSDavid van Moolenbroek trunc:
935*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "%s", tstr));
936*b636d99dSDavid van Moolenbroek 	return -1;
937*b636d99dSDavid van Moolenbroek }
938*b636d99dSDavid van Moolenbroek 
smi_check_type(SmiBasetype basetype,int be)939*b636d99dSDavid van Moolenbroek static int smi_check_type(SmiBasetype basetype, int be)
940*b636d99dSDavid van Moolenbroek {
941*b636d99dSDavid van Moolenbroek     int i;
942*b636d99dSDavid van Moolenbroek 
943*b636d99dSDavid van Moolenbroek     for (i = 0; smi2betab[i].basetype != SMI_BASETYPE_UNKNOWN; i++) {
944*b636d99dSDavid van Moolenbroek 	if (smi2betab[i].basetype == basetype && smi2betab[i].be == be) {
945*b636d99dSDavid van Moolenbroek 	    return 1;
946*b636d99dSDavid van Moolenbroek 	}
947*b636d99dSDavid van Moolenbroek     }
948*b636d99dSDavid van Moolenbroek 
949*b636d99dSDavid van Moolenbroek     return 0;
950*b636d99dSDavid van Moolenbroek }
951*b636d99dSDavid van Moolenbroek 
smi_check_a_range(SmiType * smiType,SmiRange * smiRange,struct be * elem)952*b636d99dSDavid van Moolenbroek static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange,
953*b636d99dSDavid van Moolenbroek 			     struct be *elem)
954*b636d99dSDavid van Moolenbroek {
955*b636d99dSDavid van Moolenbroek     int ok = 1;
956*b636d99dSDavid van Moolenbroek 
957*b636d99dSDavid van Moolenbroek     switch (smiType->basetype) {
958*b636d99dSDavid van Moolenbroek     case SMI_BASETYPE_OBJECTIDENTIFIER:
959*b636d99dSDavid van Moolenbroek     case SMI_BASETYPE_OCTETSTRING:
960*b636d99dSDavid van Moolenbroek 	if (smiRange->minValue.value.unsigned32
961*b636d99dSDavid van Moolenbroek 	    == smiRange->maxValue.value.unsigned32) {
962*b636d99dSDavid van Moolenbroek 	    ok = (elem->asnlen == smiRange->minValue.value.unsigned32);
963*b636d99dSDavid van Moolenbroek 	} else {
964*b636d99dSDavid van Moolenbroek 	    ok = (elem->asnlen >= smiRange->minValue.value.unsigned32
965*b636d99dSDavid van Moolenbroek 		  && elem->asnlen <= smiRange->maxValue.value.unsigned32);
966*b636d99dSDavid van Moolenbroek 	}
967*b636d99dSDavid van Moolenbroek 	break;
968*b636d99dSDavid van Moolenbroek 
969*b636d99dSDavid van Moolenbroek     case SMI_BASETYPE_INTEGER32:
970*b636d99dSDavid van Moolenbroek 	ok = (elem->data.integer >= smiRange->minValue.value.integer32
971*b636d99dSDavid van Moolenbroek 	      && elem->data.integer <= smiRange->maxValue.value.integer32);
972*b636d99dSDavid van Moolenbroek 	break;
973*b636d99dSDavid van Moolenbroek 
974*b636d99dSDavid van Moolenbroek     case SMI_BASETYPE_UNSIGNED32:
975*b636d99dSDavid van Moolenbroek 	ok = (elem->data.uns >= smiRange->minValue.value.unsigned32
976*b636d99dSDavid van Moolenbroek 	      && elem->data.uns <= smiRange->maxValue.value.unsigned32);
977*b636d99dSDavid van Moolenbroek 	break;
978*b636d99dSDavid van Moolenbroek 
979*b636d99dSDavid van Moolenbroek     case SMI_BASETYPE_UNSIGNED64:
980*b636d99dSDavid van Moolenbroek 	/* XXX */
981*b636d99dSDavid van Moolenbroek 	break;
982*b636d99dSDavid van Moolenbroek 
983*b636d99dSDavid van Moolenbroek 	/* case SMI_BASETYPE_INTEGER64: SMIng */
984*b636d99dSDavid van Moolenbroek 	/* case SMI_BASETYPE_FLOAT32: SMIng */
985*b636d99dSDavid van Moolenbroek 	/* case SMI_BASETYPE_FLOAT64: SMIng */
986*b636d99dSDavid van Moolenbroek 	/* case SMI_BASETYPE_FLOAT128: SMIng */
987*b636d99dSDavid van Moolenbroek 
988*b636d99dSDavid van Moolenbroek     case SMI_BASETYPE_ENUM:
989*b636d99dSDavid van Moolenbroek     case SMI_BASETYPE_BITS:
990*b636d99dSDavid van Moolenbroek     case SMI_BASETYPE_UNKNOWN:
991*b636d99dSDavid van Moolenbroek 	ok = 1;
992*b636d99dSDavid van Moolenbroek 	break;
993*b636d99dSDavid van Moolenbroek 
994*b636d99dSDavid van Moolenbroek     default:
995*b636d99dSDavid van Moolenbroek 	ok = 0;
996*b636d99dSDavid van Moolenbroek 	break;
997*b636d99dSDavid van Moolenbroek     }
998*b636d99dSDavid van Moolenbroek 
999*b636d99dSDavid van Moolenbroek     return ok;
1000*b636d99dSDavid van Moolenbroek }
1001*b636d99dSDavid van Moolenbroek 
smi_check_range(SmiType * smiType,struct be * elem)1002*b636d99dSDavid van Moolenbroek static int smi_check_range(SmiType *smiType, struct be *elem)
1003*b636d99dSDavid van Moolenbroek {
1004*b636d99dSDavid van Moolenbroek         SmiRange *smiRange;
1005*b636d99dSDavid van Moolenbroek 	int ok = 1;
1006*b636d99dSDavid van Moolenbroek 
1007*b636d99dSDavid van Moolenbroek 	for (smiRange = smiGetFirstRange(smiType);
1008*b636d99dSDavid van Moolenbroek 	     smiRange;
1009*b636d99dSDavid van Moolenbroek 	     smiRange = smiGetNextRange(smiRange)) {
1010*b636d99dSDavid van Moolenbroek 
1011*b636d99dSDavid van Moolenbroek 	    ok = smi_check_a_range(smiType, smiRange, elem);
1012*b636d99dSDavid van Moolenbroek 
1013*b636d99dSDavid van Moolenbroek 	    if (ok) {
1014*b636d99dSDavid van Moolenbroek 		break;
1015*b636d99dSDavid van Moolenbroek 	    }
1016*b636d99dSDavid van Moolenbroek 	}
1017*b636d99dSDavid van Moolenbroek 
1018*b636d99dSDavid van Moolenbroek 	if (ok) {
1019*b636d99dSDavid van Moolenbroek 	    SmiType *parentType;
1020*b636d99dSDavid van Moolenbroek 	    parentType = smiGetParentType(smiType);
1021*b636d99dSDavid van Moolenbroek 	    if (parentType) {
1022*b636d99dSDavid van Moolenbroek 		ok = smi_check_range(parentType, elem);
1023*b636d99dSDavid van Moolenbroek 	    }
1024*b636d99dSDavid van Moolenbroek 	}
1025*b636d99dSDavid van Moolenbroek 
1026*b636d99dSDavid van Moolenbroek 	return ok;
1027*b636d99dSDavid van Moolenbroek }
1028*b636d99dSDavid van Moolenbroek 
1029*b636d99dSDavid van Moolenbroek static SmiNode *
smi_print_variable(netdissect_options * ndo,struct be * elem,int * status)1030*b636d99dSDavid van Moolenbroek smi_print_variable(netdissect_options *ndo,
1031*b636d99dSDavid van Moolenbroek                    struct be *elem, int *status)
1032*b636d99dSDavid van Moolenbroek {
1033*b636d99dSDavid van Moolenbroek 	unsigned int oid[128], oidlen;
1034*b636d99dSDavid van Moolenbroek 	SmiNode *smiNode = NULL;
1035*b636d99dSDavid van Moolenbroek 	unsigned int i;
1036*b636d99dSDavid van Moolenbroek 
1037*b636d99dSDavid van Moolenbroek 	*status = smi_decode_oid(ndo, elem, oid, sizeof(oid) / sizeof(unsigned int),
1038*b636d99dSDavid van Moolenbroek 	    &oidlen);
1039*b636d99dSDavid van Moolenbroek 	if (*status < 0)
1040*b636d99dSDavid van Moolenbroek 		return NULL;
1041*b636d99dSDavid van Moolenbroek 	smiNode = smiGetNodeByOID(oidlen, oid);
1042*b636d99dSDavid van Moolenbroek 	if (! smiNode) {
1043*b636d99dSDavid van Moolenbroek 		*status = asn1_print(ndo, elem);
1044*b636d99dSDavid van Moolenbroek 		return NULL;
1045*b636d99dSDavid van Moolenbroek 	}
1046*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1047*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%s::", smiGetNodeModule(smiNode)->name));
1048*b636d99dSDavid van Moolenbroek 	}
1049*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "%s", smiNode->name));
1050*b636d99dSDavid van Moolenbroek 	if (smiNode->oidlen < oidlen) {
1051*b636d99dSDavid van Moolenbroek 		for (i = smiNode->oidlen; i < oidlen; i++) {
1052*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, ".%u", oid[i]));
1053*b636d99dSDavid van Moolenbroek 		}
1054*b636d99dSDavid van Moolenbroek 	}
1055*b636d99dSDavid van Moolenbroek 	*status = 0;
1056*b636d99dSDavid van Moolenbroek 	return smiNode;
1057*b636d99dSDavid van Moolenbroek }
1058*b636d99dSDavid van Moolenbroek 
1059*b636d99dSDavid van Moolenbroek static int
smi_print_value(netdissect_options * ndo,SmiNode * smiNode,u_char pduid,struct be * elem)1060*b636d99dSDavid van Moolenbroek smi_print_value(netdissect_options *ndo,
1061*b636d99dSDavid van Moolenbroek                 SmiNode *smiNode, u_char pduid, struct be *elem)
1062*b636d99dSDavid van Moolenbroek {
1063*b636d99dSDavid van Moolenbroek 	unsigned int i, oid[128], oidlen;
1064*b636d99dSDavid van Moolenbroek 	SmiType *smiType;
1065*b636d99dSDavid van Moolenbroek 	SmiNamedNumber *nn;
1066*b636d99dSDavid van Moolenbroek 	int done = 0;
1067*b636d99dSDavid van Moolenbroek 
1068*b636d99dSDavid van Moolenbroek 	if (! smiNode || ! (smiNode->nodekind
1069*b636d99dSDavid van Moolenbroek 			    & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) {
1070*b636d99dSDavid van Moolenbroek 	    return asn1_print(ndo, elem);
1071*b636d99dSDavid van Moolenbroek 	}
1072*b636d99dSDavid van Moolenbroek 
1073*b636d99dSDavid van Moolenbroek 	if (elem->type == BE_NOSUCHOBJECT
1074*b636d99dSDavid van Moolenbroek 	    || elem->type == BE_NOSUCHINST
1075*b636d99dSDavid van Moolenbroek 	    || elem->type == BE_ENDOFMIBVIEW) {
1076*b636d99dSDavid van Moolenbroek 	    return asn1_print(ndo, elem);
1077*b636d99dSDavid van Moolenbroek 	}
1078*b636d99dSDavid van Moolenbroek 
1079*b636d99dSDavid van Moolenbroek 	if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) {
1080*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, "[notNotifyable]"));
1081*b636d99dSDavid van Moolenbroek 	}
1082*b636d99dSDavid van Moolenbroek 
1083*b636d99dSDavid van Moolenbroek 	if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) {
1084*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, "[notReadable]"));
1085*b636d99dSDavid van Moolenbroek 	}
1086*b636d99dSDavid van Moolenbroek 
1087*b636d99dSDavid van Moolenbroek 	if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) {
1088*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, "[notWritable]"));
1089*b636d99dSDavid van Moolenbroek 	}
1090*b636d99dSDavid van Moolenbroek 
1091*b636d99dSDavid van Moolenbroek 	if (RESPONSE_CLASS(pduid)
1092*b636d99dSDavid van Moolenbroek 	    && smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) {
1093*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, "[noAccess]"));
1094*b636d99dSDavid van Moolenbroek 	}
1095*b636d99dSDavid van Moolenbroek 
1096*b636d99dSDavid van Moolenbroek 	smiType = smiGetNodeType(smiNode);
1097*b636d99dSDavid van Moolenbroek 	if (! smiType) {
1098*b636d99dSDavid van Moolenbroek 	    return asn1_print(ndo, elem);
1099*b636d99dSDavid van Moolenbroek 	}
1100*b636d99dSDavid van Moolenbroek 
1101*b636d99dSDavid van Moolenbroek 	if (! smi_check_type(smiType->basetype, elem->type)) {
1102*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, "[wrongType]"));
1103*b636d99dSDavid van Moolenbroek 	}
1104*b636d99dSDavid van Moolenbroek 
1105*b636d99dSDavid van Moolenbroek 	if (! smi_check_range(smiType, elem)) {
1106*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, "[outOfRange]"));
1107*b636d99dSDavid van Moolenbroek 	}
1108*b636d99dSDavid van Moolenbroek 
1109*b636d99dSDavid van Moolenbroek 	/* resolve bits to named bits */
1110*b636d99dSDavid van Moolenbroek 
1111*b636d99dSDavid van Moolenbroek 	/* check whether instance identifier is valid */
1112*b636d99dSDavid van Moolenbroek 
1113*b636d99dSDavid van Moolenbroek 	/* apply display hints (integer, octetstring) */
1114*b636d99dSDavid van Moolenbroek 
1115*b636d99dSDavid van Moolenbroek 	/* convert instance identifier to index type values */
1116*b636d99dSDavid van Moolenbroek 
1117*b636d99dSDavid van Moolenbroek 	switch (elem->type) {
1118*b636d99dSDavid van Moolenbroek 	case BE_OID:
1119*b636d99dSDavid van Moolenbroek 	        if (smiType->basetype == SMI_BASETYPE_BITS) {
1120*b636d99dSDavid van Moolenbroek 		        /* print bit labels */
1121*b636d99dSDavid van Moolenbroek 		} else {
1122*b636d99dSDavid van Moolenbroek 		        smi_decode_oid(ndo, elem, oid,
1123*b636d99dSDavid van Moolenbroek 				       sizeof(oid)/sizeof(unsigned int),
1124*b636d99dSDavid van Moolenbroek 				       &oidlen);
1125*b636d99dSDavid van Moolenbroek 			smiNode = smiGetNodeByOID(oidlen, oid);
1126*b636d99dSDavid van Moolenbroek 			if (smiNode) {
1127*b636d99dSDavid van Moolenbroek 			        if (ndo->ndo_vflag) {
1128*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, "%s::", smiGetNodeModule(smiNode)->name));
1129*b636d99dSDavid van Moolenbroek 				}
1130*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "%s", smiNode->name));
1131*b636d99dSDavid van Moolenbroek 				if (smiNode->oidlen < oidlen) {
1132*b636d99dSDavid van Moolenbroek 				        for (i = smiNode->oidlen;
1133*b636d99dSDavid van Moolenbroek 					     i < oidlen; i++) {
1134*b636d99dSDavid van Moolenbroek 					        ND_PRINT((ndo, ".%u", oid[i]));
1135*b636d99dSDavid van Moolenbroek 					}
1136*b636d99dSDavid van Moolenbroek 				}
1137*b636d99dSDavid van Moolenbroek 				done++;
1138*b636d99dSDavid van Moolenbroek 			}
1139*b636d99dSDavid van Moolenbroek 		}
1140*b636d99dSDavid van Moolenbroek 		break;
1141*b636d99dSDavid van Moolenbroek 
1142*b636d99dSDavid van Moolenbroek 	case BE_INT:
1143*b636d99dSDavid van Moolenbroek 	        if (smiType->basetype == SMI_BASETYPE_ENUM) {
1144*b636d99dSDavid van Moolenbroek 		        for (nn = smiGetFirstNamedNumber(smiType);
1145*b636d99dSDavid van Moolenbroek 			     nn;
1146*b636d99dSDavid van Moolenbroek 			     nn = smiGetNextNamedNumber(nn)) {
1147*b636d99dSDavid van Moolenbroek 			         if (nn->value.value.integer32
1148*b636d99dSDavid van Moolenbroek 				     == elem->data.integer) {
1149*b636d99dSDavid van Moolenbroek 				         ND_PRINT((ndo, "%s", nn->name));
1150*b636d99dSDavid van Moolenbroek 					 ND_PRINT((ndo, "(%d)", elem->data.integer));
1151*b636d99dSDavid van Moolenbroek 					 done++;
1152*b636d99dSDavid van Moolenbroek 					 break;
1153*b636d99dSDavid van Moolenbroek 				}
1154*b636d99dSDavid van Moolenbroek 			}
1155*b636d99dSDavid van Moolenbroek 		}
1156*b636d99dSDavid van Moolenbroek 		break;
1157*b636d99dSDavid van Moolenbroek 	}
1158*b636d99dSDavid van Moolenbroek 
1159*b636d99dSDavid van Moolenbroek 	if (! done) {
1160*b636d99dSDavid van Moolenbroek 		return asn1_print(ndo, elem);
1161*b636d99dSDavid van Moolenbroek 	}
1162*b636d99dSDavid van Moolenbroek 	return 0;
1163*b636d99dSDavid van Moolenbroek }
1164*b636d99dSDavid van Moolenbroek #endif
1165*b636d99dSDavid van Moolenbroek 
1166*b636d99dSDavid van Moolenbroek /*
1167*b636d99dSDavid van Moolenbroek  * General SNMP header
1168*b636d99dSDavid van Moolenbroek  *	SEQUENCE {
1169*b636d99dSDavid van Moolenbroek  *		version INTEGER {version-1(0)},
1170*b636d99dSDavid van Moolenbroek  *		community OCTET STRING,
1171*b636d99dSDavid van Moolenbroek  *		data ANY	-- PDUs
1172*b636d99dSDavid van Moolenbroek  *	}
1173*b636d99dSDavid van Moolenbroek  * PDUs for all but Trap: (see rfc1157 from page 15 on)
1174*b636d99dSDavid van Moolenbroek  *	SEQUENCE {
1175*b636d99dSDavid van Moolenbroek  *		request-id INTEGER,
1176*b636d99dSDavid van Moolenbroek  *		error-status INTEGER,
1177*b636d99dSDavid van Moolenbroek  *		error-index INTEGER,
1178*b636d99dSDavid van Moolenbroek  *		varbindlist SEQUENCE OF
1179*b636d99dSDavid van Moolenbroek  *			SEQUENCE {
1180*b636d99dSDavid van Moolenbroek  *				name ObjectName,
1181*b636d99dSDavid van Moolenbroek  *				value ObjectValue
1182*b636d99dSDavid van Moolenbroek  *			}
1183*b636d99dSDavid van Moolenbroek  *	}
1184*b636d99dSDavid van Moolenbroek  * PDU for Trap:
1185*b636d99dSDavid van Moolenbroek  *	SEQUENCE {
1186*b636d99dSDavid van Moolenbroek  *		enterprise OBJECT IDENTIFIER,
1187*b636d99dSDavid van Moolenbroek  *		agent-addr NetworkAddress,
1188*b636d99dSDavid van Moolenbroek  *		generic-trap INTEGER,
1189*b636d99dSDavid van Moolenbroek  *		specific-trap INTEGER,
1190*b636d99dSDavid van Moolenbroek  *		time-stamp TimeTicks,
1191*b636d99dSDavid van Moolenbroek  *		varbindlist SEQUENCE OF
1192*b636d99dSDavid van Moolenbroek  *			SEQUENCE {
1193*b636d99dSDavid van Moolenbroek  *				name ObjectName,
1194*b636d99dSDavid van Moolenbroek  *				value ObjectValue
1195*b636d99dSDavid van Moolenbroek  *			}
1196*b636d99dSDavid van Moolenbroek  *	}
1197*b636d99dSDavid van Moolenbroek  */
1198*b636d99dSDavid van Moolenbroek 
1199*b636d99dSDavid van Moolenbroek /*
1200*b636d99dSDavid van Moolenbroek  * Decode SNMP varBind
1201*b636d99dSDavid van Moolenbroek  */
1202*b636d99dSDavid van Moolenbroek static void
varbind_print(netdissect_options * ndo,u_char pduid,const u_char * np,u_int length)1203*b636d99dSDavid van Moolenbroek varbind_print(netdissect_options *ndo,
1204*b636d99dSDavid van Moolenbroek               u_char pduid, const u_char *np, u_int length)
1205*b636d99dSDavid van Moolenbroek {
1206*b636d99dSDavid van Moolenbroek 	struct be elem;
1207*b636d99dSDavid van Moolenbroek 	int count = 0, ind;
1208*b636d99dSDavid van Moolenbroek #ifdef USE_LIBSMI
1209*b636d99dSDavid van Moolenbroek 	SmiNode *smiNode = NULL;
1210*b636d99dSDavid van Moolenbroek #endif
1211*b636d99dSDavid van Moolenbroek 	int status;
1212*b636d99dSDavid van Moolenbroek 
1213*b636d99dSDavid van Moolenbroek 	/* Sequence of varBind */
1214*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1215*b636d99dSDavid van Moolenbroek 		return;
1216*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_SEQ) {
1217*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[!SEQ of varbind]"));
1218*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1219*b636d99dSDavid van Moolenbroek 		return;
1220*b636d99dSDavid van Moolenbroek 	}
1221*b636d99dSDavid van Moolenbroek 	if ((u_int)count < length)
1222*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[%d extra after SEQ of varbind]", length - count));
1223*b636d99dSDavid van Moolenbroek 	/* descend */
1224*b636d99dSDavid van Moolenbroek 	length = elem.asnlen;
1225*b636d99dSDavid van Moolenbroek 	np = (u_char *)elem.data.raw;
1226*b636d99dSDavid van Moolenbroek 
1227*b636d99dSDavid van Moolenbroek 	for (ind = 1; length > 0; ind++) {
1228*b636d99dSDavid van Moolenbroek 		const u_char *vbend;
1229*b636d99dSDavid van Moolenbroek 		u_int vblength;
1230*b636d99dSDavid van Moolenbroek 
1231*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " "));
1232*b636d99dSDavid van Moolenbroek 
1233*b636d99dSDavid van Moolenbroek 		/* Sequence */
1234*b636d99dSDavid van Moolenbroek 		if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1235*b636d99dSDavid van Moolenbroek 			return;
1236*b636d99dSDavid van Moolenbroek 		if (elem.type != BE_SEQ) {
1237*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[!varbind]"));
1238*b636d99dSDavid van Moolenbroek 			asn1_print(ndo, &elem);
1239*b636d99dSDavid van Moolenbroek 			return;
1240*b636d99dSDavid van Moolenbroek 		}
1241*b636d99dSDavid van Moolenbroek 		vbend = np + count;
1242*b636d99dSDavid van Moolenbroek 		vblength = length - count;
1243*b636d99dSDavid van Moolenbroek 		/* descend */
1244*b636d99dSDavid van Moolenbroek 		length = elem.asnlen;
1245*b636d99dSDavid van Moolenbroek 		np = (u_char *)elem.data.raw;
1246*b636d99dSDavid van Moolenbroek 
1247*b636d99dSDavid van Moolenbroek 		/* objName (OID) */
1248*b636d99dSDavid van Moolenbroek 		if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1249*b636d99dSDavid van Moolenbroek 			return;
1250*b636d99dSDavid van Moolenbroek 		if (elem.type != BE_OID) {
1251*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[objName!=OID]"));
1252*b636d99dSDavid van Moolenbroek 			asn1_print(ndo, &elem);
1253*b636d99dSDavid van Moolenbroek 			return;
1254*b636d99dSDavid van Moolenbroek 		}
1255*b636d99dSDavid van Moolenbroek #ifdef USE_LIBSMI
1256*b636d99dSDavid van Moolenbroek 		smiNode = smi_print_variable(ndo, &elem, &status);
1257*b636d99dSDavid van Moolenbroek #else
1258*b636d99dSDavid van Moolenbroek 		status = asn1_print(ndo, &elem);
1259*b636d99dSDavid van Moolenbroek #endif
1260*b636d99dSDavid van Moolenbroek 		if (status < 0)
1261*b636d99dSDavid van Moolenbroek 			return;
1262*b636d99dSDavid van Moolenbroek 		length -= count;
1263*b636d99dSDavid van Moolenbroek 		np += count;
1264*b636d99dSDavid van Moolenbroek 
1265*b636d99dSDavid van Moolenbroek 		if (pduid != GETREQ && pduid != GETNEXTREQ
1266*b636d99dSDavid van Moolenbroek 		    && pduid != GETBULKREQ)
1267*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "="));
1268*b636d99dSDavid van Moolenbroek 
1269*b636d99dSDavid van Moolenbroek 		/* objVal (ANY) */
1270*b636d99dSDavid van Moolenbroek 		if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1271*b636d99dSDavid van Moolenbroek 			return;
1272*b636d99dSDavid van Moolenbroek 		if (pduid == GETREQ || pduid == GETNEXTREQ
1273*b636d99dSDavid van Moolenbroek 		    || pduid == GETBULKREQ) {
1274*b636d99dSDavid van Moolenbroek 			if (elem.type != BE_NULL) {
1275*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "[objVal!=NULL]"));
1276*b636d99dSDavid van Moolenbroek 				if (asn1_print(ndo, &elem) < 0)
1277*b636d99dSDavid van Moolenbroek 					return;
1278*b636d99dSDavid van Moolenbroek 			}
1279*b636d99dSDavid van Moolenbroek 		} else {
1280*b636d99dSDavid van Moolenbroek 		        if (elem.type != BE_NULL) {
1281*b636d99dSDavid van Moolenbroek #ifdef USE_LIBSMI
1282*b636d99dSDavid van Moolenbroek 				status = smi_print_value(ndo, smiNode, pduid, &elem);
1283*b636d99dSDavid van Moolenbroek #else
1284*b636d99dSDavid van Moolenbroek 				status = asn1_print(ndo, &elem);
1285*b636d99dSDavid van Moolenbroek #endif
1286*b636d99dSDavid van Moolenbroek 			}
1287*b636d99dSDavid van Moolenbroek 			if (status < 0)
1288*b636d99dSDavid van Moolenbroek 				return;
1289*b636d99dSDavid van Moolenbroek 		}
1290*b636d99dSDavid van Moolenbroek 		length = vblength;
1291*b636d99dSDavid van Moolenbroek 		np = vbend;
1292*b636d99dSDavid van Moolenbroek 	}
1293*b636d99dSDavid van Moolenbroek }
1294*b636d99dSDavid van Moolenbroek 
1295*b636d99dSDavid van Moolenbroek /*
1296*b636d99dSDavid van Moolenbroek  * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest,
1297*b636d99dSDavid van Moolenbroek  * GetBulk, Inform, V2Trap, and Report
1298*b636d99dSDavid van Moolenbroek  */
1299*b636d99dSDavid van Moolenbroek static void
snmppdu_print(netdissect_options * ndo,u_short pduid,const u_char * np,u_int length)1300*b636d99dSDavid van Moolenbroek snmppdu_print(netdissect_options *ndo,
1301*b636d99dSDavid van Moolenbroek               u_short pduid, const u_char *np, u_int length)
1302*b636d99dSDavid van Moolenbroek {
1303*b636d99dSDavid van Moolenbroek 	struct be elem;
1304*b636d99dSDavid van Moolenbroek 	int count = 0, error;
1305*b636d99dSDavid van Moolenbroek 
1306*b636d99dSDavid van Moolenbroek 	/* reqId (Integer) */
1307*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1308*b636d99dSDavid van Moolenbroek 		return;
1309*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1310*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[reqId!=INT]"));
1311*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1312*b636d99dSDavid van Moolenbroek 		return;
1313*b636d99dSDavid van Moolenbroek 	}
1314*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag)
1315*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "R=%d ", elem.data.integer));
1316*b636d99dSDavid van Moolenbroek 	length -= count;
1317*b636d99dSDavid van Moolenbroek 	np += count;
1318*b636d99dSDavid van Moolenbroek 
1319*b636d99dSDavid van Moolenbroek 	/* errorStatus (Integer) */
1320*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1321*b636d99dSDavid van Moolenbroek 		return;
1322*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1323*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[errorStatus!=INT]"));
1324*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1325*b636d99dSDavid van Moolenbroek 		return;
1326*b636d99dSDavid van Moolenbroek 	}
1327*b636d99dSDavid van Moolenbroek 	error = 0;
1328*b636d99dSDavid van Moolenbroek 	if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
1329*b636d99dSDavid van Moolenbroek 	    || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
1330*b636d99dSDavid van Moolenbroek 	    && elem.data.integer != 0) {
1331*b636d99dSDavid van Moolenbroek 		char errbuf[20];
1332*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[errorStatus(%s)!=0]",
1333*b636d99dSDavid van Moolenbroek 			DECODE_ErrorStatus(elem.data.integer)));
1334*b636d99dSDavid van Moolenbroek 	} else if (pduid == GETBULKREQ) {
1335*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " N=%d", elem.data.integer));
1336*b636d99dSDavid van Moolenbroek 	} else if (elem.data.integer != 0) {
1337*b636d99dSDavid van Moolenbroek 		char errbuf[20];
1338*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " %s", DECODE_ErrorStatus(elem.data.integer)));
1339*b636d99dSDavid van Moolenbroek 		error = elem.data.integer;
1340*b636d99dSDavid van Moolenbroek 	}
1341*b636d99dSDavid van Moolenbroek 	length -= count;
1342*b636d99dSDavid van Moolenbroek 	np += count;
1343*b636d99dSDavid van Moolenbroek 
1344*b636d99dSDavid van Moolenbroek 	/* errorIndex (Integer) */
1345*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1346*b636d99dSDavid van Moolenbroek 		return;
1347*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1348*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[errorIndex!=INT]"));
1349*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1350*b636d99dSDavid van Moolenbroek 		return;
1351*b636d99dSDavid van Moolenbroek 	}
1352*b636d99dSDavid van Moolenbroek 	if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
1353*b636d99dSDavid van Moolenbroek 	    || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
1354*b636d99dSDavid van Moolenbroek 	    && elem.data.integer != 0)
1355*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[errorIndex(%d)!=0]", elem.data.integer));
1356*b636d99dSDavid van Moolenbroek 	else if (pduid == GETBULKREQ)
1357*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " M=%d", elem.data.integer));
1358*b636d99dSDavid van Moolenbroek 	else if (elem.data.integer != 0) {
1359*b636d99dSDavid van Moolenbroek 		if (!error)
1360*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[errorIndex(%d) w/o errorStatus]", elem.data.integer));
1361*b636d99dSDavid van Moolenbroek 		else {
1362*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "@%d", elem.data.integer));
1363*b636d99dSDavid van Moolenbroek 			error = elem.data.integer;
1364*b636d99dSDavid van Moolenbroek 		}
1365*b636d99dSDavid van Moolenbroek 	} else if (error) {
1366*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[errorIndex==0]"));
1367*b636d99dSDavid van Moolenbroek 		error = 0;
1368*b636d99dSDavid van Moolenbroek 	}
1369*b636d99dSDavid van Moolenbroek 	length -= count;
1370*b636d99dSDavid van Moolenbroek 	np += count;
1371*b636d99dSDavid van Moolenbroek 
1372*b636d99dSDavid van Moolenbroek 	varbind_print(ndo, pduid, np, length);
1373*b636d99dSDavid van Moolenbroek 	return;
1374*b636d99dSDavid van Moolenbroek }
1375*b636d99dSDavid van Moolenbroek 
1376*b636d99dSDavid van Moolenbroek /*
1377*b636d99dSDavid van Moolenbroek  * Decode SNMP Trap PDU
1378*b636d99dSDavid van Moolenbroek  */
1379*b636d99dSDavid van Moolenbroek static void
trappdu_print(netdissect_options * ndo,const u_char * np,u_int length)1380*b636d99dSDavid van Moolenbroek trappdu_print(netdissect_options *ndo,
1381*b636d99dSDavid van Moolenbroek               const u_char *np, u_int length)
1382*b636d99dSDavid van Moolenbroek {
1383*b636d99dSDavid van Moolenbroek 	struct be elem;
1384*b636d99dSDavid van Moolenbroek 	int count = 0, generic;
1385*b636d99dSDavid van Moolenbroek 
1386*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " "));
1387*b636d99dSDavid van Moolenbroek 
1388*b636d99dSDavid van Moolenbroek 	/* enterprise (oid) */
1389*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1390*b636d99dSDavid van Moolenbroek 		return;
1391*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_OID) {
1392*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[enterprise!=OID]"));
1393*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1394*b636d99dSDavid van Moolenbroek 		return;
1395*b636d99dSDavid van Moolenbroek 	}
1396*b636d99dSDavid van Moolenbroek 	if (asn1_print(ndo, &elem) < 0)
1397*b636d99dSDavid van Moolenbroek 		return;
1398*b636d99dSDavid van Moolenbroek 	length -= count;
1399*b636d99dSDavid van Moolenbroek 	np += count;
1400*b636d99dSDavid van Moolenbroek 
1401*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " "));
1402*b636d99dSDavid van Moolenbroek 
1403*b636d99dSDavid van Moolenbroek 	/* agent-addr (inetaddr) */
1404*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1405*b636d99dSDavid van Moolenbroek 		return;
1406*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INETADDR) {
1407*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[agent-addr!=INETADDR]"));
1408*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1409*b636d99dSDavid van Moolenbroek 		return;
1410*b636d99dSDavid van Moolenbroek 	}
1411*b636d99dSDavid van Moolenbroek 	if (asn1_print(ndo, &elem) < 0)
1412*b636d99dSDavid van Moolenbroek 		return;
1413*b636d99dSDavid van Moolenbroek 	length -= count;
1414*b636d99dSDavid van Moolenbroek 	np += count;
1415*b636d99dSDavid van Moolenbroek 
1416*b636d99dSDavid van Moolenbroek 	/* generic-trap (Integer) */
1417*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1418*b636d99dSDavid van Moolenbroek 		return;
1419*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1420*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[generic-trap!=INT]"));
1421*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1422*b636d99dSDavid van Moolenbroek 		return;
1423*b636d99dSDavid van Moolenbroek 	}
1424*b636d99dSDavid van Moolenbroek 	generic = elem.data.integer;
1425*b636d99dSDavid van Moolenbroek 	{
1426*b636d99dSDavid van Moolenbroek 		char buf[20];
1427*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " %s", DECODE_GenericTrap(generic)));
1428*b636d99dSDavid van Moolenbroek 	}
1429*b636d99dSDavid van Moolenbroek 	length -= count;
1430*b636d99dSDavid van Moolenbroek 	np += count;
1431*b636d99dSDavid van Moolenbroek 
1432*b636d99dSDavid van Moolenbroek 	/* specific-trap (Integer) */
1433*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1434*b636d99dSDavid van Moolenbroek 		return;
1435*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1436*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[specific-trap!=INT]"));
1437*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1438*b636d99dSDavid van Moolenbroek 		return;
1439*b636d99dSDavid van Moolenbroek 	}
1440*b636d99dSDavid van Moolenbroek 	if (generic != GT_ENTERPRISE) {
1441*b636d99dSDavid van Moolenbroek 		if (elem.data.integer != 0)
1442*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[specific-trap(%d)!=0]", elem.data.integer));
1443*b636d99dSDavid van Moolenbroek 	} else
1444*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " s=%d", elem.data.integer));
1445*b636d99dSDavid van Moolenbroek 	length -= count;
1446*b636d99dSDavid van Moolenbroek 	np += count;
1447*b636d99dSDavid van Moolenbroek 
1448*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " "));
1449*b636d99dSDavid van Moolenbroek 
1450*b636d99dSDavid van Moolenbroek 	/* time-stamp (TimeTicks) */
1451*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1452*b636d99dSDavid van Moolenbroek 		return;
1453*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_UNS) {			/* XXX */
1454*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[time-stamp!=TIMETICKS]"));
1455*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1456*b636d99dSDavid van Moolenbroek 		return;
1457*b636d99dSDavid van Moolenbroek 	}
1458*b636d99dSDavid van Moolenbroek 	if (asn1_print(ndo, &elem) < 0)
1459*b636d99dSDavid van Moolenbroek 		return;
1460*b636d99dSDavid van Moolenbroek 	length -= count;
1461*b636d99dSDavid van Moolenbroek 	np += count;
1462*b636d99dSDavid van Moolenbroek 
1463*b636d99dSDavid van Moolenbroek 	varbind_print(ndo, TRAP, np, length);
1464*b636d99dSDavid van Moolenbroek 	return;
1465*b636d99dSDavid van Moolenbroek }
1466*b636d99dSDavid van Moolenbroek 
1467*b636d99dSDavid van Moolenbroek /*
1468*b636d99dSDavid van Moolenbroek  * Decode arbitrary SNMP PDUs.
1469*b636d99dSDavid van Moolenbroek  */
1470*b636d99dSDavid van Moolenbroek static void
pdu_print(netdissect_options * ndo,const u_char * np,u_int length,int version)1471*b636d99dSDavid van Moolenbroek pdu_print(netdissect_options *ndo,
1472*b636d99dSDavid van Moolenbroek           const u_char *np, u_int length, int version)
1473*b636d99dSDavid van Moolenbroek {
1474*b636d99dSDavid van Moolenbroek 	struct be pdu;
1475*b636d99dSDavid van Moolenbroek 	int count = 0;
1476*b636d99dSDavid van Moolenbroek 
1477*b636d99dSDavid van Moolenbroek 	/* PDU (Context) */
1478*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &pdu)) < 0)
1479*b636d99dSDavid van Moolenbroek 		return;
1480*b636d99dSDavid van Moolenbroek 	if (pdu.type != BE_PDU) {
1481*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[no PDU]"));
1482*b636d99dSDavid van Moolenbroek 		return;
1483*b636d99dSDavid van Moolenbroek 	}
1484*b636d99dSDavid van Moolenbroek 	if ((u_int)count < length)
1485*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[%d extra after PDU]", length - count));
1486*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1487*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "{ "));
1488*b636d99dSDavid van Moolenbroek 	}
1489*b636d99dSDavid van Moolenbroek 	if (asn1_print(ndo, &pdu) < 0)
1490*b636d99dSDavid van Moolenbroek 		return;
1491*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " "));
1492*b636d99dSDavid van Moolenbroek 	/* descend into PDU */
1493*b636d99dSDavid van Moolenbroek 	length = pdu.asnlen;
1494*b636d99dSDavid van Moolenbroek 	np = (u_char *)pdu.data.raw;
1495*b636d99dSDavid van Moolenbroek 
1496*b636d99dSDavid van Moolenbroek 	if (version == SNMP_VERSION_1 &&
1497*b636d99dSDavid van Moolenbroek 	    (pdu.id == GETBULKREQ || pdu.id == INFORMREQ ||
1498*b636d99dSDavid van Moolenbroek 	     pdu.id == V2TRAP || pdu.id == REPORT)) {
1499*b636d99dSDavid van Moolenbroek 	        ND_PRINT((ndo, "[v2 PDU in v1 message]"));
1500*b636d99dSDavid van Moolenbroek 		return;
1501*b636d99dSDavid van Moolenbroek 	}
1502*b636d99dSDavid van Moolenbroek 
1503*b636d99dSDavid van Moolenbroek 	if (version == SNMP_VERSION_2 && pdu.id == TRAP) {
1504*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[v1 PDU in v2 message]"));
1505*b636d99dSDavid van Moolenbroek 		return;
1506*b636d99dSDavid van Moolenbroek 	}
1507*b636d99dSDavid van Moolenbroek 
1508*b636d99dSDavid van Moolenbroek 	switch (pdu.id) {
1509*b636d99dSDavid van Moolenbroek 	case TRAP:
1510*b636d99dSDavid van Moolenbroek 		trappdu_print(ndo, np, length);
1511*b636d99dSDavid van Moolenbroek 		break;
1512*b636d99dSDavid van Moolenbroek 	case GETREQ:
1513*b636d99dSDavid van Moolenbroek 	case GETNEXTREQ:
1514*b636d99dSDavid van Moolenbroek 	case GETRESP:
1515*b636d99dSDavid van Moolenbroek 	case SETREQ:
1516*b636d99dSDavid van Moolenbroek 	case GETBULKREQ:
1517*b636d99dSDavid van Moolenbroek 	case INFORMREQ:
1518*b636d99dSDavid van Moolenbroek 	case V2TRAP:
1519*b636d99dSDavid van Moolenbroek 	case REPORT:
1520*b636d99dSDavid van Moolenbroek 		snmppdu_print(ndo, pdu.id, np, length);
1521*b636d99dSDavid van Moolenbroek 		break;
1522*b636d99dSDavid van Moolenbroek 	}
1523*b636d99dSDavid van Moolenbroek 
1524*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1525*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " } "));
1526*b636d99dSDavid van Moolenbroek 	}
1527*b636d99dSDavid van Moolenbroek }
1528*b636d99dSDavid van Moolenbroek 
1529*b636d99dSDavid van Moolenbroek /*
1530*b636d99dSDavid van Moolenbroek  * Decode a scoped SNMP PDU.
1531*b636d99dSDavid van Moolenbroek  */
1532*b636d99dSDavid van Moolenbroek static void
scopedpdu_print(netdissect_options * ndo,const u_char * np,u_int length,int version)1533*b636d99dSDavid van Moolenbroek scopedpdu_print(netdissect_options *ndo,
1534*b636d99dSDavid van Moolenbroek                 const u_char *np, u_int length, int version)
1535*b636d99dSDavid van Moolenbroek {
1536*b636d99dSDavid van Moolenbroek 	struct be elem;
1537*b636d99dSDavid van Moolenbroek 	int i, count = 0;
1538*b636d99dSDavid van Moolenbroek 
1539*b636d99dSDavid van Moolenbroek 	/* Sequence */
1540*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1541*b636d99dSDavid van Moolenbroek 		return;
1542*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_SEQ) {
1543*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[!scoped PDU]"));
1544*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1545*b636d99dSDavid van Moolenbroek 		return;
1546*b636d99dSDavid van Moolenbroek 	}
1547*b636d99dSDavid van Moolenbroek 	length = elem.asnlen;
1548*b636d99dSDavid van Moolenbroek 	np = (u_char *)elem.data.raw;
1549*b636d99dSDavid van Moolenbroek 
1550*b636d99dSDavid van Moolenbroek 	/* contextEngineID (OCTET STRING) */
1551*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1552*b636d99dSDavid van Moolenbroek 		return;
1553*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_STR) {
1554*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[contextEngineID!=STR]"));
1555*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1556*b636d99dSDavid van Moolenbroek 		return;
1557*b636d99dSDavid van Moolenbroek 	}
1558*b636d99dSDavid van Moolenbroek 	length -= count;
1559*b636d99dSDavid van Moolenbroek 	np += count;
1560*b636d99dSDavid van Moolenbroek 
1561*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "E= "));
1562*b636d99dSDavid van Moolenbroek 	for (i = 0; i < (int)elem.asnlen; i++) {
1563*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "0x%02X", elem.data.str[i]));
1564*b636d99dSDavid van Moolenbroek 	}
1565*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " "));
1566*b636d99dSDavid van Moolenbroek 
1567*b636d99dSDavid van Moolenbroek 	/* contextName (OCTET STRING) */
1568*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1569*b636d99dSDavid van Moolenbroek 		return;
1570*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_STR) {
1571*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[contextName!=STR]"));
1572*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1573*b636d99dSDavid van Moolenbroek 		return;
1574*b636d99dSDavid van Moolenbroek 	}
1575*b636d99dSDavid van Moolenbroek 	length -= count;
1576*b636d99dSDavid van Moolenbroek 	np += count;
1577*b636d99dSDavid van Moolenbroek 
1578*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "C=%.*s ", (int)elem.asnlen, elem.data.str));
1579*b636d99dSDavid van Moolenbroek 
1580*b636d99dSDavid van Moolenbroek 	pdu_print(ndo, np, length, version);
1581*b636d99dSDavid van Moolenbroek }
1582*b636d99dSDavid van Moolenbroek 
1583*b636d99dSDavid van Moolenbroek /*
1584*b636d99dSDavid van Moolenbroek  * Decode SNMP Community Header (SNMPv1 and SNMPv2c)
1585*b636d99dSDavid van Moolenbroek  */
1586*b636d99dSDavid van Moolenbroek static void
community_print(netdissect_options * ndo,const u_char * np,u_int length,int version)1587*b636d99dSDavid van Moolenbroek community_print(netdissect_options *ndo,
1588*b636d99dSDavid van Moolenbroek                 const u_char *np, u_int length, int version)
1589*b636d99dSDavid van Moolenbroek {
1590*b636d99dSDavid van Moolenbroek 	struct be elem;
1591*b636d99dSDavid van Moolenbroek 	int count = 0;
1592*b636d99dSDavid van Moolenbroek 
1593*b636d99dSDavid van Moolenbroek 	/* Community (String) */
1594*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1595*b636d99dSDavid van Moolenbroek 		return;
1596*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_STR) {
1597*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[comm!=STR]"));
1598*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1599*b636d99dSDavid van Moolenbroek 		return;
1600*b636d99dSDavid van Moolenbroek 	}
1601*b636d99dSDavid van Moolenbroek 	/* default community */
1602*b636d99dSDavid van Moolenbroek 	if (!(elem.asnlen == sizeof(DEF_COMMUNITY) - 1 &&
1603*b636d99dSDavid van Moolenbroek 	    strncmp((char *)elem.data.str, DEF_COMMUNITY,
1604*b636d99dSDavid van Moolenbroek 	            sizeof(DEF_COMMUNITY) - 1) == 0))
1605*b636d99dSDavid van Moolenbroek 		/* ! "public" */
1606*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "C=%.*s ", (int)elem.asnlen, elem.data.str));
1607*b636d99dSDavid van Moolenbroek 	length -= count;
1608*b636d99dSDavid van Moolenbroek 	np += count;
1609*b636d99dSDavid van Moolenbroek 
1610*b636d99dSDavid van Moolenbroek 	pdu_print(ndo, np, length, version);
1611*b636d99dSDavid van Moolenbroek }
1612*b636d99dSDavid van Moolenbroek 
1613*b636d99dSDavid van Moolenbroek /*
1614*b636d99dSDavid van Moolenbroek  * Decode SNMPv3 User-based Security Message Header (SNMPv3)
1615*b636d99dSDavid van Moolenbroek  */
1616*b636d99dSDavid van Moolenbroek static void
usm_print(netdissect_options * ndo,const u_char * np,u_int length)1617*b636d99dSDavid van Moolenbroek usm_print(netdissect_options *ndo,
1618*b636d99dSDavid van Moolenbroek           const u_char *np, u_int length)
1619*b636d99dSDavid van Moolenbroek {
1620*b636d99dSDavid van Moolenbroek         struct be elem;
1621*b636d99dSDavid van Moolenbroek 	int count = 0;
1622*b636d99dSDavid van Moolenbroek 
1623*b636d99dSDavid van Moolenbroek 	/* Sequence */
1624*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1625*b636d99dSDavid van Moolenbroek 		return;
1626*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_SEQ) {
1627*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[!usm]"));
1628*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1629*b636d99dSDavid van Moolenbroek 		return;
1630*b636d99dSDavid van Moolenbroek 	}
1631*b636d99dSDavid van Moolenbroek 	length = elem.asnlen;
1632*b636d99dSDavid van Moolenbroek 	np = (u_char *)elem.data.raw;
1633*b636d99dSDavid van Moolenbroek 
1634*b636d99dSDavid van Moolenbroek 	/* msgAuthoritativeEngineID (OCTET STRING) */
1635*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1636*b636d99dSDavid van Moolenbroek 		return;
1637*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_STR) {
1638*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgAuthoritativeEngineID!=STR]"));
1639*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1640*b636d99dSDavid van Moolenbroek 		return;
1641*b636d99dSDavid van Moolenbroek 	}
1642*b636d99dSDavid van Moolenbroek 	length -= count;
1643*b636d99dSDavid van Moolenbroek 	np += count;
1644*b636d99dSDavid van Moolenbroek 
1645*b636d99dSDavid van Moolenbroek 	/* msgAuthoritativeEngineBoots (INTEGER) */
1646*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1647*b636d99dSDavid van Moolenbroek 		return;
1648*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1649*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgAuthoritativeEngineBoots!=INT]"));
1650*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1651*b636d99dSDavid van Moolenbroek 		return;
1652*b636d99dSDavid van Moolenbroek 	}
1653*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag)
1654*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "B=%d ", elem.data.integer));
1655*b636d99dSDavid van Moolenbroek 	length -= count;
1656*b636d99dSDavid van Moolenbroek 	np += count;
1657*b636d99dSDavid van Moolenbroek 
1658*b636d99dSDavid van Moolenbroek 	/* msgAuthoritativeEngineTime (INTEGER) */
1659*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1660*b636d99dSDavid van Moolenbroek 		return;
1661*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1662*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgAuthoritativeEngineTime!=INT]"));
1663*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1664*b636d99dSDavid van Moolenbroek 		return;
1665*b636d99dSDavid van Moolenbroek 	}
1666*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag)
1667*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "T=%d ", elem.data.integer));
1668*b636d99dSDavid van Moolenbroek 	length -= count;
1669*b636d99dSDavid van Moolenbroek 	np += count;
1670*b636d99dSDavid van Moolenbroek 
1671*b636d99dSDavid van Moolenbroek 	/* msgUserName (OCTET STRING) */
1672*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1673*b636d99dSDavid van Moolenbroek 		return;
1674*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_STR) {
1675*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgUserName!=STR]"));
1676*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1677*b636d99dSDavid van Moolenbroek 		return;
1678*b636d99dSDavid van Moolenbroek 	}
1679*b636d99dSDavid van Moolenbroek 	length -= count;
1680*b636d99dSDavid van Moolenbroek         np += count;
1681*b636d99dSDavid van Moolenbroek 
1682*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "U=%.*s ", (int)elem.asnlen, elem.data.str));
1683*b636d99dSDavid van Moolenbroek 
1684*b636d99dSDavid van Moolenbroek 	/* msgAuthenticationParameters (OCTET STRING) */
1685*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1686*b636d99dSDavid van Moolenbroek 		return;
1687*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_STR) {
1688*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgAuthenticationParameters!=STR]"));
1689*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1690*b636d99dSDavid van Moolenbroek 		return;
1691*b636d99dSDavid van Moolenbroek 	}
1692*b636d99dSDavid van Moolenbroek 	length -= count;
1693*b636d99dSDavid van Moolenbroek         np += count;
1694*b636d99dSDavid van Moolenbroek 
1695*b636d99dSDavid van Moolenbroek 	/* msgPrivacyParameters (OCTET STRING) */
1696*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1697*b636d99dSDavid van Moolenbroek 		return;
1698*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_STR) {
1699*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgPrivacyParameters!=STR]"));
1700*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1701*b636d99dSDavid van Moolenbroek 		return;
1702*b636d99dSDavid van Moolenbroek 	}
1703*b636d99dSDavid van Moolenbroek 	length -= count;
1704*b636d99dSDavid van Moolenbroek         np += count;
1705*b636d99dSDavid van Moolenbroek 
1706*b636d99dSDavid van Moolenbroek 	if ((u_int)count < length)
1707*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[%d extra after usm SEQ]", length - count));
1708*b636d99dSDavid van Moolenbroek }
1709*b636d99dSDavid van Moolenbroek 
1710*b636d99dSDavid van Moolenbroek /*
1711*b636d99dSDavid van Moolenbroek  * Decode SNMPv3 Message Header (SNMPv3)
1712*b636d99dSDavid van Moolenbroek  */
1713*b636d99dSDavid van Moolenbroek static void
v3msg_print(netdissect_options * ndo,const u_char * np,u_int length)1714*b636d99dSDavid van Moolenbroek v3msg_print(netdissect_options *ndo,
1715*b636d99dSDavid van Moolenbroek             const u_char *np, u_int length)
1716*b636d99dSDavid van Moolenbroek {
1717*b636d99dSDavid van Moolenbroek 	struct be elem;
1718*b636d99dSDavid van Moolenbroek 	int count = 0;
1719*b636d99dSDavid van Moolenbroek 	u_char flags;
1720*b636d99dSDavid van Moolenbroek 	int model;
1721*b636d99dSDavid van Moolenbroek 	const u_char *xnp = np;
1722*b636d99dSDavid van Moolenbroek 	int xlength = length;
1723*b636d99dSDavid van Moolenbroek 
1724*b636d99dSDavid van Moolenbroek 	/* Sequence */
1725*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1726*b636d99dSDavid van Moolenbroek 		return;
1727*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_SEQ) {
1728*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[!message]"));
1729*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1730*b636d99dSDavid van Moolenbroek 		return;
1731*b636d99dSDavid van Moolenbroek 	}
1732*b636d99dSDavid van Moolenbroek 	length = elem.asnlen;
1733*b636d99dSDavid van Moolenbroek 	np = (u_char *)elem.data.raw;
1734*b636d99dSDavid van Moolenbroek 
1735*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1736*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "{ "));
1737*b636d99dSDavid van Moolenbroek 	}
1738*b636d99dSDavid van Moolenbroek 
1739*b636d99dSDavid van Moolenbroek 	/* msgID (INTEGER) */
1740*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1741*b636d99dSDavid van Moolenbroek 		return;
1742*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1743*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgID!=INT]"));
1744*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1745*b636d99dSDavid van Moolenbroek 		return;
1746*b636d99dSDavid van Moolenbroek 	}
1747*b636d99dSDavid van Moolenbroek 	length -= count;
1748*b636d99dSDavid van Moolenbroek 	np += count;
1749*b636d99dSDavid van Moolenbroek 
1750*b636d99dSDavid van Moolenbroek 	/* msgMaxSize (INTEGER) */
1751*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1752*b636d99dSDavid van Moolenbroek 		return;
1753*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1754*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgMaxSize!=INT]"));
1755*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1756*b636d99dSDavid van Moolenbroek 		return;
1757*b636d99dSDavid van Moolenbroek 	}
1758*b636d99dSDavid van Moolenbroek 	length -= count;
1759*b636d99dSDavid van Moolenbroek 	np += count;
1760*b636d99dSDavid van Moolenbroek 
1761*b636d99dSDavid van Moolenbroek 	/* msgFlags (OCTET STRING) */
1762*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1763*b636d99dSDavid van Moolenbroek 		return;
1764*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_STR) {
1765*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgFlags!=STR]"));
1766*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1767*b636d99dSDavid van Moolenbroek 		return;
1768*b636d99dSDavid van Moolenbroek 	}
1769*b636d99dSDavid van Moolenbroek 	if (elem.asnlen != 1) {
1770*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgFlags size %d]", elem.asnlen));
1771*b636d99dSDavid van Moolenbroek 		return;
1772*b636d99dSDavid van Moolenbroek 	}
1773*b636d99dSDavid van Moolenbroek 	flags = elem.data.str[0];
1774*b636d99dSDavid van Moolenbroek 	if (flags != 0x00 && flags != 0x01 && flags != 0x03
1775*b636d99dSDavid van Moolenbroek 	    && flags != 0x04 && flags != 0x05 && flags != 0x07) {
1776*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgFlags=0x%02X]", flags));
1777*b636d99dSDavid van Moolenbroek 		return;
1778*b636d99dSDavid van Moolenbroek 	}
1779*b636d99dSDavid van Moolenbroek 	length -= count;
1780*b636d99dSDavid van Moolenbroek 	np += count;
1781*b636d99dSDavid van Moolenbroek 
1782*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "F=%s%s%s ",
1783*b636d99dSDavid van Moolenbroek 	          flags & 0x01 ? "a" : "",
1784*b636d99dSDavid van Moolenbroek 	          flags & 0x02 ? "p" : "",
1785*b636d99dSDavid van Moolenbroek 	          flags & 0x04 ? "r" : ""));
1786*b636d99dSDavid van Moolenbroek 
1787*b636d99dSDavid van Moolenbroek 	/* msgSecurityModel (INTEGER) */
1788*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1789*b636d99dSDavid van Moolenbroek 		return;
1790*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1791*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgSecurityModel!=INT]"));
1792*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1793*b636d99dSDavid van Moolenbroek 		return;
1794*b636d99dSDavid van Moolenbroek 	}
1795*b636d99dSDavid van Moolenbroek 	model = elem.data.integer;
1796*b636d99dSDavid van Moolenbroek 	length -= count;
1797*b636d99dSDavid van Moolenbroek 	np += count;
1798*b636d99dSDavid van Moolenbroek 
1799*b636d99dSDavid van Moolenbroek 	if ((u_int)count < length)
1800*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[%d extra after message SEQ]", length - count));
1801*b636d99dSDavid van Moolenbroek 
1802*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1803*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "} "));
1804*b636d99dSDavid van Moolenbroek 	}
1805*b636d99dSDavid van Moolenbroek 
1806*b636d99dSDavid van Moolenbroek 	if (model == 3) {
1807*b636d99dSDavid van Moolenbroek 	    if (ndo->ndo_vflag) {
1808*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "{ USM "));
1809*b636d99dSDavid van Moolenbroek 	    }
1810*b636d99dSDavid van Moolenbroek 	} else {
1811*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, "[security model %d]", model));
1812*b636d99dSDavid van Moolenbroek             return;
1813*b636d99dSDavid van Moolenbroek 	}
1814*b636d99dSDavid van Moolenbroek 
1815*b636d99dSDavid van Moolenbroek 	np = xnp + (np - xnp);
1816*b636d99dSDavid van Moolenbroek 	length = xlength - (np - xnp);
1817*b636d99dSDavid van Moolenbroek 
1818*b636d99dSDavid van Moolenbroek 	/* msgSecurityParameters (OCTET STRING) */
1819*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1820*b636d99dSDavid van Moolenbroek 		return;
1821*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_STR) {
1822*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[msgSecurityParameters!=STR]"));
1823*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1824*b636d99dSDavid van Moolenbroek 		return;
1825*b636d99dSDavid van Moolenbroek 	}
1826*b636d99dSDavid van Moolenbroek 	length -= count;
1827*b636d99dSDavid van Moolenbroek 	np += count;
1828*b636d99dSDavid van Moolenbroek 
1829*b636d99dSDavid van Moolenbroek 	if (model == 3) {
1830*b636d99dSDavid van Moolenbroek 	    usm_print(ndo, elem.data.str, elem.asnlen);
1831*b636d99dSDavid van Moolenbroek 	    if (ndo->ndo_vflag) {
1832*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "} "));
1833*b636d99dSDavid van Moolenbroek 	    }
1834*b636d99dSDavid van Moolenbroek 	}
1835*b636d99dSDavid van Moolenbroek 
1836*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1837*b636d99dSDavid van Moolenbroek 	    ND_PRINT((ndo, "{ ScopedPDU "));
1838*b636d99dSDavid van Moolenbroek 	}
1839*b636d99dSDavid van Moolenbroek 
1840*b636d99dSDavid van Moolenbroek 	scopedpdu_print(ndo, np, length, 3);
1841*b636d99dSDavid van Moolenbroek 
1842*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1843*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "} "));
1844*b636d99dSDavid van Moolenbroek 	}
1845*b636d99dSDavid van Moolenbroek }
1846*b636d99dSDavid van Moolenbroek 
1847*b636d99dSDavid van Moolenbroek /*
1848*b636d99dSDavid van Moolenbroek  * Decode SNMP header and pass on to PDU printing routines
1849*b636d99dSDavid van Moolenbroek  */
1850*b636d99dSDavid van Moolenbroek void
snmp_print(netdissect_options * ndo,const u_char * np,u_int length)1851*b636d99dSDavid van Moolenbroek snmp_print(netdissect_options *ndo,
1852*b636d99dSDavid van Moolenbroek            const u_char *np, u_int length)
1853*b636d99dSDavid van Moolenbroek {
1854*b636d99dSDavid van Moolenbroek 	struct be elem;
1855*b636d99dSDavid van Moolenbroek 	int count = 0;
1856*b636d99dSDavid van Moolenbroek 	int version = 0;
1857*b636d99dSDavid van Moolenbroek 
1858*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " "));
1859*b636d99dSDavid van Moolenbroek 
1860*b636d99dSDavid van Moolenbroek 	/* initial Sequence */
1861*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1862*b636d99dSDavid van Moolenbroek 		return;
1863*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_SEQ) {
1864*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[!init SEQ]"));
1865*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1866*b636d99dSDavid van Moolenbroek 		return;
1867*b636d99dSDavid van Moolenbroek 	}
1868*b636d99dSDavid van Moolenbroek 	if ((u_int)count < length)
1869*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[%d extra after iSEQ]", length - count));
1870*b636d99dSDavid van Moolenbroek 	/* descend */
1871*b636d99dSDavid van Moolenbroek 	length = elem.asnlen;
1872*b636d99dSDavid van Moolenbroek 	np = (u_char *)elem.data.raw;
1873*b636d99dSDavid van Moolenbroek 
1874*b636d99dSDavid van Moolenbroek 	/* Version (INTEGER) */
1875*b636d99dSDavid van Moolenbroek 	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
1876*b636d99dSDavid van Moolenbroek 		return;
1877*b636d99dSDavid van Moolenbroek 	if (elem.type != BE_INT) {
1878*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[version!=INT]"));
1879*b636d99dSDavid van Moolenbroek 		asn1_print(ndo, &elem);
1880*b636d99dSDavid van Moolenbroek 		return;
1881*b636d99dSDavid van Moolenbroek 	}
1882*b636d99dSDavid van Moolenbroek 
1883*b636d99dSDavid van Moolenbroek 	switch (elem.data.integer) {
1884*b636d99dSDavid van Moolenbroek 	case SNMP_VERSION_1:
1885*b636d99dSDavid van Moolenbroek 	case SNMP_VERSION_2:
1886*b636d99dSDavid van Moolenbroek 	case SNMP_VERSION_3:
1887*b636d99dSDavid van Moolenbroek 		if (ndo->ndo_vflag)
1888*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "{ %s ", SnmpVersion[elem.data.integer]));
1889*b636d99dSDavid van Moolenbroek 		break;
1890*b636d99dSDavid van Moolenbroek 	default:
1891*b636d99dSDavid van Moolenbroek 	        ND_PRINT((ndo, "[version = %d]", elem.data.integer));
1892*b636d99dSDavid van Moolenbroek 		return;
1893*b636d99dSDavid van Moolenbroek 	}
1894*b636d99dSDavid van Moolenbroek 	version = elem.data.integer;
1895*b636d99dSDavid van Moolenbroek 	length -= count;
1896*b636d99dSDavid van Moolenbroek 	np += count;
1897*b636d99dSDavid van Moolenbroek 
1898*b636d99dSDavid van Moolenbroek 	switch (version) {
1899*b636d99dSDavid van Moolenbroek 	case SNMP_VERSION_1:
1900*b636d99dSDavid van Moolenbroek         case SNMP_VERSION_2:
1901*b636d99dSDavid van Moolenbroek 		community_print(ndo, np, length, version);
1902*b636d99dSDavid van Moolenbroek 		break;
1903*b636d99dSDavid van Moolenbroek 	case SNMP_VERSION_3:
1904*b636d99dSDavid van Moolenbroek 		v3msg_print(ndo, np, length);
1905*b636d99dSDavid van Moolenbroek 		break;
1906*b636d99dSDavid van Moolenbroek 	default:
1907*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[version = %d]", elem.data.integer));
1908*b636d99dSDavid van Moolenbroek 		break;
1909*b636d99dSDavid van Moolenbroek 	}
1910*b636d99dSDavid van Moolenbroek 
1911*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1912*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "} "));
1913*b636d99dSDavid van Moolenbroek 	}
1914*b636d99dSDavid van Moolenbroek }
1915