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