blob: a38fee2e4f25970a7035553a2918f67c5e5e78ef [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
Elliott Hughes820eced2021-08-20 18:00:50 -070062#include <config.h>
The Android Open Source Project2949f582009-03-03 19:30:46 -080063#endif
64
Elliott Hughes820eced2021-08-20 18:00:50 -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 Hughes820eced2021-08-20 18:00:50 -070074#include "netdissect-ctype.h"
75
Elliott Hughese2e3bd12017-05-15 10:59:29 -070076#include "netdissect.h"
Elliott Hughes820eced2021-08-20 18:00:50 -070077#include "extract.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080078
79#undef OPAQUE /* defined in <wingdi.h> */
80
Elliott Hughes892a68b2015-10-19 14:43:53 -070081
The Android Open Source Project2949f582009-03-03 19:30:46 -080082/*
83 * Universal ASN.1 types
84 * (we only care about the tag values for those allowed in the Internet SMI)
85 */
Elliott Hughes892a68b2015-10-19 14:43:53 -070086static const char *Universal[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -080087 "U-0",
88 "Boolean",
89 "Integer",
90#define INTEGER 2
91 "Bitstring",
92 "String",
93#define STRING 4
94 "Null",
95#define ASN_NULL 5
96 "ObjID",
97#define OBJECTID 6
98 "ObjectDes",
99 "U-8","U-9","U-10","U-11", /* 8-11 */
100 "U-12","U-13","U-14","U-15", /* 12-15 */
101 "Sequence",
102#define SEQUENCE 16
103 "Set"
104};
105
106/*
107 * Application-wide ASN.1 types from the Internet SMI and their tags
108 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700109static const char *Application[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800110 "IpAddress",
111#define IPADDR 0
112 "Counter",
113#define COUNTER 1
114 "Gauge",
115#define GAUGE 2
116 "TimeTicks",
117#define TIMETICKS 3
118 "Opaque",
119#define OPAQUE 4
120 "C-5",
121 "Counter64"
122#define COUNTER64 6
123};
124
125/*
126 * Context-specific ASN.1 types for the SNMP PDUs and their tags
127 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700128static const char *Context[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800129 "GetRequest",
130#define GETREQ 0
131 "GetNextRequest",
132#define GETNEXTREQ 1
133 "GetResponse",
134#define GETRESP 2
135 "SetRequest",
136#define SETREQ 3
137 "Trap",
138#define TRAP 4
139 "GetBulk",
140#define GETBULKREQ 5
141 "Inform",
142#define INFORMREQ 6
143 "V2Trap",
144#define V2TRAP 7
145 "Report"
146#define REPORT 8
147};
148
149#define NOTIFY_CLASS(x) (x == TRAP || x == V2TRAP || x == INFORMREQ)
150#define READ_CLASS(x) (x == GETREQ || x == GETNEXTREQ || x == GETBULKREQ)
151#define WRITE_CLASS(x) (x == SETREQ)
152#define RESPONSE_CLASS(x) (x == GETRESP)
153#define INTERNAL_CLASS(x) (x == REPORT)
154
155/*
156 * Context-specific ASN.1 types for the SNMP Exceptions and their tags
157 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700158static const char *Exceptions[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800159 "noSuchObject",
160#define NOSUCHOBJECT 0
161 "noSuchInstance",
162#define NOSUCHINSTANCE 1
163 "endOfMibView",
164#define ENDOFMIBVIEW 2
165};
166
167/*
168 * Private ASN.1 types
169 * The Internet SMI does not specify any
170 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700171static const char *Private[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800172 "P-0"
173};
174
175/*
176 * error-status values for any SNMP PDU
177 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700178static const char *ErrorStatus[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800179 "noError",
180 "tooBig",
181 "noSuchName",
182 "badValue",
183 "readOnly",
184 "genErr",
185 "noAccess",
186 "wrongType",
187 "wrongLength",
188 "wrongEncoding",
189 "wrongValue",
190 "noCreation",
191 "inconsistentValue",
192 "resourceUnavailable",
193 "commitFailed",
194 "undoFailed",
195 "authorizationError",
196 "notWritable",
197 "inconsistentName"
198};
199#define DECODE_ErrorStatus(e) \
200 ( e >= 0 && (size_t)e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
201 ? ErrorStatus[e] \
202 : (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf))
203
204/*
205 * generic-trap values in the SNMP Trap-PDU
206 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700207static const char *GenericTrap[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800208 "coldStart",
209 "warmStart",
210 "linkDown",
211 "linkUp",
212 "authenticationFailure",
213 "egpNeighborLoss",
214 "enterpriseSpecific"
215#define GT_ENTERPRISE 6
216};
217#define DECODE_GenericTrap(t) \
218 ( t >= 0 && (size_t)t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
219 ? GenericTrap[t] \
220 : (snprintf(buf, sizeof(buf), "gt=%d", t), buf))
221
222/*
223 * ASN.1 type class table
224 * Ties together the preceding Universal, Application, Context, and Private
225 * type definitions.
226 */
227#define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700228static const struct {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800229 const char *name;
230 const char **Id;
231 int numIDs;
232 } Class[] = {
233 defineCLASS(Universal),
234#define UNIVERSAL 0
235 defineCLASS(Application),
236#define APPLICATION 1
237 defineCLASS(Context),
238#define CONTEXT 2
239 defineCLASS(Private),
240#define PRIVATE 3
241 defineCLASS(Exceptions),
242#define EXCEPTIONS 4
243};
244
245/*
246 * defined forms for ASN.1 types
247 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700248static const char *Form[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800249 "Primitive",
250#define PRIMITIVE 0
251 "Constructed",
252#define CONSTRUCTED 1
253};
254
255/*
256 * A structure for the OID tree for the compiled-in MIB.
257 * This is stored as a general-order tree.
258 */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700259static struct obj {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800260 const char *desc; /* name of object */
261 u_char oid; /* sub-id following parent */
262 u_char type; /* object type (unused) */
263 struct obj *child, *next; /* child and next sibling pointers */
264} *objp = NULL;
265
266/*
267 * Include the compiled in SNMP MIB. "mib.h" is produced by feeding
268 * RFC-1156 format files into "makemib". "mib.h" MUST define at least
269 * a value for `mibroot'.
270 *
271 * In particular, this is gross, as this is including initialized structures,
272 * and by right shouldn't be an "include" file.
273 */
274#include "mib.h"
275
276/*
277 * This defines a list of OIDs which will be abbreviated on output.
278 * Currently, this includes the prefixes for the Internet MIB, the
279 * private enterprises tree, and the experimental tree.
280 */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700281#define OID_FIRST_OCTET(x, y) (((x)*40) + (y)) /* X.690 8.19.4 */
282
283#ifndef NO_ABREV_MIB
284static const uint8_t mib_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 2, 1 };
285#endif
286#ifndef NO_ABREV_ENTER
287static const uint8_t enterprises_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 4, 1 };
288#endif
289#ifndef NO_ABREV_EXPERI
290static const uint8_t experimental_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 3 };
291#endif
292#ifndef NO_ABBREV_SNMPMODS
293static const uint8_t snmpModules_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 6, 3 };
294#endif
295
296#define OBJ_ABBREV_ENTRY(prefix, obj) \
297 { prefix, &_ ## obj ## _obj, obj ## _oid, sizeof (obj ## _oid) }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700298static const struct obj_abrev {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800299 const char *prefix; /* prefix for this abrev */
300 struct obj *node; /* pointer into object table */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700301 const uint8_t *oid; /* ASN.1 encoded OID */
302 size_t oid_len; /* length of OID */
The Android Open Source Project2949f582009-03-03 19:30:46 -0800303} obj_abrev_list[] = {
304#ifndef NO_ABREV_MIB
305 /* .iso.org.dod.internet.mgmt.mib */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700306 OBJ_ABBREV_ENTRY("", mib),
The Android Open Source Project2949f582009-03-03 19:30:46 -0800307#endif
308#ifndef NO_ABREV_ENTER
309 /* .iso.org.dod.internet.private.enterprises */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700310 OBJ_ABBREV_ENTRY("E:", enterprises),
The Android Open Source Project2949f582009-03-03 19:30:46 -0800311#endif
312#ifndef NO_ABREV_EXPERI
313 /* .iso.org.dod.internet.experimental */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700314 OBJ_ABBREV_ENTRY("X:", experimental),
The Android Open Source Project2949f582009-03-03 19:30:46 -0800315#endif
316#ifndef NO_ABBREV_SNMPMODS
317 /* .iso.org.dod.internet.snmpV2.snmpModules */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700318 OBJ_ABBREV_ENTRY("S:", snmpModules),
The Android Open Source Project2949f582009-03-03 19:30:46 -0800319#endif
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700320 { 0,0,0,0 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800321};
322
323/*
324 * This is used in the OID print routine to walk down the object tree
325 * rooted at `mibroot'.
326 */
327#define OBJ_PRINT(o, suppressdot) \
328{ \
329 if (objp) { \
330 do { \
331 if ((o) == objp->oid) \
332 break; \
333 } while ((objp = objp->next) != NULL); \
334 } \
335 if (objp) { \
Elliott Hughes820eced2021-08-20 18:00:50 -0700336 ND_PRINT(suppressdot?"%s":".%s", objp->desc); \
The Android Open Source Project2949f582009-03-03 19:30:46 -0800337 objp = objp->child; \
338 } else \
Elliott Hughes820eced2021-08-20 18:00:50 -0700339 ND_PRINT(suppressdot?"%u":".%u", (o)); \
The Android Open Source Project2949f582009-03-03 19:30:46 -0800340}
341
342/*
343 * This is the definition for the Any-Data-Type storage used purely for
344 * temporary internal representation while decoding an ASN.1 data stream.
345 */
346struct be {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700347 uint32_t asnlen;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800348 union {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700349 const uint8_t *raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800350 int32_t integer;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700351 uint32_t uns;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800352 const u_char *str;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700353 uint64_t uns64;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800354 } data;
355 u_short id;
356 u_char form, class; /* tag info */
357 u_char type;
358#define BE_ANY 255
359#define BE_NONE 0
360#define BE_NULL 1
361#define BE_OCTET 2
362#define BE_OID 3
363#define BE_INT 4
364#define BE_UNS 5
365#define BE_STR 6
366#define BE_SEQ 7
367#define BE_INETADDR 8
368#define BE_PDU 9
369#define BE_UNS64 10
370#define BE_NOSUCHOBJECT 128
371#define BE_NOSUCHINST 129
372#define BE_ENDOFMIBVIEW 130
373};
374
375/*
376 * SNMP versions recognized by this module
377 */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700378static const char *SnmpVersion[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800379 "SNMPv1",
380#define SNMP_VERSION_1 0
381 "SNMPv2c",
382#define SNMP_VERSION_2 1
383 "SNMPv2u",
384#define SNMP_VERSION_2U 2
385 "SNMPv3"
386#define SNMP_VERSION_3 3
387};
388
389/*
390 * Defaults for SNMP PDU components
391 */
392#define DEF_COMMUNITY "public"
393
394/*
395 * constants for ASN.1 decoding
396 */
397#define OIDMUX 40
398#define ASNLEN_INETADDR 4
399#define ASN_SHIFT7 7
400#define ASN_SHIFT8 8
401#define ASN_BIT8 0x80
402#define ASN_LONGLEN 0x80
403
404#define ASN_ID_BITS 0x1f
405#define ASN_FORM_BITS 0x20
406#define ASN_FORM_SHIFT 5
407#define ASN_CLASS_BITS 0xc0
408#define ASN_CLASS_SHIFT 6
409
410#define ASN_ID_EXT 0x1f /* extension ID in tag field */
411
412/*
413 * This decodes the next ASN.1 object in the stream pointed to by "p"
414 * (and of real-length "len") and stores the intermediate data in the
415 * provided BE object.
416 *
417 * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
418 * O/w, this returns the number of bytes parsed from "p".
419 */
420static int
Elliott Hughes892a68b2015-10-19 14:43:53 -0700421asn1_parse(netdissect_options *ndo,
Elliott Hughes820eced2021-08-20 18:00:50 -0700422 const u_char *p, u_int len, struct be *elem)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800423{
424 u_char form, class, id;
Elliott Hughes820eced2021-08-20 18:00:50 -0700425 u_int i, hdr;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800426
427 elem->asnlen = 0;
428 elem->type = BE_ANY;
429 if (len < 1) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700430 ND_PRINT("[nothing to parse]");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800431 return -1;
432 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800433
434 /*
435 * it would be nice to use a bit field, but you can't depend on them.
436 * +---+---+---+---+---+---+---+---+
437 * + class |frm| id |
438 * +---+---+---+---+---+---+---+---+
439 * 7 6 5 4 3 2 1 0
440 */
Elliott Hughes820eced2021-08-20 18:00:50 -0700441 id = GET_U_1(p) & ASN_ID_BITS; /* lower 5 bits, range 00-1f */
The Android Open Source Project2949f582009-03-03 19:30:46 -0800442#ifdef notdef
Elliott Hughes820eced2021-08-20 18:00:50 -0700443 form = (GET_U_1(p) & 0xe0) >> 5; /* move upper 3 bits to lower 3 */
The Android Open Source Project2949f582009-03-03 19:30:46 -0800444 class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */
445 form &= 0x1; /* bit 5 -> bit 0, range 0-1 */
446#else
Elliott Hughes820eced2021-08-20 18:00:50 -0700447 form = (u_char)(GET_U_1(p) & ASN_FORM_BITS) >> ASN_FORM_SHIFT;
448 class = (u_char)(GET_U_1(p) & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800449#endif
450 elem->form = form;
451 elem->class = class;
452 elem->id = id;
453 p++; len--; hdr = 1;
454 /* extended tag field */
455 if (id == ASN_ID_EXT) {
456 /*
457 * The ID follows, as a sequence of octets with the
458 * 8th bit set and the remaining 7 bits being
459 * the next 7 bits of the value, terminated with
460 * an octet with the 8th bit not set.
461 *
462 * First, assemble all the octets with the 8th
463 * bit set. XXX - this doesn't handle a value
464 * that won't fit in 32 bits.
465 */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700466 id = 0;
Elliott Hughes820eced2021-08-20 18:00:50 -0700467 while (GET_U_1(p) & ASN_BIT8) {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800468 if (len < 1) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700469 ND_PRINT("[Xtagfield?]");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800470 return -1;
471 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700472 id = (id << 7) | (GET_U_1(p) & ~ASN_BIT8);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700473 len--;
474 hdr++;
475 p++;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800476 }
477 if (len < 1) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700478 ND_PRINT("[Xtagfield?]");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800479 return -1;
480 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700481 elem->id = id = (id << 7) | GET_U_1(p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800482 --len;
483 ++hdr;
484 ++p;
485 }
486 if (len < 1) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700487 ND_PRINT("[no asnlen]");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800488 return -1;
489 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700490 elem->asnlen = GET_U_1(p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800491 p++; len--; hdr++;
492 if (elem->asnlen & ASN_BIT8) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700493 uint32_t noct = elem->asnlen % ASN_BIT8;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800494 elem->asnlen = 0;
495 if (len < noct) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700496 ND_PRINT("[asnlen? %d<%d]", len, noct);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800497 return -1;
498 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700499 ND_TCHECK_LEN(p, noct);
500 for (; noct != 0; len--, hdr++, noct--) {
501 elem->asnlen = (elem->asnlen << ASN_SHIFT8) | GET_U_1(p);
502 p++;
503 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800504 }
505 if (len < elem->asnlen) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700506 ND_PRINT("[len%d<asnlen%u]", len, elem->asnlen);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800507 return -1;
508 }
509 if (form >= sizeof(Form)/sizeof(Form[0])) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700510 ND_PRINT("[form?%d]", form);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800511 return -1;
512 }
513 if (class >= sizeof(Class)/sizeof(Class[0])) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700514 ND_PRINT("[class?%c/%d]", *Form[form], class);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800515 return -1;
516 }
517 if ((int)id >= Class[class].numIDs) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700518 ND_PRINT("[id?%c/%s/%d]", *Form[form], Class[class].name, id);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800519 return -1;
520 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700521 ND_TCHECK_LEN(p, elem->asnlen);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800522
523 switch (form) {
524 case PRIMITIVE:
525 switch (class) {
526 case UNIVERSAL:
527 switch (id) {
528 case STRING:
529 elem->type = BE_STR;
530 elem->data.str = p;
531 break;
532
533 case INTEGER: {
Elliott Hughes820eced2021-08-20 18:00:50 -0700534 int32_t data;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800535 elem->type = BE_INT;
536 data = 0;
537
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700538 if (elem->asnlen == 0) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700539 ND_PRINT("[asnlen=0]");
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700540 return -1;
541 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700542 if (GET_U_1(p) & ASN_BIT8) /* negative */
The Android Open Source Project2949f582009-03-03 19:30:46 -0800543 data = -1;
Elliott Hughes820eced2021-08-20 18:00:50 -0700544 for (i = elem->asnlen; i != 0; p++, i--)
545 data = (data << ASN_SHIFT8) | GET_U_1(p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800546 elem->data.integer = data;
547 break;
548 }
549
550 case OBJECTID:
551 elem->type = BE_OID;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700552 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800553 break;
554
555 case ASN_NULL:
556 elem->type = BE_NULL;
557 elem->data.raw = NULL;
558 break;
559
560 default:
561 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700562 elem->data.raw = (const uint8_t *)p;
Elliott Hughes820eced2021-08-20 18:00:50 -0700563 ND_PRINT("[P/U/%s]", Class[class].Id[id]);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800564 break;
565 }
566 break;
567
568 case APPLICATION:
569 switch (id) {
570 case IPADDR:
571 elem->type = BE_INETADDR;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700572 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800573 break;
574
575 case COUNTER:
576 case GAUGE:
577 case TIMETICKS: {
Elliott Hughes820eced2021-08-20 18:00:50 -0700578 uint32_t data;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800579 elem->type = BE_UNS;
580 data = 0;
Elliott Hughes820eced2021-08-20 18:00:50 -0700581 for (i = elem->asnlen; i != 0; p++, i--)
582 data = (data << 8) + GET_U_1(p);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800583 elem->data.uns = data;
584 break;
585 }
586
587 case COUNTER64: {
Elliott Hughes820eced2021-08-20 18:00:50 -0700588 uint64_t data64;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800589 elem->type = BE_UNS64;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700590 data64 = 0;
Elliott Hughes820eced2021-08-20 18:00:50 -0700591 for (i = elem->asnlen; i != 0; p++, i--)
592 data64 = (data64 << 8) + GET_U_1(p);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700593 elem->data.uns64 = data64;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800594 break;
595 }
596
597 default:
598 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700599 elem->data.raw = (const uint8_t *)p;
Elliott Hughes820eced2021-08-20 18:00:50 -0700600 ND_PRINT("[P/A/%s]",
601 Class[class].Id[id]);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800602 break;
603 }
604 break;
605
606 case CONTEXT:
607 switch (id) {
608 case NOSUCHOBJECT:
609 elem->type = BE_NOSUCHOBJECT;
610 elem->data.raw = NULL;
611 break;
612
613 case NOSUCHINSTANCE:
614 elem->type = BE_NOSUCHINST;
615 elem->data.raw = NULL;
616 break;
617
618 case ENDOFMIBVIEW:
619 elem->type = BE_ENDOFMIBVIEW;
620 elem->data.raw = NULL;
621 break;
622 }
623 break;
624
625 default:
Elliott Hughes820eced2021-08-20 18:00:50 -0700626 ND_PRINT("[P/%s/%s]", Class[class].name, Class[class].Id[id]);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800627 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700628 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800629 break;
630 }
631 break;
632
633 case CONSTRUCTED:
634 switch (class) {
635 case UNIVERSAL:
636 switch (id) {
637 case SEQUENCE:
638 elem->type = BE_SEQ;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700639 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800640 break;
641
642 default:
643 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700644 elem->data.raw = (const uint8_t *)p;
Elliott Hughes820eced2021-08-20 18:00:50 -0700645 ND_PRINT("C/U/%s", Class[class].Id[id]);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800646 break;
647 }
648 break;
649
650 case CONTEXT:
651 elem->type = BE_PDU;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700652 elem->data.raw = (const uint8_t *)p;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800653 break;
654
655 default:
656 elem->type = BE_OCTET;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700657 elem->data.raw = (const uint8_t *)p;
Elliott Hughes820eced2021-08-20 18:00:50 -0700658 ND_PRINT("C/%s/%s", Class[class].name, Class[class].Id[id]);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800659 break;
660 }
661 break;
662 }
663 p += elem->asnlen;
664 len -= elem->asnlen;
665 return elem->asnlen + hdr;
666
667trunc:
Elliott Hughes820eced2021-08-20 18:00:50 -0700668 nd_print_trunc(ndo);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800669 return -1;
670}
671
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700672static int
673asn1_print_octets(netdissect_options *ndo, struct be *elem)
674{
675 const u_char *p = (const u_char *)elem->data.raw;
676 uint32_t asnlen = elem->asnlen;
677 uint32_t i;
678
Elliott Hughes820eced2021-08-20 18:00:50 -0700679 ND_TCHECK_LEN(p, asnlen);
680 for (i = asnlen; i != 0; p++, i--)
681 ND_PRINT("_%.2x", GET_U_1(p));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700682 return 0;
683
684trunc:
Elliott Hughes820eced2021-08-20 18:00:50 -0700685 nd_print_trunc(ndo);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700686 return -1;
687}
688
689static int
690asn1_print_string(netdissect_options *ndo, struct be *elem)
691{
Elliott Hughes820eced2021-08-20 18:00:50 -0700692 int printable = 1, first = 1;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700693 const u_char *p;
694 uint32_t asnlen = elem->asnlen;
695 uint32_t i;
696
697 p = elem->data.str;
Elliott Hughes820eced2021-08-20 18:00:50 -0700698 ND_TCHECK_LEN(p, asnlen);
699 for (i = asnlen; printable && i != 0; p++, i--)
700 printable = ND_ASCII_ISPRINT(GET_U_1(p));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700701 p = elem->data.str;
702 if (printable) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700703 ND_PRINT("\"");
704 if (nd_printn(ndo, p, asnlen, ndo->ndo_snapend)) {
705 ND_PRINT("\"");
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700706 goto trunc;
707 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700708 ND_PRINT("\"");
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700709 } else {
Elliott Hughes820eced2021-08-20 18:00:50 -0700710 for (i = asnlen; i != 0; p++, i--) {
711 ND_PRINT(first ? "%.2x" : "_%.2x", GET_U_1(p));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700712 first = 0;
713 }
714 }
715 return 0;
716
717trunc:
Elliott Hughes820eced2021-08-20 18:00:50 -0700718 nd_print_trunc(ndo);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700719 return -1;
720}
721
The Android Open Source Project2949f582009-03-03 19:30:46 -0800722/*
723 * Display the ASN.1 object represented by the BE object.
724 * This used to be an integral part of asn1_parse() before the intermediate
725 * BE form was added.
726 */
727static int
Elliott Hughes892a68b2015-10-19 14:43:53 -0700728asn1_print(netdissect_options *ndo,
729 struct be *elem)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800730{
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700731 const u_char *p;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700732 uint32_t asnlen = elem->asnlen;
733 uint32_t i;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800734
735 switch (elem->type) {
736
737 case BE_OCTET:
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700738 if (asn1_print_octets(ndo, elem) == -1)
739 return -1;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800740 break;
741
742 case BE_NULL:
743 break;
744
745 case BE_OID: {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700746 int o = 0, first = -1;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800747
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700748 p = (const u_char *)elem->data.raw;
749 i = asnlen;
750 if (!ndo->ndo_nflag && asnlen > 2) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700751 const struct obj_abrev *a = &obj_abrev_list[0];
The Android Open Source Project2949f582009-03-03 19:30:46 -0800752 for (; a->node; a++) {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700753 if (i < a->oid_len)
754 continue;
Elliott Hughes820eced2021-08-20 18:00:50 -0700755 if (!ND_TTEST_LEN(p, a->oid_len))
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700756 continue;
757 if (memcmp(a->oid, p, a->oid_len) == 0) {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800758 objp = a->node->child;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700759 i -= a->oid_len;
760 p += a->oid_len;
Elliott Hughes820eced2021-08-20 18:00:50 -0700761 ND_PRINT("%s", a->prefix);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800762 first = 1;
763 break;
764 }
765 }
766 }
767
Elliott Hughes820eced2021-08-20 18:00:50 -0700768 for (; i != 0; p++, i--) {
769 o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8);
770 if (GET_U_1(p) & ASN_LONGLEN)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800771 continue;
772
773 /*
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700774 * first subitem encodes two items with
775 * 1st*OIDMUX+2nd
The Android Open Source Project2949f582009-03-03 19:30:46 -0800776 * (see X.690:1997 clause 8.19 for the details)
777 */
778 if (first < 0) {
779 int s;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700780 if (!ndo->ndo_nflag)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800781 objp = mibroot;
782 first = 0;
783 s = o / OIDMUX;
784 if (s > 2) s = 2;
785 OBJ_PRINT(s, first);
786 o -= s * OIDMUX;
787 }
788 OBJ_PRINT(o, first);
789 if (--first < 0)
790 first = 0;
791 o = 0;
792 }
793 break;
794 }
795
796 case BE_INT:
Elliott Hughes820eced2021-08-20 18:00:50 -0700797 ND_PRINT("%d", elem->data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800798 break;
799
800 case BE_UNS:
Elliott Hughes820eced2021-08-20 18:00:50 -0700801 ND_PRINT("%u", elem->data.uns);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800802 break;
803
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700804 case BE_UNS64:
Elliott Hughes820eced2021-08-20 18:00:50 -0700805 ND_PRINT("%" PRIu64, elem->data.uns64);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800806 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800807
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700808 case BE_STR:
809 if (asn1_print_string(ndo, elem) == -1)
810 return -1;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800811 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800812
813 case BE_SEQ:
Elliott Hughes820eced2021-08-20 18:00:50 -0700814 ND_PRINT("Seq(%u)", elem->asnlen);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800815 break;
816
817 case BE_INETADDR:
818 if (asnlen != ASNLEN_INETADDR)
Elliott Hughes820eced2021-08-20 18:00:50 -0700819 ND_PRINT("[inetaddr len!=%d]", ASNLEN_INETADDR);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700820 p = (const u_char *)elem->data.raw;
Elliott Hughes820eced2021-08-20 18:00:50 -0700821 ND_TCHECK_LEN(p, asnlen);
822 for (i = asnlen; i != 0; p++, i--) {
823 ND_PRINT((i == asnlen) ? "%u" : ".%u", GET_U_1(p));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800824 }
825 break;
826
827 case BE_NOSUCHOBJECT:
828 case BE_NOSUCHINST:
829 case BE_ENDOFMIBVIEW:
Elliott Hughes820eced2021-08-20 18:00:50 -0700830 ND_PRINT("[%s]", Class[EXCEPTIONS].Id[elem->id]);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800831 break;
832
833 case BE_PDU:
Elliott Hughes820eced2021-08-20 18:00:50 -0700834 ND_PRINT("%s(%u)", Class[CONTEXT].Id[elem->id], elem->asnlen);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800835 break;
836
837 case BE_ANY:
Elliott Hughes820eced2021-08-20 18:00:50 -0700838 ND_PRINT("[BE_ANY!?]");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800839 break;
840
841 default:
Elliott Hughes820eced2021-08-20 18:00:50 -0700842 ND_PRINT("[be!?]");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800843 break;
844 }
845 return 0;
846
847trunc:
Elliott Hughes820eced2021-08-20 18:00:50 -0700848 nd_print_trunc(ndo);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800849 return -1;
850}
851
852#ifdef notdef
853/*
854 * This is a brute force ASN.1 printer: recurses to dump an entire structure.
855 * This will work for any ASN.1 stream, not just an SNMP PDU.
856 *
857 * By adding newlines and spaces at the correct places, this would print in
858 * Rose-Normal-Form.
859 *
860 * This is not currently used.
861 */
862static void
863asn1_decode(u_char *p, u_int length)
864{
865 struct be elem;
866 int i = 0;
867
868 while (i >= 0 && length > 0) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700869 i = asn1_parse(ndo, p, length, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800870 if (i >= 0) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700871 ND_PRINT(" ");
Elliott Hughes892a68b2015-10-19 14:43:53 -0700872 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800873 return;
874 if (elem.type == BE_SEQ || elem.type == BE_PDU) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700875 ND_PRINT(" {");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800876 asn1_decode(elem.data.raw, elem.asnlen);
Elliott Hughes820eced2021-08-20 18:00:50 -0700877 ND_PRINT(" }");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800878 }
879 length -= i;
880 p += i;
881 }
882 }
883}
884#endif
885
Elliott Hughes892a68b2015-10-19 14:43:53 -0700886#ifdef USE_LIBSMI
The Android Open Source Project2949f582009-03-03 19:30:46 -0800887
888struct smi2be {
889 SmiBasetype basetype;
890 int be;
891};
892
Elliott Hughes892a68b2015-10-19 14:43:53 -0700893static const struct smi2be smi2betab[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800894 { SMI_BASETYPE_INTEGER32, BE_INT },
895 { SMI_BASETYPE_OCTETSTRING, BE_STR },
896 { SMI_BASETYPE_OCTETSTRING, BE_INETADDR },
897 { SMI_BASETYPE_OBJECTIDENTIFIER, BE_OID },
898 { SMI_BASETYPE_UNSIGNED32, BE_UNS },
899 { SMI_BASETYPE_INTEGER64, BE_NONE },
900 { SMI_BASETYPE_UNSIGNED64, BE_UNS64 },
901 { SMI_BASETYPE_FLOAT32, BE_NONE },
902 { SMI_BASETYPE_FLOAT64, BE_NONE },
903 { SMI_BASETYPE_FLOAT128, BE_NONE },
904 { SMI_BASETYPE_ENUM, BE_INT },
905 { SMI_BASETYPE_BITS, BE_STR },
906 { SMI_BASETYPE_UNKNOWN, BE_NONE }
907};
908
909static int
Elliott Hughes892a68b2015-10-19 14:43:53 -0700910smi_decode_oid(netdissect_options *ndo,
911 struct be *elem, unsigned int *oid,
912 unsigned int oidsize, unsigned int *oidlen)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800913{
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700914 const u_char *p = (const u_char *)elem->data.raw;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700915 uint32_t asnlen = elem->asnlen;
Elliott Hughes820eced2021-08-20 18:00:50 -0700916 uint32_t i = asnlen;
917 int o = 0, first = -1;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700918 unsigned int firstval;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800919
Elliott Hughes820eced2021-08-20 18:00:50 -0700920 for (*oidlen = 0; i != 0; p++, i--) {
921 o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8);
922 if (GET_U_1(p) & ASN_LONGLEN)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800923 continue;
924
925 /*
926 * first subitem encodes two items with 1st*OIDMUX+2nd
927 * (see X.690:1997 clause 8.19 for the details)
928 */
929 if (first < 0) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700930 first = 0;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700931 firstval = o / OIDMUX;
932 if (firstval > 2) firstval = 2;
933 o -= firstval * OIDMUX;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800934 if (*oidlen < oidsize) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700935 oid[(*oidlen)++] = firstval;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800936 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800937 }
938 if (*oidlen < oidsize) {
939 oid[(*oidlen)++] = o;
940 }
941 o = 0;
942 }
943 return 0;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800944}
945
946static int smi_check_type(SmiBasetype basetype, int be)
947{
948 int i;
949
950 for (i = 0; smi2betab[i].basetype != SMI_BASETYPE_UNKNOWN; i++) {
951 if (smi2betab[i].basetype == basetype && smi2betab[i].be == be) {
952 return 1;
953 }
954 }
955
956 return 0;
957}
958
959static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange,
960 struct be *elem)
961{
962 int ok = 1;
963
964 switch (smiType->basetype) {
965 case SMI_BASETYPE_OBJECTIDENTIFIER:
966 case SMI_BASETYPE_OCTETSTRING:
967 if (smiRange->minValue.value.unsigned32
968 == smiRange->maxValue.value.unsigned32) {
969 ok = (elem->asnlen == smiRange->minValue.value.unsigned32);
970 } else {
971 ok = (elem->asnlen >= smiRange->minValue.value.unsigned32
972 && elem->asnlen <= smiRange->maxValue.value.unsigned32);
973 }
974 break;
975
976 case SMI_BASETYPE_INTEGER32:
977 ok = (elem->data.integer >= smiRange->minValue.value.integer32
978 && elem->data.integer <= smiRange->maxValue.value.integer32);
979 break;
980
981 case SMI_BASETYPE_UNSIGNED32:
982 ok = (elem->data.uns >= smiRange->minValue.value.unsigned32
983 && elem->data.uns <= smiRange->maxValue.value.unsigned32);
984 break;
985
986 case SMI_BASETYPE_UNSIGNED64:
987 /* XXX */
988 break;
989
990 /* case SMI_BASETYPE_INTEGER64: SMIng */
991 /* case SMI_BASETYPE_FLOAT32: SMIng */
992 /* case SMI_BASETYPE_FLOAT64: SMIng */
993 /* case SMI_BASETYPE_FLOAT128: SMIng */
994
995 case SMI_BASETYPE_ENUM:
996 case SMI_BASETYPE_BITS:
997 case SMI_BASETYPE_UNKNOWN:
998 ok = 1;
999 break;
1000
1001 default:
1002 ok = 0;
1003 break;
1004 }
1005
1006 return ok;
1007}
1008
1009static int smi_check_range(SmiType *smiType, struct be *elem)
1010{
1011 SmiRange *smiRange;
1012 int ok = 1;
1013
1014 for (smiRange = smiGetFirstRange(smiType);
1015 smiRange;
1016 smiRange = smiGetNextRange(smiRange)) {
1017
1018 ok = smi_check_a_range(smiType, smiRange, elem);
1019
1020 if (ok) {
1021 break;
1022 }
1023 }
1024
1025 if (ok) {
1026 SmiType *parentType;
1027 parentType = smiGetParentType(smiType);
1028 if (parentType) {
1029 ok = smi_check_range(parentType, elem);
1030 }
1031 }
1032
1033 return ok;
1034}
1035
Elliott Hughes892a68b2015-10-19 14:43:53 -07001036static SmiNode *
1037smi_print_variable(netdissect_options *ndo,
1038 struct be *elem, int *status)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001039{
1040 unsigned int oid[128], oidlen;
1041 SmiNode *smiNode = NULL;
1042 unsigned int i;
1043
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001044 if (!nd_smi_module_loaded) {
1045 *status = asn1_print(ndo, elem);
1046 return NULL;
1047 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001048 *status = smi_decode_oid(ndo, elem, oid, sizeof(oid) / sizeof(unsigned int),
The Android Open Source Project2949f582009-03-03 19:30:46 -08001049 &oidlen);
1050 if (*status < 0)
1051 return NULL;
1052 smiNode = smiGetNodeByOID(oidlen, oid);
1053 if (! smiNode) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001054 *status = asn1_print(ndo, elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001055 return NULL;
1056 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001057 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001058 ND_PRINT("%s::", smiGetNodeModule(smiNode)->name);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001059 }
Elliott Hughes820eced2021-08-20 18:00:50 -07001060 ND_PRINT("%s", smiNode->name);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001061 if (smiNode->oidlen < oidlen) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001062 for (i = smiNode->oidlen; i < oidlen; i++) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001063 ND_PRINT(".%u", oid[i]);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001064 }
1065 }
1066 *status = 0;
1067 return smiNode;
1068}
1069
1070static int
Elliott Hughes892a68b2015-10-19 14:43:53 -07001071smi_print_value(netdissect_options *ndo,
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001072 SmiNode *smiNode, u_short pduid, struct be *elem)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001073{
1074 unsigned int i, oid[128], oidlen;
1075 SmiType *smiType;
1076 SmiNamedNumber *nn;
1077 int done = 0;
1078
1079 if (! smiNode || ! (smiNode->nodekind
1080 & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001081 return asn1_print(ndo, elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001082 }
1083
1084 if (elem->type == BE_NOSUCHOBJECT
1085 || elem->type == BE_NOSUCHINST
1086 || elem->type == BE_ENDOFMIBVIEW) {
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 (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001091 ND_PRINT("[notNotifyable]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001092 }
1093
1094 if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001095 ND_PRINT("[notReadable]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001096 }
1097
1098 if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001099 ND_PRINT("[notWritable]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001100 }
1101
1102 if (RESPONSE_CLASS(pduid)
1103 && smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001104 ND_PRINT("[noAccess]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001105 }
1106
1107 smiType = smiGetNodeType(smiNode);
1108 if (! smiType) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001109 return asn1_print(ndo, elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001110 }
1111
1112 if (! smi_check_type(smiType->basetype, elem->type)) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001113 ND_PRINT("[wrongType]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001114 }
1115
1116 if (! smi_check_range(smiType, elem)) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001117 ND_PRINT("[outOfRange]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001118 }
1119
1120 /* resolve bits to named bits */
1121
1122 /* check whether instance identifier is valid */
1123
1124 /* apply display hints (integer, octetstring) */
1125
1126 /* convert instance identifier to index type values */
1127
1128 switch (elem->type) {
1129 case BE_OID:
1130 if (smiType->basetype == SMI_BASETYPE_BITS) {
1131 /* print bit labels */
1132 } else {
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001133 if (nd_smi_module_loaded &&
1134 smi_decode_oid(ndo, elem, oid,
1135 sizeof(oid)/sizeof(unsigned int),
1136 &oidlen) == 0) {
1137 smiNode = smiGetNodeByOID(oidlen, oid);
1138 if (smiNode) {
1139 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001140 ND_PRINT("%s::", smiGetNodeModule(smiNode)->name);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001141 }
Elliott Hughes820eced2021-08-20 18:00:50 -07001142 ND_PRINT("%s", smiNode->name);
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001143 if (smiNode->oidlen < oidlen) {
1144 for (i = smiNode->oidlen;
1145 i < oidlen; i++) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001146 ND_PRINT(".%u", oid[i]);
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001147 }
1148 }
1149 done++;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001150 }
The Android Open Source Project2949f582009-03-03 19:30:46 -08001151 }
1152 }
1153 break;
1154
1155 case BE_INT:
1156 if (smiType->basetype == SMI_BASETYPE_ENUM) {
1157 for (nn = smiGetFirstNamedNumber(smiType);
1158 nn;
1159 nn = smiGetNextNamedNumber(nn)) {
1160 if (nn->value.value.integer32
1161 == elem->data.integer) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001162 ND_PRINT("%s", nn->name);
1163 ND_PRINT("(%d)", elem->data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001164 done++;
1165 break;
1166 }
1167 }
1168 }
1169 break;
1170 }
1171
1172 if (! done) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001173 return asn1_print(ndo, elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001174 }
1175 return 0;
1176}
1177#endif
1178
1179/*
1180 * General SNMP header
1181 * SEQUENCE {
1182 * version INTEGER {version-1(0)},
1183 * community OCTET STRING,
1184 * data ANY -- PDUs
1185 * }
1186 * PDUs for all but Trap: (see rfc1157 from page 15 on)
1187 * SEQUENCE {
1188 * request-id INTEGER,
1189 * error-status INTEGER,
1190 * error-index INTEGER,
1191 * varbindlist SEQUENCE OF
1192 * SEQUENCE {
1193 * name ObjectName,
1194 * value ObjectValue
1195 * }
1196 * }
1197 * PDU for Trap:
1198 * SEQUENCE {
1199 * enterprise OBJECT IDENTIFIER,
1200 * agent-addr NetworkAddress,
1201 * generic-trap INTEGER,
1202 * specific-trap INTEGER,
1203 * time-stamp TimeTicks,
1204 * varbindlist SEQUENCE OF
1205 * SEQUENCE {
1206 * name ObjectName,
1207 * value ObjectValue
1208 * }
1209 * }
1210 */
1211
1212/*
1213 * Decode SNMP varBind
1214 */
1215static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001216varbind_print(netdissect_options *ndo,
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001217 u_short pduid, const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001218{
1219 struct be elem;
1220 int count = 0, ind;
Elliott Hughes892a68b2015-10-19 14:43:53 -07001221#ifdef USE_LIBSMI
The Android Open Source Project2949f582009-03-03 19:30:46 -08001222 SmiNode *smiNode = NULL;
1223#endif
1224 int status;
1225
1226 /* Sequence of varBind */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001227 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001228 return;
1229 if (elem.type != BE_SEQ) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001230 ND_PRINT("[!SEQ of varbind]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001231 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001232 return;
1233 }
1234 if ((u_int)count < length)
Elliott Hughes820eced2021-08-20 18:00:50 -07001235 ND_PRINT("[%d extra after SEQ of varbind]", length - count);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001236 /* descend */
1237 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001238 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001239
1240 for (ind = 1; length > 0; ind++) {
1241 const u_char *vbend;
1242 u_int vblength;
1243
Elliott Hughes820eced2021-08-20 18:00:50 -07001244 ND_PRINT(" ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001245
1246 /* Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001247 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001248 return;
1249 if (elem.type != BE_SEQ) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001250 ND_PRINT("[!varbind]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001251 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001252 return;
1253 }
1254 vbend = np + count;
1255 vblength = length - count;
1256 /* descend */
1257 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001258 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001259
1260 /* objName (OID) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001261 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001262 return;
1263 if (elem.type != BE_OID) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001264 ND_PRINT("[objName!=OID]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001265 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001266 return;
1267 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001268#ifdef USE_LIBSMI
1269 smiNode = smi_print_variable(ndo, &elem, &status);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001270#else
Elliott Hughes892a68b2015-10-19 14:43:53 -07001271 status = asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001272#endif
1273 if (status < 0)
1274 return;
1275 length -= count;
1276 np += count;
1277
1278 if (pduid != GETREQ && pduid != GETNEXTREQ
1279 && pduid != GETBULKREQ)
Elliott Hughes820eced2021-08-20 18:00:50 -07001280 ND_PRINT("=");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001281
1282 /* objVal (ANY) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001283 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001284 return;
1285 if (pduid == GETREQ || pduid == GETNEXTREQ
1286 || pduid == GETBULKREQ) {
1287 if (elem.type != BE_NULL) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001288 ND_PRINT("[objVal!=NULL]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001289 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001290 return;
1291 }
1292 } else {
1293 if (elem.type != BE_NULL) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001294#ifdef USE_LIBSMI
1295 status = smi_print_value(ndo, smiNode, pduid, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001296#else
Elliott Hughes892a68b2015-10-19 14:43:53 -07001297 status = asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001298#endif
1299 }
1300 if (status < 0)
1301 return;
1302 }
1303 length = vblength;
1304 np = vbend;
1305 }
1306}
1307
1308/*
1309 * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest,
1310 * GetBulk, Inform, V2Trap, and Report
1311 */
1312static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001313snmppdu_print(netdissect_options *ndo,
1314 u_short pduid, const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001315{
1316 struct be elem;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001317 int count = 0, error_status;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001318
1319 /* reqId (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001320 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001321 return;
1322 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001323 ND_PRINT("[reqId!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001324 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001325 return;
1326 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001327 if (ndo->ndo_vflag)
Elliott Hughes820eced2021-08-20 18:00:50 -07001328 ND_PRINT("R=%d ", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001329 length -= count;
1330 np += count;
1331
1332 /* errorStatus (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001333 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001334 return;
1335 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001336 ND_PRINT("[errorStatus!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001337 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001338 return;
1339 }
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001340 error_status = 0;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001341 if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
1342 || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
1343 && elem.data.integer != 0) {
1344 char errbuf[20];
Elliott Hughes820eced2021-08-20 18:00:50 -07001345 ND_PRINT("[errorStatus(%s)!=0]",
1346 DECODE_ErrorStatus(elem.data.integer));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001347 } else if (pduid == GETBULKREQ) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001348 ND_PRINT(" N=%d", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001349 } else if (elem.data.integer != 0) {
1350 char errbuf[20];
Elliott Hughes820eced2021-08-20 18:00:50 -07001351 ND_PRINT(" %s", DECODE_ErrorStatus(elem.data.integer));
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001352 error_status = elem.data.integer;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001353 }
1354 length -= count;
1355 np += count;
1356
1357 /* errorIndex (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001358 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001359 return;
1360 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001361 ND_PRINT("[errorIndex!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001362 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001363 return;
1364 }
1365 if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
1366 || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
1367 && elem.data.integer != 0)
Elliott Hughes820eced2021-08-20 18:00:50 -07001368 ND_PRINT("[errorIndex(%d)!=0]", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001369 else if (pduid == GETBULKREQ)
Elliott Hughes820eced2021-08-20 18:00:50 -07001370 ND_PRINT(" M=%d", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001371 else if (elem.data.integer != 0) {
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001372 if (!error_status)
Elliott Hughes820eced2021-08-20 18:00:50 -07001373 ND_PRINT("[errorIndex(%d) w/o errorStatus]", elem.data.integer);
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001374 else
Elliott Hughes820eced2021-08-20 18:00:50 -07001375 ND_PRINT("@%d", elem.data.integer);
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001376 } else if (error_status) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001377 ND_PRINT("[errorIndex==0]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001378 }
1379 length -= count;
1380 np += count;
1381
Elliott Hughes892a68b2015-10-19 14:43:53 -07001382 varbind_print(ndo, pduid, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001383}
1384
1385/*
1386 * Decode SNMP Trap PDU
1387 */
1388static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001389trappdu_print(netdissect_options *ndo,
1390 const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001391{
1392 struct be elem;
1393 int count = 0, generic;
1394
Elliott Hughes820eced2021-08-20 18:00:50 -07001395 ND_PRINT(" ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001396
1397 /* enterprise (oid) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001398 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001399 return;
1400 if (elem.type != BE_OID) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001401 ND_PRINT("[enterprise!=OID]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001402 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001403 return;
1404 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001405 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001406 return;
1407 length -= count;
1408 np += count;
1409
Elliott Hughes820eced2021-08-20 18:00:50 -07001410 ND_PRINT(" ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001411
1412 /* agent-addr (inetaddr) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001413 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001414 return;
1415 if (elem.type != BE_INETADDR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001416 ND_PRINT("[agent-addr!=INETADDR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001417 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001418 return;
1419 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001420 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001421 return;
1422 length -= count;
1423 np += count;
1424
1425 /* generic-trap (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001426 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001427 return;
1428 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001429 ND_PRINT("[generic-trap!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001430 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001431 return;
1432 }
1433 generic = elem.data.integer;
1434 {
1435 char buf[20];
Elliott Hughes820eced2021-08-20 18:00:50 -07001436 ND_PRINT(" %s", DECODE_GenericTrap(generic));
The Android Open Source Project2949f582009-03-03 19:30:46 -08001437 }
1438 length -= count;
1439 np += count;
1440
1441 /* specific-trap (Integer) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001442 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001443 return;
1444 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001445 ND_PRINT("[specific-trap!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001446 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001447 return;
1448 }
1449 if (generic != GT_ENTERPRISE) {
1450 if (elem.data.integer != 0)
Elliott Hughes820eced2021-08-20 18:00:50 -07001451 ND_PRINT("[specific-trap(%d)!=0]", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001452 } else
Elliott Hughes820eced2021-08-20 18:00:50 -07001453 ND_PRINT(" s=%d", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001454 length -= count;
1455 np += count;
1456
Elliott Hughes820eced2021-08-20 18:00:50 -07001457 ND_PRINT(" ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001458
1459 /* time-stamp (TimeTicks) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001460 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001461 return;
1462 if (elem.type != BE_UNS) { /* XXX */
Elliott Hughes820eced2021-08-20 18:00:50 -07001463 ND_PRINT("[time-stamp!=TIMETICKS]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001464 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001465 return;
1466 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001467 if (asn1_print(ndo, &elem) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001468 return;
1469 length -= count;
1470 np += count;
1471
Elliott Hughes892a68b2015-10-19 14:43:53 -07001472 varbind_print(ndo, TRAP, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001473}
1474
1475/*
1476 * Decode arbitrary SNMP PDUs.
1477 */
1478static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001479pdu_print(netdissect_options *ndo,
1480 const u_char *np, u_int length, int version)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001481{
1482 struct be pdu;
1483 int count = 0;
1484
1485 /* PDU (Context) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001486 if ((count = asn1_parse(ndo, np, length, &pdu)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001487 return;
1488 if (pdu.type != BE_PDU) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001489 ND_PRINT("[no PDU]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001490 return;
1491 }
1492 if ((u_int)count < length)
Elliott Hughes820eced2021-08-20 18:00:50 -07001493 ND_PRINT("[%d extra after PDU]", length - count);
Elliott Hughes892a68b2015-10-19 14:43:53 -07001494 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001495 ND_PRINT("{ ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001496 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001497 if (asn1_print(ndo, &pdu) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001498 return;
Elliott Hughes820eced2021-08-20 18:00:50 -07001499 ND_PRINT(" ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001500 /* descend into PDU */
1501 length = pdu.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001502 np = (const u_char *)pdu.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001503
1504 if (version == SNMP_VERSION_1 &&
1505 (pdu.id == GETBULKREQ || pdu.id == INFORMREQ ||
1506 pdu.id == V2TRAP || pdu.id == REPORT)) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001507 ND_PRINT("[v2 PDU in v1 message]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001508 return;
1509 }
1510
1511 if (version == SNMP_VERSION_2 && pdu.id == TRAP) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001512 ND_PRINT("[v1 PDU in v2 message]");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001513 return;
1514 }
1515
1516 switch (pdu.id) {
1517 case TRAP:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001518 trappdu_print(ndo, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001519 break;
1520 case GETREQ:
1521 case GETNEXTREQ:
1522 case GETRESP:
1523 case SETREQ:
1524 case GETBULKREQ:
1525 case INFORMREQ:
1526 case V2TRAP:
1527 case REPORT:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001528 snmppdu_print(ndo, pdu.id, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001529 break;
1530 }
1531
Elliott Hughes892a68b2015-10-19 14:43:53 -07001532 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001533 ND_PRINT(" } ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001534 }
1535}
1536
1537/*
1538 * Decode a scoped SNMP PDU.
1539 */
1540static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001541scopedpdu_print(netdissect_options *ndo,
1542 const u_char *np, u_int length, int version)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001543{
1544 struct be elem;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001545 int count = 0;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001546
1547 /* Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001548 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001549 return;
1550 if (elem.type != BE_SEQ) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001551 ND_PRINT("[!scoped PDU]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001552 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001553 return;
1554 }
1555 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001556 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001557
1558 /* contextEngineID (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001559 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001560 return;
1561 if (elem.type != BE_STR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001562 ND_PRINT("[contextEngineID!=STR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001563 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001564 return;
1565 }
1566 length -= count;
1567 np += count;
1568
Elliott Hughes820eced2021-08-20 18:00:50 -07001569 ND_PRINT("E=");
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001570 if (asn1_print_octets(ndo, &elem) == -1)
1571 return;
Elliott Hughes820eced2021-08-20 18:00:50 -07001572 ND_PRINT(" ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001573
1574 /* contextName (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001575 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001576 return;
1577 if (elem.type != BE_STR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001578 ND_PRINT("[contextName!=STR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001579 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001580 return;
1581 }
1582 length -= count;
1583 np += count;
1584
Elliott Hughes820eced2021-08-20 18:00:50 -07001585 ND_PRINT("C=");
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001586 if (asn1_print_string(ndo, &elem) == -1)
1587 return;
Elliott Hughes820eced2021-08-20 18:00:50 -07001588 ND_PRINT(" ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001589
Elliott Hughes892a68b2015-10-19 14:43:53 -07001590 pdu_print(ndo, np, length, version);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001591}
1592
1593/*
1594 * Decode SNMP Community Header (SNMPv1 and SNMPv2c)
1595 */
1596static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001597community_print(netdissect_options *ndo,
1598 const u_char *np, u_int length, int version)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001599{
1600 struct be elem;
1601 int count = 0;
1602
1603 /* Community (String) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001604 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001605 return;
1606 if (elem.type != BE_STR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001607 ND_PRINT("[comm!=STR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001608 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001609 return;
1610 }
1611 /* default community */
1612 if (!(elem.asnlen == sizeof(DEF_COMMUNITY) - 1 &&
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001613 strncmp((const char *)elem.data.str, DEF_COMMUNITY,
1614 sizeof(DEF_COMMUNITY) - 1) == 0)) {
The Android Open Source Project2949f582009-03-03 19:30:46 -08001615 /* ! "public" */
Elliott Hughes820eced2021-08-20 18:00:50 -07001616 ND_PRINT("C=");
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001617 if (asn1_print_string(ndo, &elem) == -1)
1618 return;
Elliott Hughes820eced2021-08-20 18:00:50 -07001619 ND_PRINT(" ");
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001620 }
The Android Open Source Project2949f582009-03-03 19:30:46 -08001621 length -= count;
1622 np += count;
1623
Elliott Hughes892a68b2015-10-19 14:43:53 -07001624 pdu_print(ndo, np, length, version);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001625}
1626
1627/*
1628 * Decode SNMPv3 User-based Security Message Header (SNMPv3)
1629 */
1630static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001631usm_print(netdissect_options *ndo,
1632 const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001633{
1634 struct be elem;
1635 int count = 0;
1636
1637 /* Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001638 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001639 return;
1640 if (elem.type != BE_SEQ) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001641 ND_PRINT("[!usm]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001642 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001643 return;
1644 }
1645 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001646 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001647
1648 /* msgAuthoritativeEngineID (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001649 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001650 return;
1651 if (elem.type != BE_STR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001652 ND_PRINT("[msgAuthoritativeEngineID!=STR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001653 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001654 return;
1655 }
1656 length -= count;
1657 np += count;
1658
1659 /* msgAuthoritativeEngineBoots (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001660 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001661 return;
1662 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001663 ND_PRINT("[msgAuthoritativeEngineBoots!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001664 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001665 return;
1666 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001667 if (ndo->ndo_vflag)
Elliott Hughes820eced2021-08-20 18:00:50 -07001668 ND_PRINT("B=%d ", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001669 length -= count;
1670 np += count;
1671
1672 /* msgAuthoritativeEngineTime (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001673 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001674 return;
1675 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001676 ND_PRINT("[msgAuthoritativeEngineTime!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001677 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001678 return;
1679 }
Elliott Hughes892a68b2015-10-19 14:43:53 -07001680 if (ndo->ndo_vflag)
Elliott Hughes820eced2021-08-20 18:00:50 -07001681 ND_PRINT("T=%d ", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001682 length -= count;
1683 np += count;
1684
1685 /* msgUserName (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001686 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001687 return;
1688 if (elem.type != BE_STR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001689 ND_PRINT("[msgUserName!=STR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001690 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001691 return;
1692 }
1693 length -= count;
1694 np += count;
1695
Elliott Hughes820eced2021-08-20 18:00:50 -07001696 ND_PRINT("U=");
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001697 if (asn1_print_string(ndo, &elem) == -1)
1698 return;
Elliott Hughes820eced2021-08-20 18:00:50 -07001699 ND_PRINT(" ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001700
1701 /* msgAuthenticationParameters (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001702 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001703 return;
1704 if (elem.type != BE_STR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001705 ND_PRINT("[msgAuthenticationParameters!=STR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001706 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001707 return;
1708 }
1709 length -= count;
1710 np += count;
1711
1712 /* msgPrivacyParameters (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001713 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001714 return;
1715 if (elem.type != BE_STR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001716 ND_PRINT("[msgPrivacyParameters!=STR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001717 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001718 return;
1719 }
1720 length -= count;
1721 np += count;
1722
1723 if ((u_int)count < length)
Elliott Hughes820eced2021-08-20 18:00:50 -07001724 ND_PRINT("[%d extra after usm SEQ]", length - count);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001725}
1726
1727/*
1728 * Decode SNMPv3 Message Header (SNMPv3)
1729 */
1730static void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001731v3msg_print(netdissect_options *ndo,
1732 const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001733{
1734 struct be elem;
1735 int count = 0;
1736 u_char flags;
1737 int model;
1738 const u_char *xnp = np;
1739 int xlength = length;
1740
1741 /* Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001742 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001743 return;
1744 if (elem.type != BE_SEQ) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001745 ND_PRINT("[!message]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001746 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001747 return;
1748 }
1749 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001750 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001751
Elliott Hughes892a68b2015-10-19 14:43:53 -07001752 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001753 ND_PRINT("{ ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001754 }
1755
1756 /* msgID (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001757 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001758 return;
1759 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001760 ND_PRINT("[msgID!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001761 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001762 return;
1763 }
1764 length -= count;
1765 np += count;
1766
1767 /* msgMaxSize (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001768 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001769 return;
1770 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001771 ND_PRINT("[msgMaxSize!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001772 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001773 return;
1774 }
1775 length -= count;
1776 np += count;
1777
1778 /* msgFlags (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001779 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001780 return;
1781 if (elem.type != BE_STR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001782 ND_PRINT("[msgFlags!=STR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001783 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001784 return;
1785 }
1786 if (elem.asnlen != 1) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001787 ND_PRINT("[msgFlags size %d]", elem.asnlen);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001788 return;
1789 }
Elliott Hughes820eced2021-08-20 18:00:50 -07001790 flags = GET_U_1(elem.data.str);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001791 if (flags != 0x00 && flags != 0x01 && flags != 0x03
1792 && flags != 0x04 && flags != 0x05 && flags != 0x07) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001793 ND_PRINT("[msgFlags=0x%02X]", flags);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001794 return;
1795 }
1796 length -= count;
1797 np += count;
1798
Elliott Hughes820eced2021-08-20 18:00:50 -07001799 ND_PRINT("F=%s%s%s ",
Elliott Hughes892a68b2015-10-19 14:43:53 -07001800 flags & 0x01 ? "a" : "",
1801 flags & 0x02 ? "p" : "",
Elliott Hughes820eced2021-08-20 18:00:50 -07001802 flags & 0x04 ? "r" : "");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001803
1804 /* msgSecurityModel (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001805 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001806 return;
1807 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001808 ND_PRINT("[msgSecurityModel!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001809 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001810 return;
1811 }
1812 model = elem.data.integer;
1813 length -= count;
1814 np += count;
1815
1816 if ((u_int)count < length)
Elliott Hughes820eced2021-08-20 18:00:50 -07001817 ND_PRINT("[%d extra after message SEQ]", length - count);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001818
Elliott Hughes892a68b2015-10-19 14:43:53 -07001819 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001820 ND_PRINT("} ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001821 }
1822
1823 if (model == 3) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001824 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001825 ND_PRINT("{ USM ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001826 }
1827 } else {
Elliott Hughes820eced2021-08-20 18:00:50 -07001828 ND_PRINT("[security model %d]", model);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001829 return;
1830 }
1831
1832 np = xnp + (np - xnp);
1833 length = xlength - (np - xnp);
1834
1835 /* msgSecurityParameters (OCTET STRING) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001836 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001837 return;
1838 if (elem.type != BE_STR) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001839 ND_PRINT("[msgSecurityParameters!=STR]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001840 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001841 return;
1842 }
1843 length -= count;
1844 np += count;
1845
1846 if (model == 3) {
Elliott Hughes892a68b2015-10-19 14:43:53 -07001847 usm_print(ndo, elem.data.str, elem.asnlen);
1848 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001849 ND_PRINT("} ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001850 }
1851 }
1852
Elliott Hughes892a68b2015-10-19 14:43:53 -07001853 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001854 ND_PRINT("{ ScopedPDU ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001855 }
1856
Elliott Hughes892a68b2015-10-19 14:43:53 -07001857 scopedpdu_print(ndo, np, length, 3);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001858
Elliott Hughes892a68b2015-10-19 14:43:53 -07001859 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001860 ND_PRINT("} ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001861 }
1862}
1863
1864/*
1865 * Decode SNMP header and pass on to PDU printing routines
1866 */
1867void
Elliott Hughes892a68b2015-10-19 14:43:53 -07001868snmp_print(netdissect_options *ndo,
1869 const u_char *np, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001870{
1871 struct be elem;
1872 int count = 0;
1873 int version = 0;
1874
Elliott Hughes820eced2021-08-20 18:00:50 -07001875 ndo->ndo_protocol = "snmp";
1876 ND_PRINT(" ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001877
1878 /* initial Sequence */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001879 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001880 return;
1881 if (elem.type != BE_SEQ) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001882 ND_PRINT("[!init SEQ]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001883 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001884 return;
1885 }
1886 if ((u_int)count < length)
Elliott Hughes820eced2021-08-20 18:00:50 -07001887 ND_PRINT("[%d extra after iSEQ]", length - count);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001888 /* descend */
1889 length = elem.asnlen;
Elliott Hughese2e3bd12017-05-15 10:59:29 -07001890 np = (const u_char *)elem.data.raw;
The Android Open Source Project2949f582009-03-03 19:30:46 -08001891
1892 /* Version (INTEGER) */
Elliott Hughes892a68b2015-10-19 14:43:53 -07001893 if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
The Android Open Source Project2949f582009-03-03 19:30:46 -08001894 return;
1895 if (elem.type != BE_INT) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001896 ND_PRINT("[version!=INT]");
Elliott Hughes892a68b2015-10-19 14:43:53 -07001897 asn1_print(ndo, &elem);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001898 return;
1899 }
1900
1901 switch (elem.data.integer) {
1902 case SNMP_VERSION_1:
1903 case SNMP_VERSION_2:
1904 case SNMP_VERSION_3:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001905 if (ndo->ndo_vflag)
Elliott Hughes820eced2021-08-20 18:00:50 -07001906 ND_PRINT("{ %s ", SnmpVersion[elem.data.integer]);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001907 break;
1908 default:
Elliott Hughes820eced2021-08-20 18:00:50 -07001909 ND_PRINT("SNMP [version = %d]", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001910 return;
1911 }
1912 version = elem.data.integer;
1913 length -= count;
1914 np += count;
1915
1916 switch (version) {
1917 case SNMP_VERSION_1:
1918 case SNMP_VERSION_2:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001919 community_print(ndo, np, length, version);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001920 break;
1921 case SNMP_VERSION_3:
Elliott Hughes892a68b2015-10-19 14:43:53 -07001922 v3msg_print(ndo, np, length);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001923 break;
1924 default:
Elliott Hughes820eced2021-08-20 18:00:50 -07001925 ND_PRINT("[version = %d]", elem.data.integer);
The Android Open Source Project2949f582009-03-03 19:30:46 -08001926 break;
1927 }
1928
Elliott Hughes892a68b2015-10-19 14:43:53 -07001929 if (ndo->ndo_vflag) {
Elliott Hughes820eced2021-08-20 18:00:50 -07001930 ND_PRINT("} ");
The Android Open Source Project2949f582009-03-03 19:30:46 -08001931 }
1932}