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