blob: 1b096dcfe579289b90be9521dafaad86df1e136e [file] [log] [blame]
The Android Open Source Project2949f582009-03-03 19:30:46 -08001/*
2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3 * John Robert LoVerso. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 *
28 * This implementation has been influenced by the CMU SNMP release,
29 * by Steve Waldbusser. However, this shares no code with that system.
30 * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_.
31 * Earlier forms of this implementation were derived and/or inspired by an
32 * awk script originally written by C. Philip Wood of LANL (but later
33 * heavily modified by John Robert LoVerso). The copyright notice for
34 * that work is preserved below, even though it may not rightly apply
35 * to this file.
36 *
37 * Support for SNMPv2c/SNMPv3 and the ability to link the module against
38 * the libsmi was added by J. Schoenwaelder, Copyright (c) 1999.
39 *
40 * This started out as a very simple program, but the incremental decoding
41 * (into the BE structure) complicated things.
42 *
43 # Los Alamos National Laboratory
44 #
45 # Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
46 # This software was produced under a U.S. Government contract
47 # (W-7405-ENG-36) by Los Alamos National Laboratory, which is
48 # operated by the University of California for the U.S. Department
49 # of Energy. The U.S. Government is licensed to use, reproduce,
50 # and distribute this software. Permission is granted to the
51 # public to copy and use this software without charge, provided
52 # that this Notice and any statement of authorship are reproduced
53 # on all copies. Neither the Government nor the University makes
54 # any warranty, express or implied, or assumes any liability or
55 # responsibility for the use of this software.
56 # @(#)snmp.awk.x 1.1 (LANL) 1/15/90
57 */
58
Elliott Hughese2e3bd12017-05-15 10:59:29 -070059/* \summary: Simple Network Management Protocol (SNMP) printer */
60
The Android Open Source Project2949f582009-03-03 19:30:46 -080061#ifdef HAVE_CONFIG_H
62#include "config.h"
63#endif
64
Elliott Hughese2e3bd12017-05-15 10:59:29 -070065#include <netdissect-stdinc.h>
The Android Open Source Project2949f582009-03-03 19:30:46 -080066
67#include <stdio.h>
68#include <string.h>
69
Elliott Hughes892a68b2015-10-19 14:43:53 -070070#ifdef USE_LIBSMI
The Android Open Source Project2949f582009-03-03 19:30:46 -080071#include <smi.h>
72#endif
73
Elliott Hughese2e3bd12017-05-15 10:59:29 -070074#include "netdissect.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080075
76#undef OPAQUE /* defined in <wingdi.h> */
77
Elliott Hughes892a68b2015-10-19 14:43:53 -070078static const char tstr[] = "[|snmp]";
79
The Android Open Source Project2949f582009-03-03 19:30:46 -080080/*
81 * Universal ASN.1 types
82 * (we only care about the tag values for those allowed in the Internet SMI)
83 */
Elliott Hughes892a68b2015-10-19 14:43:53 -070084static const char *Universal[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -080085 "U-0",
86 "Boolean",
87 "Integer",
88#define INTEGER 2
89 "Bitstring",
90 "String",
91#define STRING 4
92 "Null",
93#define ASN_NULL 5
94 "ObjID",
95#define OBJECTID 6
96 "ObjectDes",
97 "U-8","U-9","U-10","U-11", /* 8-11 */
98 "U-12","U-13","U-14","U-15", /* 12-15 */
99 "Sequence",
100#define SEQUENCE 16
101 "Set"
102};
103
104/*
105 * Application-wide ASN.1 types from the Internet SMI and their tags
106 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700107static const char *Application[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800108 "IpAddress",
109#define IPADDR 0
110 "Counter",
111#define COUNTER 1
112 "Gauge",
113#define GAUGE 2
114 "TimeTicks",
115#define TIMETICKS 3
116 "Opaque",
117#define OPAQUE 4
118 "C-5",
119 "Counter64"
120#define COUNTER64 6
121};
122
123/*
124 * Context-specific ASN.1 types for the SNMP PDUs and their tags
125 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700126static const char *Context[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800127 "GetRequest",
128#define GETREQ 0
129 "GetNextRequest",
130#define GETNEXTREQ 1
131 "GetResponse",
132#define GETRESP 2
133 "SetRequest",
134#define SETREQ 3
135 "Trap",
136#define TRAP 4
137 "GetBulk",
138#define GETBULKREQ 5
139 "Inform",
140#define INFORMREQ 6
141 "V2Trap",
142#define V2TRAP 7
143 "Report"
144#define REPORT 8
145};
146
147#define NOTIFY_CLASS(x) (x == TRAP || x == V2TRAP || x == INFORMREQ)
148#define READ_CLASS(x) (x == GETREQ || x == GETNEXTREQ || x == GETBULKREQ)
149#define WRITE_CLASS(x) (x == SETREQ)
150#define RESPONSE_CLASS(x) (x == GETRESP)
151#define INTERNAL_CLASS(x) (x == REPORT)
152
153/*
154 * Context-specific ASN.1 types for the SNMP Exceptions and their tags
155 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700156static const char *Exceptions[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800157 "noSuchObject",
158#define NOSUCHOBJECT 0
159 "noSuchInstance",
160#define NOSUCHINSTANCE 1
161 "endOfMibView",
162#define ENDOFMIBVIEW 2
163};
164
165/*
166 * Private ASN.1 types
167 * The Internet SMI does not specify any
168 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700169static const char *Private[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800170 "P-0"
171};
172
173/*
174 * error-status values for any SNMP PDU
175 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700176static const char *ErrorStatus[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800177 "noError",
178 "tooBig",
179 "noSuchName",
180 "badValue",
181 "readOnly",
182 "genErr",
183 "noAccess",
184 "wrongType",
185 "wrongLength",
186 "wrongEncoding",
187 "wrongValue",
188 "noCreation",
189 "inconsistentValue",
190 "resourceUnavailable",
191 "commitFailed",
192 "undoFailed",
193 "authorizationError",
194 "notWritable",
195 "inconsistentName"
196};
197#define DECODE_ErrorStatus(e) \
198 ( e >= 0 && (size_t)e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
199 ? ErrorStatus[e] \
200 : (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf))
201
202/*
203 * generic-trap values in the SNMP Trap-PDU
204 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700205static const char *GenericTrap[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800206 "coldStart",
207 "warmStart",
208 "linkDown",
209 "linkUp",
210 "authenticationFailure",
211 "egpNeighborLoss",
212 "enterpriseSpecific"
213#define GT_ENTERPRISE 6
214};
215#define DECODE_GenericTrap(t) \
216 ( t >= 0 && (size_t)t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
217 ? GenericTrap[t] \
218 : (snprintf(buf, sizeof(buf), "gt=%d", t), buf))
219
220/*
221 * ASN.1 type class table
222 * Ties together the preceding Universal, Application, Context, and Private
223 * type definitions.
224 */
225#define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700226static const struct {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800227 const char *name;
228 const char **Id;
229 int numIDs;
230 } Class[] = {
231 defineCLASS(Universal),
232#define UNIVERSAL 0
233 defineCLASS(Application),
234#define APPLICATION 1
235 defineCLASS(Context),
236#define CONTEXT 2
237 defineCLASS(Private),
238#define PRIVATE 3
239 defineCLASS(Exceptions),
240#define EXCEPTIONS 4
241};
242
243/*
244 * defined forms for ASN.1 types
245 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700246static const char *Form[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800247 "Primitive",
248#define PRIMITIVE 0
249 "Constructed",
250#define CONSTRUCTED 1
251};
252
253/*
254 * A structure for the OID tree for the compiled-in MIB.
255 * This is stored as a general-order tree.
256 */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700257static struct obj {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800258 const char *desc; /* name of object */
259 u_char oid; /* sub-id following parent */
260 u_char type; /* object type (unused) */
261 struct obj *child, *next; /* child and next sibling pointers */
262} *objp = NULL;
263
264/*
265 * Include the compiled in SNMP MIB. "mib.h" is produced by feeding
266 * RFC-1156 format files into "makemib". "mib.h" MUST define at least
267 * a value for `mibroot'.
268 *
269 * In particular, this is gross, as this is including initialized structures,
270 * and by right shouldn't be an "include" file.
271 */
272#include "mib.h"
273
274/*
275 * This defines a list of OIDs which will be abbreviated on output.
276 * Currently, this includes the prefixes for the Internet MIB, the
277 * private enterprises tree, and the experimental tree.
278 */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700279#define OID_FIRST_OCTET(x, y) (((x)*40) + (y)) /* X.690 8.19.4 */
280
281#ifndef NO_ABREV_MIB
282static const uint8_t mib_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 2, 1 };
283#endif
284#ifndef NO_ABREV_ENTER
285static const uint8_t enterprises_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 4, 1 };
286#endif
287#ifndef NO_ABREV_EXPERI
288static const uint8_t experimental_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 3 };
289#endif
290#ifndef NO_ABBREV_SNMPMODS
291static const uint8_t snmpModules_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 6, 3 };
292#endif
293
294#define OBJ_ABBREV_ENTRY(prefix, obj) \
295 { prefix, &_ ## obj ## _obj, obj ## _oid, sizeof (obj ## _oid) }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700296static const struct obj_abrev {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800297 const char *prefix; /* prefix for this abrev */
298 struct obj *node; /* pointer into object table */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700299 const uint8_t *oid; /* ASN.1 encoded OID */
300 size_t oid_len; /* length of OID */
The Android Open Source Project2949f582009-03-03 19:30:46 -0800301} obj_abrev_list[] = {
302#ifndef NO_ABREV_MIB
303 /* .iso.org.dod.internet.mgmt.mib */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700304 OBJ_ABBREV_ENTRY("", mib),
The Android Open Source Project2949f582009-03-03 19:30:46 -0800305#endif
306#ifndef NO_ABREV_ENTER
307 /* .iso.org.dod.internet.private.enterprises */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700308 OBJ_ABBREV_ENTRY("E:", enterprises),
The Android Open Source Project2949f582009-03-03 19:30:46 -0800309#endif
310#ifndef NO_ABREV_EXPERI
311 /* .iso.org.dod.internet.experimental */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700312 OBJ_ABBREV_ENTRY("X:", experimental),
The Android Open Source Project2949f582009-03-03 19:30:46 -0800313#endif
314#ifndef NO_ABBREV_SNMPMODS
315 /* .iso.org.dod.internet.snmpV2.snmpModules */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700316 OBJ_ABBREV_ENTRY("S:", snmpModules),
The Android Open Source Project2949f582009-03-03 19:30:46 -0800317#endif
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700318 { 0,0,0,0 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800319};
320
321/*
322 * This is used in the OID print routine to walk down the object tree
323 * rooted at `mibroot'.
324 */
325#define OBJ_PRINT(o, suppressdot) \
326{ \
327 if (objp) { \
328 do { \
329 if ((o) == objp->oid) \
330 break; \
331 } while ((objp = objp->next) != NULL); \
332 } \
333 if (objp) { \
Elliott Hughes892a68b2015-10-19 14:43:53 -0700334 ND_PRINT((ndo, suppressdot?"%s":".%s", objp->desc)); \
The Android Open Source Project2949f582009-03-03 19:30:46 -0800335 objp = objp->child; \
336 } else \
Elliott Hughes892a68b2015-10-19 14:43:53 -0700337 ND_PRINT((ndo, suppressdot?"%u":".%u", (o))); \
The Android Open Source Project2949f582009-03-03 19:30:46 -0800338}
339
340/*
341 * This is the definition for the Any-Data-Type storage used purely for
342 * temporary internal representation while decoding an ASN.1 data stream.
343 */
344struct be {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700345 uint32_t asnlen;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800346 union {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700347 const uint8_t *raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800348 int32_t integer;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700349 uint32_t uns;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800350 const u_char *str;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700351 uint64_t uns64;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800352 } data;
353 u_short id;
354 u_char form, class; /* tag info */
355 u_char type;
356#define BE_ANY 255
357#define BE_NONE 0
358#define BE_NULL 1
359#define BE_OCTET 2
360#define BE_OID 3
361#define BE_INT 4
362#define BE_UNS 5
363#define BE_STR 6
364#define BE_SEQ 7
365#define BE_INETADDR 8
366#define BE_PDU 9
367#define BE_UNS64 10
368#define BE_NOSUCHOBJECT 128
369#define BE_NOSUCHINST 129
370#define BE_ENDOFMIBVIEW 130
371};
372
373/*
374 * SNMP versions recognized by this module
375 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700376static const char *SnmpVersion[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800377 "SNMPv1",
378#define SNMP_VERSION_1 0
379 "SNMPv2c",
380#define SNMP_VERSION_2 1
381 "SNMPv2u",
382#define SNMP_VERSION_2U 2
383 "SNMPv3"
384#define SNMP_VERSION_3 3
385};
386
387/*
388 * Defaults for SNMP PDU components
389 */
390#define DEF_COMMUNITY "public"
391
392/*
393 * constants for ASN.1 decoding
394 */
395#define OIDMUX 40
396#define ASNLEN_INETADDR 4
397#define ASN_SHIFT7 7
398#define ASN_SHIFT8 8
399#define ASN_BIT8 0x80
400#define ASN_LONGLEN 0x80
401
402#define ASN_ID_BITS 0x1f
403#define ASN_FORM_BITS 0x20
404#define ASN_FORM_SHIFT 5
405#define ASN_CLASS_BITS 0xc0
406#define ASN_CLASS_SHIFT 6
407
408#define ASN_ID_EXT 0x1f /* extension ID in tag field */
409
410/*
411 * This decodes the next ASN.1 object in the stream pointed to by "p"
412 * (and of real-length "len") and stores the intermediate data in the
413 * provided BE object.
414 *
415 * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
416 * O/w, this returns the number of bytes parsed from "p".
417 */
418static int
Elliott Hughes892a68b2015-10-19 14:43:53 -0700419asn1_parse(netdissect_options *ndo,
420 register const u_char *p, u_int len, struct be *elem)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800421{
422 u_char form, class, id;
423 int i, hdr;
424
425 elem->asnlen = 0;
426 elem->type = BE_ANY;
427 if (len < 1) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700428 ND_PRINT((ndo, "[nothing to parse]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800429 return -1;
430 }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700431 ND_TCHECK(*p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800432
433 /*
434 * it would be nice to use a bit field, but you can't depend on them.
435 * +---+---+---+---+---+---+---+---+
436 * + class |frm| id |
437 * +---+---+---+---+---+---+---+---+
438 * 7 6 5 4 3 2 1 0
439 */
440 id = *p & ASN_ID_BITS; /* lower 5 bits, range 00-1f */
441#ifdef notdef
442 form = (*p & 0xe0) >> 5; /* move upper 3 bits to lower 3 */
443 class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */
444 form &= 0x1; /* bit 5 -> bit 0, range 0-1 */
445#else
446 form = (u_char)(*p & ASN_FORM_BITS) >> ASN_FORM_SHIFT;
447 class = (u_char)(*p & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT;
448#endif
449 elem->form = form;
450 elem->class = class;
451 elem->id = id;
452 p++; len--; hdr = 1;
453 /* extended tag field */
454 if (id == ASN_ID_EXT) {
455 /*
456 * The ID follows, as a sequence of octets with the
457 * 8th bit set and the remaining 7 bits being
458 * the next 7 bits of the value, terminated with
459 * an octet with the 8th bit not set.
460 *
461 * First, assemble all the octets with the 8th
462 * bit set. XXX - this doesn't handle a value
463 * that won't fit in 32 bits.
464 */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700465 id = 0;
466 ND_TCHECK(*p);
467 while (*p & ASN_BIT8) {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800468 if (len < 1) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700469 ND_PRINT((ndo, "[Xtagfield?]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800470 return -1;
471 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800472 id = (id << 7) | (*p & ~ASN_BIT8);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700473 len--;
474 hdr++;
475 p++;
476 ND_TCHECK(*p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800477 }
478 if (len < 1) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700479 ND_PRINT((ndo, "[Xtagfield?]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800480 return -1;
481 }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700482 ND_TCHECK(*p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800483 elem->id = id = (id << 7) | *p;
484 --len;
485 ++hdr;
486 ++p;
487 }
488 if (len < 1) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700489 ND_PRINT((ndo, "[no asnlen]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800490 return -1;
491 }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700492 ND_TCHECK(*p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800493 elem->asnlen = *p;
494 p++; len--; hdr++;
495 if (elem->asnlen & ASN_BIT8) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700496 uint32_t noct = elem->asnlen % ASN_BIT8;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800497 elem->asnlen = 0;
498 if (len < noct) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700499 ND_PRINT((ndo, "[asnlen? %d<%d]", len, noct));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800500 return -1;
501 }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700502 ND_TCHECK2(*p, noct);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800503 for (; noct-- > 0; len--, hdr++)
504 elem->asnlen = (elem->asnlen << ASN_SHIFT8) | *p++;
505 }
506 if (len < elem->asnlen) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700507 ND_PRINT((ndo, "[len%d<asnlen%u]", len, elem->asnlen));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800508 return -1;
509 }
510 if (form >= sizeof(Form)/sizeof(Form[0])) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700511 ND_PRINT((ndo, "[form?%d]", form));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800512 return -1;
513 }
514 if (class >= sizeof(Class)/sizeof(Class[0])) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700515 ND_PRINT((ndo, "[class?%c/%d]", *Form[form], class));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800516 return -1;
517 }
518 if ((int)id >= Class[class].numIDs) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700519 ND_PRINT((ndo, "[id?%c/%s/%d]", *Form[form], Class[class].name, id));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800520 return -1;
521 }
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700522 ND_TCHECK2(*p, elem->asnlen);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800523
524 switch (form) {
525 case PRIMITIVE:
526 switch (class) {
527 case UNIVERSAL:
528 switch (id) {
529 case STRING:
530 elem->type = BE_STR;
531 elem->data.str = p;
532 break;
533
534 case INTEGER: {
535 register int32_t data;
536 elem->type = BE_INT;
537 data = 0;
538
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700539 if (elem->asnlen == 0) {
540 ND_PRINT((ndo, "[asnlen=0]"));
541 return -1;
542 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800543 if (*p & ASN_BIT8) /* negative */
544 data = -1;
545 for (i = elem->asnlen; i-- > 0; p++)
546 data = (data << ASN_SHIFT8) | *p;
547 elem->data.integer = data;
548 break;
549 }
550
551 case OBJECTID:
552 elem->type = BE_OID;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700553 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800554 break;
555
556 case ASN_NULL:
557 elem->type = BE_NULL;
558 elem->data.raw = NULL;
559 break;
560
561 default:
562 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700563 elem->data.raw = (const uint8_t *)p;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700564 ND_PRINT((ndo, "[P/U/%s]", Class[class].Id[id]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800565 break;
566 }
567 break;
568
569 case APPLICATION:
570 switch (id) {
571 case IPADDR:
572 elem->type = BE_INETADDR;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700573 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800574 break;
575
576 case COUNTER:
577 case GAUGE:
578 case TIMETICKS: {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700579 register uint32_t data;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800580 elem->type = BE_UNS;
581 data = 0;
582 for (i = elem->asnlen; i-- > 0; p++)
583 data = (data << 8) + *p;
584 elem->data.uns = data;
585 break;
586 }
587
588 case COUNTER64: {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700589 register uint64_t data64;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800590 elem->type = BE_UNS64;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700591 data64 = 0;
592 for (i = elem->asnlen; i-- > 0; p++)
593 data64 = (data64 << 8) + *p;
594 elem->data.uns64 = data64;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800595 break;
596 }
597
598 default:
599 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700600 elem->data.raw = (const uint8_t *)p;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700601 ND_PRINT((ndo, "[P/A/%s]",
602 Class[class].Id[id]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800603 break;
604 }
605 break;
606
607 case CONTEXT:
608 switch (id) {
609 case NOSUCHOBJECT:
610 elem->type = BE_NOSUCHOBJECT;
611 elem->data.raw = NULL;
612 break;
613
614 case NOSUCHINSTANCE:
615 elem->type = BE_NOSUCHINST;
616 elem->data.raw = NULL;
617 break;
618
619 case ENDOFMIBVIEW:
620 elem->type = BE_ENDOFMIBVIEW;
621 elem->data.raw = NULL;
622 break;
623 }
624 break;
625
626 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700627 ND_PRINT((ndo, "[P/%s/%s]", Class[class].name, Class[class].Id[id]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800628 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700629 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800630 break;
631 }
632 break;
633
634 case CONSTRUCTED:
635 switch (class) {
636 case UNIVERSAL:
637 switch (id) {
638 case SEQUENCE:
639 elem->type = BE_SEQ;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700640 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800641 break;
642
643 default:
644 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700645 elem->data.raw = (const uint8_t *)p;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700646 ND_PRINT((ndo, "C/U/%s", Class[class].Id[id]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800647 break;
648 }
649 break;
650
651 case CONTEXT:
652 elem->type = BE_PDU;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700653 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800654 break;
655
656 default:
657 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700658 elem->data.raw = (const uint8_t *)p;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700659 ND_PRINT((ndo, "C/%s/%s", Class[class].name, Class[class].Id[id]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800660 break;
661 }
662 break;
663 }
664 p += elem->asnlen;
665 len -= elem->asnlen;
666 return elem->asnlen + hdr;
667
668trunc:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700669 ND_PRINT((ndo, "%s", tstr));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800670 return -1;
671}
672
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700673static int
674asn1_print_octets(netdissect_options *ndo, struct be *elem)
675{
676 const u_char *p = (const u_char *)elem->data.raw;
677 uint32_t asnlen = elem->asnlen;
678 uint32_t i;
679
680 ND_TCHECK2(*p, asnlen);
681 for (i = asnlen; i-- > 0; p++)
682 ND_PRINT((ndo, "_%.2x", *p));
683 return 0;
684
685trunc:
686 ND_PRINT((ndo, "%s", tstr));
687 return -1;
688}
689
690static int
691asn1_print_string(netdissect_options *ndo, struct be *elem)
692{
693 register int printable = 1, first = 1;
694 const u_char *p;
695 uint32_t asnlen = elem->asnlen;
696 uint32_t i;
697
698 p = elem->data.str;
699 ND_TCHECK2(*p, asnlen);
700 for (i = asnlen; printable && i-- > 0; p++)
701 printable = ND_ISPRINT(*p);
702 p = elem->data.str;
703 if (printable) {
704 ND_PRINT((ndo, "\""));
705 if (fn_printn(ndo, p, asnlen, ndo->ndo_snapend)) {
706 ND_PRINT((ndo, "\""));
707 goto trunc;
708 }
709 ND_PRINT((ndo, "\""));
710 } else {
711 for (i = asnlen; i-- > 0; p++) {
712 ND_PRINT((ndo, first ? "%.2x" : "_%.2x", *p));
713 first = 0;
714 }
715 }
716 return 0;
717
718trunc:
719 ND_PRINT((ndo, "%s", tstr));
720 return -1;
721}
722
The Android Open Source Project2949f582009-03-03 19:30:46 -0800723/*
724 * Display the ASN.1 object represented by the BE object.
725 * This used to be an integral part of asn1_parse() before the intermediate
726 * BE form was added.
727 */
728static int
Elliott Hughes892a68b2015-10-19 14:43:53 -0700729asn1_print(netdissect_options *ndo,
730 struct be *elem)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800731{
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700732 const u_char *p;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700733 uint32_t asnlen = elem->asnlen;
734 uint32_t i;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800735
736 switch (elem->type) {
737
738 case BE_OCTET:
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700739 if (asn1_print_octets(ndo, elem) == -1)
740 return -1;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800741 break;
742
743 case BE_NULL:
744 break;
745
746 case BE_OID: {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700747 int o = 0, first = -1;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800748
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700749 p = (const u_char *)elem->data.raw;
750 i = asnlen;
751 if (!ndo->ndo_nflag && asnlen > 2) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700752 const struct obj_abrev *a = &obj_abrev_list[0];
The Android Open Source Project2949f582009-03-03 19:30:46 -0800753 for (; a->node; a++) {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700754 if (i < a->oid_len)
755 continue;
756 if (!ND_TTEST2(*p, a->oid_len))
757 continue;
758 if (memcmp(a->oid, p, a->oid_len) == 0) {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800759 objp = a->node->child;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700760 i -= a->oid_len;
761 p += a->oid_len;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700762 ND_PRINT((ndo, "%s", a->prefix));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800763 first = 1;
764 break;
765 }
766 }
767 }
768
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700769 for (; i-- > 0; p++) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700770 ND_TCHECK(*p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800771 o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
772 if (*p & ASN_LONGLEN)
773 continue;
774
775 /*
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700776 * first subitem encodes two items with
777 * 1st*OIDMUX+2nd
The Android Open Source Project2949f582009-03-03 19:30:46 -0800778 * (see X.690:1997 clause 8.19 for the details)
779 */
780 if (first < 0) {
781 int s;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700782 if (!ndo->ndo_nflag)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800783 objp = mibroot;
784 first = 0;
785 s = o / OIDMUX;
786 if (s > 2) s = 2;
787 OBJ_PRINT(s, first);
788 o -= s * OIDMUX;
789 }
790 OBJ_PRINT(o, first);
791 if (--first < 0)
792 first = 0;
793 o = 0;
794 }
795 break;
796 }
797
798 case BE_INT:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700799 ND_PRINT((ndo, "%d", elem->data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800800 break;
801
802 case BE_UNS:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700803 ND_PRINT((ndo, "%u", elem->data.uns));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800804 break;
805
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700806 case BE_UNS64:
807 ND_PRINT((ndo, "%" PRIu64, elem->data.uns64));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800808 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800809
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700810 case BE_STR:
811 if (asn1_print_string(ndo, elem) == -1)
812 return -1;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800813 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800814
815 case BE_SEQ:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700816 ND_PRINT((ndo, "Seq(%u)", elem->asnlen));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800817 break;
818
819 case BE_INETADDR:
820 if (asnlen != ASNLEN_INETADDR)
Elliott Hughes892a68b2015-10-19 14:43:53 -0700821 ND_PRINT((ndo, "[inetaddr len!=%d]", ASNLEN_INETADDR));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700822 p = (const u_char *)elem->data.raw;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700823 ND_TCHECK2(*p, asnlen);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800824 for (i = asnlen; i-- != 0; p++) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700825 ND_PRINT((ndo, (i == asnlen-1) ? "%u" : ".%u", *p));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800826 }
827 break;
828
829 case BE_NOSUCHOBJECT:
830 case BE_NOSUCHINST:
831 case BE_ENDOFMIBVIEW:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700832 ND_PRINT((ndo, "[%s]", Class[EXCEPTIONS].Id[elem->id]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800833 break;
834
835 case BE_PDU:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700836 ND_PRINT((ndo, "%s(%u)", Class[CONTEXT].Id[elem->id], elem->asnlen));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800837 break;
838
839 case BE_ANY:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700840 ND_PRINT((ndo, "[BE_ANY!?]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800841 break;
842
843 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700844 ND_PRINT((ndo, "[be!?]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800845 break;
846 }
847 return 0;
848
849trunc:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700850 ND_PRINT((ndo, "%s", tstr));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800851 return -1;
852}
853
854#ifdef notdef
855/*
856 * This is a brute force ASN.1 printer: recurses to dump an entire structure.
857 * This will work for any ASN.1 stream, not just an SNMP PDU.
858 *
859 * By adding newlines and spaces at the correct places, this would print in
860 * Rose-Normal-Form.
861 *
862 * This is not currently used.
863 */
864static void
865asn1_decode(u_char *p, u_int length)
866{
867 struct be elem;
868 int i = 0;
869
870 while (i >= 0 && length > 0) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700871 i = asn1_parse(ndo, p, length, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800872 if (i >= 0) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700873 ND_PRINT((ndo, " "));
874 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800875 return;
876 if (elem.type == BE_SEQ || elem.type == BE_PDU) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700877 ND_PRINT((ndo, " {"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800878 asn1_decode(elem.data.raw, elem.asnlen);
Elliott Hughes892a68b2015-10-19 14:43:53 -0700879 ND_PRINT((ndo, " }"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800880 }
881 length -= i;
882 p += i;
883 }
884 }
885}
886#endif
887
Elliott Hughes892a68b2015-10-19 14:43:53 -0700888#ifdef USE_LIBSMI
The Android Open Source Project2949f582009-03-03 19:30:46 -0800889
890struct smi2be {
891 SmiBasetype basetype;
892 int be;
893};
894
Elliott Hughes892a68b2015-10-19 14:43:53 -0700895static const struct smi2be smi2betab[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800896 { SMI_BASETYPE_INTEGER32, BE_INT },
897 { SMI_BASETYPE_OCTETSTRING, BE_STR },
898 { SMI_BASETYPE_OCTETSTRING, BE_INETADDR },
899 { SMI_BASETYPE_OBJECTIDENTIFIER, BE_OID },
900 { SMI_BASETYPE_UNSIGNED32, BE_UNS },
901 { SMI_BASETYPE_INTEGER64, BE_NONE },
902 { SMI_BASETYPE_UNSIGNED64, BE_UNS64 },
903 { SMI_BASETYPE_FLOAT32, BE_NONE },
904 { SMI_BASETYPE_FLOAT64, BE_NONE },
905 { SMI_BASETYPE_FLOAT128, BE_NONE },
906 { SMI_BASETYPE_ENUM, BE_INT },
907 { SMI_BASETYPE_BITS, BE_STR },
908 { SMI_BASETYPE_UNKNOWN, BE_NONE }
909};
910
911static int
Elliott Hughes892a68b2015-10-19 14:43:53 -0700912smi_decode_oid(netdissect_options *ndo,
913 struct be *elem, unsigned int *oid,
914 unsigned int oidsize, unsigned int *oidlen)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800915{
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700916 const u_char *p = (const u_char *)elem->data.raw;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700917 uint32_t asnlen = elem->asnlen;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800918 int o = 0, first = -1, i = asnlen;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700919 unsigned int firstval;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800920
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700921 for (*oidlen = 0; i-- > 0; p++) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700922 ND_TCHECK(*p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800923 o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
924 if (*p & ASN_LONGLEN)
925 continue;
926
927 /*
928 * first subitem encodes two items with 1st*OIDMUX+2nd
929 * (see X.690:1997 clause 8.19 for the details)
930 */
931 if (first < 0) {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700932 first = 0;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700933 firstval = o / OIDMUX;
934 if (firstval > 2) firstval = 2;
935 o -= firstval * OIDMUX;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800936 if (*oidlen < oidsize) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700937 oid[(*oidlen)++] = firstval;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800938 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800939 }
940 if (*oidlen < oidsize) {
941 oid[(*oidlen)++] = o;
942 }
943 o = 0;
944 }
945 return 0;
946
947trunc:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700948 ND_PRINT((ndo, "%s", tstr));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800949 return -1;
950}
951
952static int smi_check_type(SmiBasetype basetype, int be)
953{
954 int i;
955
956 for (i = 0; smi2betab[i].basetype != SMI_BASETYPE_UNKNOWN; i++) {
957 if (smi2betab[i].basetype == basetype && smi2betab[i].be == be) {
958 return 1;
959 }
960 }
961
962 return 0;
963}
964
965static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange,
966 struct be *elem)
967{
968 int ok = 1;
969
970 switch (smiType->basetype) {
971 case SMI_BASETYPE_OBJECTIDENTIFIER:
972 case SMI_BASETYPE_OCTETSTRING:
973 if (smiRange->minValue.value.unsigned32
974 == smiRange->maxValue.value.unsigned32) {
975 ok = (elem->asnlen == smiRange->minValue.value.unsigned32);
976 } else {
977 ok = (elem->asnlen >= smiRange->minValue.value.unsigned32
978 && elem->asnlen <= smiRange->maxValue.value.unsigned32);
979 }
980 break;
981
982 case SMI_BASETYPE_INTEGER32:
983 ok = (elem->data.integer >= smiRange->minValue.value.integer32
984 && elem->data.integer <= smiRange->maxValue.value.integer32);
985 break;
986
987 case SMI_BASETYPE_UNSIGNED32:
988 ok = (elem->data.uns >= smiRange->minValue.value.unsigned32
989 && elem->data.uns <= smiRange->maxValue.value.unsigned32);
990 break;
991
992 case SMI_BASETYPE_UNSIGNED64:
993 /* XXX */
994 break;
995
996 /* case SMI_BASETYPE_INTEGER64: SMIng */
997 /* case SMI_BASETYPE_FLOAT32: SMIng */
998 /* case SMI_BASETYPE_FLOAT64: SMIng */
999 /* case SMI_BASETYPE_FLOAT128: SMIng */
1000
1001 case SMI_BASETYPE_ENUM:
1002 case SMI_BASETYPE_BITS:
1003 case SMI_BASETYPE_UNKNOWN:
1004 ok = 1;
1005 break;
1006
1007 default:
1008 ok = 0;
1009 break;
1010 }
1011
1012 return ok;
1013}
1014
1015static int smi_check_range(SmiType *smiType, struct be *elem)
1016{
1017 SmiRange *smiRange;
1018 int ok = 1;
1019
1020 for (smiRange = smiGetFirstRange(smiType);
1021 smiRange;
1022 smiRange = smiGetNextRange(smiRange)) {
1023
1024 ok = smi_check_a_range(smiType, smiRange, elem);
1025
1026 if (ok) {
1027 break;
1028 }
1029 }
1030
1031 if (ok) {
1032 SmiType *parentType;
1033 parentType = smiGetParentType(smiType);
1034 if (parentType) {
1035 ok = smi_check_range(parentType, elem);
1036 }
1037 }
1038
1039 return ok;
1040}
1041
Elliott Hughes892a68b2015-10-19 14:43:53 -07001042static SmiNode *
1043smi_print_variable(netdissect_options *ndo,
1044 struct be *elem, int *status)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001045{
1046 unsigned int oid[128], oidlen;
1047 SmiNode *smiNode = NULL;
1048 unsigned int i;
1049
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001050 if (!nd_smi_module_loaded) {
1051 *status = asn1_print(ndo, elem);
1052 return NULL;
1053 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001054 *status = smi_decode_oid(ndo, elem, oid, sizeof(oid) / sizeof(unsigned int),
The Android Open Source Project2949f582009-03-03 19:30:46 -08001055 &oidlen);
1056 if (*status < 0)
1057 return NULL;
1058 smiNode = smiGetNodeByOID(oidlen, oid);
1059 if (! smiNode) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001060 *status = asn1_print(ndo, elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001061 return NULL;
1062 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001063 if (ndo->ndo_vflag) {
1064 ND_PRINT((ndo, "%s::", smiGetNodeModule(smiNode)->name));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001065 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001066 ND_PRINT((ndo, "%s", smiNode->name));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001067 if (smiNode->oidlen < oidlen) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001068 for (i = smiNode->oidlen; i < oidlen; i++) {
1069 ND_PRINT((ndo, ".%u", oid[i]));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001070 }
1071 }
1072 *status = 0;
1073 return smiNode;
1074}
1075
1076static int
Elliott Hughes892a68b2015-10-19 14:43:53 -07001077smi_print_value(netdissect_options *ndo,
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001078 SmiNode *smiNode, u_short pduid, struct be *elem)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001079{
1080 unsigned int i, oid[128], oidlen;
1081 SmiType *smiType;
1082 SmiNamedNumber *nn;
1083 int done = 0;
1084
1085 if (! smiNode || ! (smiNode->nodekind
1086 & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001087 return asn1_print(ndo, elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001088 }
1089
1090 if (elem->type == BE_NOSUCHOBJECT
1091 || elem->type == BE_NOSUCHINST
1092 || elem->type == BE_ENDOFMIBVIEW) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001093 return asn1_print(ndo, elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001094 }
1095
1096 if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001097 ND_PRINT((ndo, "[notNotifyable]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001098 }
1099
1100 if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001101 ND_PRINT((ndo, "[notReadable]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001102 }
1103
1104 if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001105 ND_PRINT((ndo, "[notWritable]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001106 }
1107
1108 if (RESPONSE_CLASS(pduid)
1109 && smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001110 ND_PRINT((ndo, "[noAccess]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001111 }
1112
1113 smiType = smiGetNodeType(smiNode);
1114 if (! smiType) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001115 return asn1_print(ndo, elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001116 }
1117
1118 if (! smi_check_type(smiType->basetype, elem->type)) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001119 ND_PRINT((ndo, "[wrongType]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001120 }
1121
1122 if (! smi_check_range(smiType, elem)) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001123 ND_PRINT((ndo, "[outOfRange]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001124 }
1125
1126 /* resolve bits to named bits */
1127
1128 /* check whether instance identifier is valid */
1129
1130 /* apply display hints (integer, octetstring) */
1131
1132 /* convert instance identifier to index type values */
1133
1134 switch (elem->type) {
1135 case BE_OID:
1136 if (smiType->basetype == SMI_BASETYPE_BITS) {
1137 /* print bit labels */
1138 } else {
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001139 if (nd_smi_module_loaded &&
1140 smi_decode_oid(ndo, elem, oid,
1141 sizeof(oid)/sizeof(unsigned int),
1142 &oidlen) == 0) {
1143 smiNode = smiGetNodeByOID(oidlen, oid);
1144 if (smiNode) {
1145 if (ndo->ndo_vflag) {
1146 ND_PRINT((ndo, "%s::", smiGetNodeModule(smiNode)->name));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001147 }
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001148 ND_PRINT((ndo, "%s", smiNode->name));
1149 if (smiNode->oidlen < oidlen) {
1150 for (i = smiNode->oidlen;
1151 i < oidlen; i++) {
1152 ND_PRINT((ndo, ".%u", oid[i]));
1153 }
1154 }
1155 done++;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001156 }
The Android Open Source Project2949f582009-03-03 19:30:46 -08001157 }
1158 }
1159 break;
1160
1161 case BE_INT:
1162 if (smiType->basetype == SMI_BASETYPE_ENUM) {
1163 for (nn = smiGetFirstNamedNumber(smiType);
1164 nn;
1165 nn = smiGetNextNamedNumber(nn)) {
1166 if (nn->value.value.integer32
1167 == elem->data.integer) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001168 ND_PRINT((ndo, "%s", nn->name));
1169 ND_PRINT((ndo, "(%d)", elem->data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001170 done++;
1171 break;
1172 }
1173 }
1174 }
1175 break;
1176 }
1177
1178 if (! done) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001179 return asn1_print(ndo, elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001180 }
1181 return 0;
1182}
1183#endif
1184
1185/*
1186 * General SNMP header
1187 * SEQUENCE {
1188 * version INTEGER {version-1(0)},
1189 * community OCTET STRING,
1190 * data ANY -- PDUs
1191 * }
1192 * PDUs for all but Trap: (see rfc1157 from page 15 on)
1193 * SEQUENCE {
1194 * request-id INTEGER,
1195 * error-status INTEGER,
1196 * error-index INTEGER,
1197 * varbindlist SEQUENCE OF
1198 * SEQUENCE {
1199 * name ObjectName,
1200 * value ObjectValue
1201 * }
1202 * }
1203 * PDU for Trap:
1204 * SEQUENCE {
1205 * enterprise OBJECT IDENTIFIER,
1206 * agent-addr NetworkAddress,
1207 * generic-trap INTEGER,
1208 * specific-trap INTEGER,
1209 * time-stamp TimeTicks,
1210 * varbindlist SEQUENCE OF
1211 * SEQUENCE {
1212 * name ObjectName,
1213 * value ObjectValue
1214 * }
1215 * }
1216 */
1217
1218/*
1219 * Decode SNMP varBind
1220 */
1221static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001222varbind_print(netdissect_options *ndo,
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001223 u_short pduid, const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001224{
1225 struct be elem;
1226 int count = 0, ind;
Elliott Hughes892a68b2015-10-19 14:43:53 -07001227#ifdef USE_LIBSMI
The Android Open Source Project2949f582009-03-03 19:30:46 -08001228 SmiNode *smiNode = NULL;
1229#endif
1230 int status;
1231
1232 /* Sequence of varBind */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001233 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001234 return;
1235 if (elem.type != BE_SEQ) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001236 ND_PRINT((ndo, "[!SEQ of varbind]"));
1237 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001238 return;
1239 }
1240 if ((u_int)count < length)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001241 ND_PRINT((ndo, "[%d extra after SEQ of varbind]", length - count));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001242 /* descend */
1243 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001244 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001245
1246 for (ind = 1; length > 0; ind++) {
1247 const u_char *vbend;
1248 u_int vblength;
1249
Elliott Hughes892a68b2015-10-19 14:43:53 -07001250 ND_PRINT((ndo, " "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001251
1252 /* Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001253 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001254 return;
1255 if (elem.type != BE_SEQ) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001256 ND_PRINT((ndo, "[!varbind]"));
1257 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001258 return;
1259 }
1260 vbend = np + count;
1261 vblength = length - count;
1262 /* descend */
1263 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001264 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001265
1266 /* objName (OID) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001267 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001268 return;
1269 if (elem.type != BE_OID) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001270 ND_PRINT((ndo, "[objName!=OID]"));
1271 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001272 return;
1273 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001274#ifdef USE_LIBSMI
1275 smiNode = smi_print_variable(ndo, &elem, &status);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001276#else
Elliott Hughes892a68b2015-10-19 14:43:53 -07001277 status = asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001278#endif
1279 if (status < 0)
1280 return;
1281 length -= count;
1282 np += count;
1283
1284 if (pduid != GETREQ && pduid != GETNEXTREQ
1285 && pduid != GETBULKREQ)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001286 ND_PRINT((ndo, "="));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001287
1288 /* objVal (ANY) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001289 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001290 return;
1291 if (pduid == GETREQ || pduid == GETNEXTREQ
1292 || pduid == GETBULKREQ) {
1293 if (elem.type != BE_NULL) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001294 ND_PRINT((ndo, "[objVal!=NULL]"));
1295 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001296 return;
1297 }
1298 } else {
1299 if (elem.type != BE_NULL) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001300#ifdef USE_LIBSMI
1301 status = smi_print_value(ndo, smiNode, pduid, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001302#else
Elliott Hughes892a68b2015-10-19 14:43:53 -07001303 status = asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001304#endif
1305 }
1306 if (status < 0)
1307 return;
1308 }
1309 length = vblength;
1310 np = vbend;
1311 }
1312}
1313
1314/*
1315 * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest,
1316 * GetBulk, Inform, V2Trap, and Report
1317 */
1318static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001319snmppdu_print(netdissect_options *ndo,
1320 u_short pduid, const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001321{
1322 struct be elem;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001323 int count = 0, error_status;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001324
1325 /* reqId (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001326 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001327 return;
1328 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001329 ND_PRINT((ndo, "[reqId!=INT]"));
1330 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001331 return;
1332 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001333 if (ndo->ndo_vflag)
1334 ND_PRINT((ndo, "R=%d ", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001335 length -= count;
1336 np += count;
1337
1338 /* errorStatus (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001339 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001340 return;
1341 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001342 ND_PRINT((ndo, "[errorStatus!=INT]"));
1343 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001344 return;
1345 }
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001346 error_status = 0;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001347 if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
1348 || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
1349 && elem.data.integer != 0) {
1350 char errbuf[20];
Elliott Hughes892a68b2015-10-19 14:43:53 -07001351 ND_PRINT((ndo, "[errorStatus(%s)!=0]",
1352 DECODE_ErrorStatus(elem.data.integer)));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001353 } else if (pduid == GETBULKREQ) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001354 ND_PRINT((ndo, " N=%d", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001355 } else if (elem.data.integer != 0) {
1356 char errbuf[20];
Elliott Hughes892a68b2015-10-19 14:43:53 -07001357 ND_PRINT((ndo, " %s", DECODE_ErrorStatus(elem.data.integer)));
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001358 error_status = elem.data.integer;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001359 }
1360 length -= count;
1361 np += count;
1362
1363 /* errorIndex (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001364 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001365 return;
1366 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001367 ND_PRINT((ndo, "[errorIndex!=INT]"));
1368 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001369 return;
1370 }
1371 if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
1372 || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
1373 && elem.data.integer != 0)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001374 ND_PRINT((ndo, "[errorIndex(%d)!=0]", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001375 else if (pduid == GETBULKREQ)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001376 ND_PRINT((ndo, " M=%d", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001377 else if (elem.data.integer != 0) {
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001378 if (!error_status)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001379 ND_PRINT((ndo, "[errorIndex(%d) w/o errorStatus]", elem.data.integer));
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001380 else
Elliott Hughes892a68b2015-10-19 14:43:53 -07001381 ND_PRINT((ndo, "@%d", elem.data.integer));
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001382 } else if (error_status) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001383 ND_PRINT((ndo, "[errorIndex==0]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001384 }
1385 length -= count;
1386 np += count;
1387
Elliott Hughes892a68b2015-10-19 14:43:53 -07001388 varbind_print(ndo, pduid, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001389 return;
1390}
1391
1392/*
1393 * Decode SNMP Trap PDU
1394 */
1395static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001396trappdu_print(netdissect_options *ndo,
1397 const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001398{
1399 struct be elem;
1400 int count = 0, generic;
1401
Elliott Hughes892a68b2015-10-19 14:43:53 -07001402 ND_PRINT((ndo, " "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001403
1404 /* enterprise (oid) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001405 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001406 return;
1407 if (elem.type != BE_OID) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001408 ND_PRINT((ndo, "[enterprise!=OID]"));
1409 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001410 return;
1411 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001412 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001413 return;
1414 length -= count;
1415 np += count;
1416
Elliott Hughes892a68b2015-10-19 14:43:53 -07001417 ND_PRINT((ndo, " "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001418
1419 /* agent-addr (inetaddr) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001420 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001421 return;
1422 if (elem.type != BE_INETADDR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001423 ND_PRINT((ndo, "[agent-addr!=INETADDR]"));
1424 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001425 return;
1426 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001427 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001428 return;
1429 length -= count;
1430 np += count;
1431
1432 /* generic-trap (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001433 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001434 return;
1435 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001436 ND_PRINT((ndo, "[generic-trap!=INT]"));
1437 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001438 return;
1439 }
1440 generic = elem.data.integer;
1441 {
1442 char buf[20];
Elliott Hughes892a68b2015-10-19 14:43:53 -07001443 ND_PRINT((ndo, " %s", DECODE_GenericTrap(generic)));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001444 }
1445 length -= count;
1446 np += count;
1447
1448 /* specific-trap (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001449 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001450 return;
1451 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001452 ND_PRINT((ndo, "[specific-trap!=INT]"));
1453 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001454 return;
1455 }
1456 if (generic != GT_ENTERPRISE) {
1457 if (elem.data.integer != 0)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001458 ND_PRINT((ndo, "[specific-trap(%d)!=0]", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001459 } else
Elliott Hughes892a68b2015-10-19 14:43:53 -07001460 ND_PRINT((ndo, " s=%d", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001461 length -= count;
1462 np += count;
1463
Elliott Hughes892a68b2015-10-19 14:43:53 -07001464 ND_PRINT((ndo, " "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001465
1466 /* time-stamp (TimeTicks) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001467 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001468 return;
1469 if (elem.type != BE_UNS) { /* XXX */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001470 ND_PRINT((ndo, "[time-stamp!=TIMETICKS]"));
1471 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001472 return;
1473 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001474 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001475 return;
1476 length -= count;
1477 np += count;
1478
Elliott Hughes892a68b2015-10-19 14:43:53 -07001479 varbind_print(ndo, TRAP, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001480 return;
1481}
1482
1483/*
1484 * Decode arbitrary SNMP PDUs.
1485 */
1486static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001487pdu_print(netdissect_options *ndo,
1488 const u_char *np, u_int length, int version)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001489{
1490 struct be pdu;
1491 int count = 0;
1492
1493 /* PDU (Context) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001494 if ((count = asn1_parse(ndo, np, length, &pdu)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001495 return;
1496 if (pdu.type != BE_PDU) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001497 ND_PRINT((ndo, "[no PDU]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001498 return;
1499 }
1500 if ((u_int)count < length)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001501 ND_PRINT((ndo, "[%d extra after PDU]", length - count));
1502 if (ndo->ndo_vflag) {
1503 ND_PRINT((ndo, "{ "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001504 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001505 if (asn1_print(ndo, &pdu) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001506 return;
Elliott Hughes892a68b2015-10-19 14:43:53 -07001507 ND_PRINT((ndo, " "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001508 /* descend into PDU */
1509 length = pdu.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001510 np = (const u_char *)pdu.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001511
1512 if (version == SNMP_VERSION_1 &&
1513 (pdu.id == GETBULKREQ || pdu.id == INFORMREQ ||
1514 pdu.id == V2TRAP || pdu.id == REPORT)) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001515 ND_PRINT((ndo, "[v2 PDU in v1 message]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001516 return;
1517 }
1518
1519 if (version == SNMP_VERSION_2 && pdu.id == TRAP) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001520 ND_PRINT((ndo, "[v1 PDU in v2 message]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001521 return;
1522 }
1523
1524 switch (pdu.id) {
1525 case TRAP:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001526 trappdu_print(ndo, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001527 break;
1528 case GETREQ:
1529 case GETNEXTREQ:
1530 case GETRESP:
1531 case SETREQ:
1532 case GETBULKREQ:
1533 case INFORMREQ:
1534 case V2TRAP:
1535 case REPORT:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001536 snmppdu_print(ndo, pdu.id, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001537 break;
1538 }
1539
Elliott Hughes892a68b2015-10-19 14:43:53 -07001540 if (ndo->ndo_vflag) {
1541 ND_PRINT((ndo, " } "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001542 }
1543}
1544
1545/*
1546 * Decode a scoped SNMP PDU.
1547 */
1548static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001549scopedpdu_print(netdissect_options *ndo,
1550 const u_char *np, u_int length, int version)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001551{
1552 struct be elem;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001553 int count = 0;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001554
1555 /* Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001556 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001557 return;
1558 if (elem.type != BE_SEQ) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001559 ND_PRINT((ndo, "[!scoped PDU]"));
1560 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001561 return;
1562 }
1563 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001564 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001565
1566 /* contextEngineID (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001567 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001568 return;
1569 if (elem.type != BE_STR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001570 ND_PRINT((ndo, "[contextEngineID!=STR]"));
1571 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001572 return;
1573 }
1574 length -= count;
1575 np += count;
1576
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001577 ND_PRINT((ndo, "E="));
1578 if (asn1_print_octets(ndo, &elem) == -1)
1579 return;
Elliott Hughes892a68b2015-10-19 14:43:53 -07001580 ND_PRINT((ndo, " "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001581
1582 /* contextName (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001583 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001584 return;
1585 if (elem.type != BE_STR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001586 ND_PRINT((ndo, "[contextName!=STR]"));
1587 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001588 return;
1589 }
1590 length -= count;
1591 np += count;
1592
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001593 ND_PRINT((ndo, "C="));
1594 if (asn1_print_string(ndo, &elem) == -1)
1595 return;
1596 ND_PRINT((ndo, " "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001597
Elliott Hughes892a68b2015-10-19 14:43:53 -07001598 pdu_print(ndo, np, length, version);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001599}
1600
1601/*
1602 * Decode SNMP Community Header (SNMPv1 and SNMPv2c)
1603 */
1604static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001605community_print(netdissect_options *ndo,
1606 const u_char *np, u_int length, int version)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001607{
1608 struct be elem;
1609 int count = 0;
1610
1611 /* Community (String) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001612 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001613 return;
1614 if (elem.type != BE_STR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001615 ND_PRINT((ndo, "[comm!=STR]"));
1616 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001617 return;
1618 }
1619 /* default community */
1620 if (!(elem.asnlen == sizeof(DEF_COMMUNITY) - 1 &&
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001621 strncmp((const char *)elem.data.str, DEF_COMMUNITY,
1622 sizeof(DEF_COMMUNITY) - 1) == 0)) {
The Android Open Source Project2949f582009-03-03 19:30:46 -08001623 /* ! "public" */
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001624 ND_PRINT((ndo, "C="));
1625 if (asn1_print_string(ndo, &elem) == -1)
1626 return;
1627 ND_PRINT((ndo, " "));
1628 }
The Android Open Source Project2949f582009-03-03 19:30:46 -08001629 length -= count;
1630 np += count;
1631
Elliott Hughes892a68b2015-10-19 14:43:53 -07001632 pdu_print(ndo, np, length, version);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001633}
1634
1635/*
1636 * Decode SNMPv3 User-based Security Message Header (SNMPv3)
1637 */
1638static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001639usm_print(netdissect_options *ndo,
1640 const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001641{
1642 struct be elem;
1643 int count = 0;
1644
1645 /* Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001646 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001647 return;
1648 if (elem.type != BE_SEQ) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001649 ND_PRINT((ndo, "[!usm]"));
1650 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001651 return;
1652 }
1653 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001654 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001655
1656 /* msgAuthoritativeEngineID (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001657 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001658 return;
1659 if (elem.type != BE_STR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001660 ND_PRINT((ndo, "[msgAuthoritativeEngineID!=STR]"));
1661 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001662 return;
1663 }
1664 length -= count;
1665 np += count;
1666
1667 /* msgAuthoritativeEngineBoots (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001668 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001669 return;
1670 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001671 ND_PRINT((ndo, "[msgAuthoritativeEngineBoots!=INT]"));
1672 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001673 return;
1674 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001675 if (ndo->ndo_vflag)
1676 ND_PRINT((ndo, "B=%d ", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001677 length -= count;
1678 np += count;
1679
1680 /* msgAuthoritativeEngineTime (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001681 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001682 return;
1683 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001684 ND_PRINT((ndo, "[msgAuthoritativeEngineTime!=INT]"));
1685 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001686 return;
1687 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001688 if (ndo->ndo_vflag)
1689 ND_PRINT((ndo, "T=%d ", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001690 length -= count;
1691 np += count;
1692
1693 /* msgUserName (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001694 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001695 return;
1696 if (elem.type != BE_STR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001697 ND_PRINT((ndo, "[msgUserName!=STR]"));
1698 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001699 return;
1700 }
1701 length -= count;
1702 np += count;
1703
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001704 ND_PRINT((ndo, "U="));
1705 if (asn1_print_string(ndo, &elem) == -1)
1706 return;
1707 ND_PRINT((ndo, " "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001708
1709 /* msgAuthenticationParameters (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001710 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001711 return;
1712 if (elem.type != BE_STR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001713 ND_PRINT((ndo, "[msgAuthenticationParameters!=STR]"));
1714 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001715 return;
1716 }
1717 length -= count;
1718 np += count;
1719
1720 /* msgPrivacyParameters (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001721 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001722 return;
1723 if (elem.type != BE_STR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001724 ND_PRINT((ndo, "[msgPrivacyParameters!=STR]"));
1725 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001726 return;
1727 }
1728 length -= count;
1729 np += count;
1730
1731 if ((u_int)count < length)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001732 ND_PRINT((ndo, "[%d extra after usm SEQ]", length - count));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001733}
1734
1735/*
1736 * Decode SNMPv3 Message Header (SNMPv3)
1737 */
1738static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001739v3msg_print(netdissect_options *ndo,
1740 const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001741{
1742 struct be elem;
1743 int count = 0;
1744 u_char flags;
1745 int model;
1746 const u_char *xnp = np;
1747 int xlength = length;
1748
1749 /* Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001750 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001751 return;
1752 if (elem.type != BE_SEQ) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001753 ND_PRINT((ndo, "[!message]"));
1754 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001755 return;
1756 }
1757 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001758 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001759
Elliott Hughes892a68b2015-10-19 14:43:53 -07001760 if (ndo->ndo_vflag) {
1761 ND_PRINT((ndo, "{ "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001762 }
1763
1764 /* msgID (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001765 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001766 return;
1767 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001768 ND_PRINT((ndo, "[msgID!=INT]"));
1769 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001770 return;
1771 }
1772 length -= count;
1773 np += count;
1774
1775 /* msgMaxSize (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001776 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001777 return;
1778 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001779 ND_PRINT((ndo, "[msgMaxSize!=INT]"));
1780 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001781 return;
1782 }
1783 length -= count;
1784 np += count;
1785
1786 /* msgFlags (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001787 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001788 return;
1789 if (elem.type != BE_STR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001790 ND_PRINT((ndo, "[msgFlags!=STR]"));
1791 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001792 return;
1793 }
1794 if (elem.asnlen != 1) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001795 ND_PRINT((ndo, "[msgFlags size %d]", elem.asnlen));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001796 return;
1797 }
1798 flags = elem.data.str[0];
1799 if (flags != 0x00 && flags != 0x01 && flags != 0x03
1800 && flags != 0x04 && flags != 0x05 && flags != 0x07) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001801 ND_PRINT((ndo, "[msgFlags=0x%02X]", flags));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001802 return;
1803 }
1804 length -= count;
1805 np += count;
1806
Elliott Hughes892a68b2015-10-19 14:43:53 -07001807 ND_PRINT((ndo, "F=%s%s%s ",
1808 flags & 0x01 ? "a" : "",
1809 flags & 0x02 ? "p" : "",
1810 flags & 0x04 ? "r" : ""));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001811
1812 /* msgSecurityModel (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001813 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001814 return;
1815 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001816 ND_PRINT((ndo, "[msgSecurityModel!=INT]"));
1817 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001818 return;
1819 }
1820 model = elem.data.integer;
1821 length -= count;
1822 np += count;
1823
1824 if ((u_int)count < length)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001825 ND_PRINT((ndo, "[%d extra after message SEQ]", length - count));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001826
Elliott Hughes892a68b2015-10-19 14:43:53 -07001827 if (ndo->ndo_vflag) {
1828 ND_PRINT((ndo, "} "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001829 }
1830
1831 if (model == 3) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001832 if (ndo->ndo_vflag) {
1833 ND_PRINT((ndo, "{ USM "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001834 }
1835 } else {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001836 ND_PRINT((ndo, "[security model %d]", model));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001837 return;
1838 }
1839
1840 np = xnp + (np - xnp);
1841 length = xlength - (np - xnp);
1842
1843 /* msgSecurityParameters (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001844 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001845 return;
1846 if (elem.type != BE_STR) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001847 ND_PRINT((ndo, "[msgSecurityParameters!=STR]"));
1848 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001849 return;
1850 }
1851 length -= count;
1852 np += count;
1853
1854 if (model == 3) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001855 usm_print(ndo, elem.data.str, elem.asnlen);
1856 if (ndo->ndo_vflag) {
1857 ND_PRINT((ndo, "} "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001858 }
1859 }
1860
Elliott Hughes892a68b2015-10-19 14:43:53 -07001861 if (ndo->ndo_vflag) {
1862 ND_PRINT((ndo, "{ ScopedPDU "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001863 }
1864
Elliott Hughes892a68b2015-10-19 14:43:53 -07001865 scopedpdu_print(ndo, np, length, 3);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001866
Elliott Hughes892a68b2015-10-19 14:43:53 -07001867 if (ndo->ndo_vflag) {
1868 ND_PRINT((ndo, "} "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001869 }
1870}
1871
1872/*
1873 * Decode SNMP header and pass on to PDU printing routines
1874 */
1875void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001876snmp_print(netdissect_options *ndo,
1877 const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001878{
1879 struct be elem;
1880 int count = 0;
1881 int version = 0;
1882
Elliott Hughes892a68b2015-10-19 14:43:53 -07001883 ND_PRINT((ndo, " "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001884
1885 /* initial Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001886 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001887 return;
1888 if (elem.type != BE_SEQ) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001889 ND_PRINT((ndo, "[!init SEQ]"));
1890 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001891 return;
1892 }
1893 if ((u_int)count < length)
Elliott Hughes892a68b2015-10-19 14:43:53 -07001894 ND_PRINT((ndo, "[%d extra after iSEQ]", length - count));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001895 /* descend */
1896 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001897 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001898
1899 /* Version (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001900 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001901 return;
1902 if (elem.type != BE_INT) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001903 ND_PRINT((ndo, "[version!=INT]"));
1904 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001905 return;
1906 }
1907
1908 switch (elem.data.integer) {
1909 case SNMP_VERSION_1:
1910 case SNMP_VERSION_2:
1911 case SNMP_VERSION_3:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001912 if (ndo->ndo_vflag)
1913 ND_PRINT((ndo, "{ %s ", SnmpVersion[elem.data.integer]));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001914 break;
1915 default:
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001916 ND_PRINT((ndo, "SNMP [version = %d]", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001917 return;
1918 }
1919 version = elem.data.integer;
1920 length -= count;
1921 np += count;
1922
1923 switch (version) {
1924 case SNMP_VERSION_1:
1925 case SNMP_VERSION_2:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001926 community_print(ndo, np, length, version);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001927 break;
1928 case SNMP_VERSION_3:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001929 v3msg_print(ndo, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001930 break;
1931 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001932 ND_PRINT((ndo, "[version = %d]", elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001933 break;
1934 }
1935
Elliott Hughes892a68b2015-10-19 14:43:53 -07001936 if (ndo->ndo_vflag) {
1937 ND_PRINT((ndo, "} "));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001938 }
1939}