10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 30f74e101Schristos * John Robert LoVerso. All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that the following conditions 70f74e101Schristos * are met: 80f74e101Schristos * 90f74e101Schristos * 1. Redistributions of source code must retain the above copyright 100f74e101Schristos * notice, this list of conditions and the following disclaimer. 110f74e101Schristos * 120f74e101Schristos * 2. Redistributions in binary form must reproduce the above copyright 130f74e101Schristos * notice, this list of conditions and the following disclaimer in the 140f74e101Schristos * documentation and/or other materials provided with the distribution. 150f74e101Schristos * 160f74e101Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 170f74e101Schristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 180f74e101Schristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 190f74e101Schristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 200f74e101Schristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 210f74e101Schristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 220f74e101Schristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 230f74e101Schristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 240f74e101Schristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 250f74e101Schristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 260f74e101Schristos * 270f74e101Schristos * 280f74e101Schristos * This implementation has been influenced by the CMU SNMP release, 290f74e101Schristos * by Steve Waldbusser. However, this shares no code with that system. 300f74e101Schristos * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_. 310f74e101Schristos * Earlier forms of this implementation were derived and/or inspired by an 320f74e101Schristos * awk script originally written by C. Philip Wood of LANL (but later 330f74e101Schristos * heavily modified by John Robert LoVerso). The copyright notice for 340f74e101Schristos * that work is preserved below, even though it may not rightly apply 350f74e101Schristos * to this file. 360f74e101Schristos * 370f74e101Schristos * Support for SNMPv2c/SNMPv3 and the ability to link the module against 380f74e101Schristos * the libsmi was added by J. Schoenwaelder, Copyright (c) 1999. 390f74e101Schristos * 400f74e101Schristos * This started out as a very simple program, but the incremental decoding 410f74e101Schristos * (into the BE structure) complicated things. 420f74e101Schristos * 430f74e101Schristos # Los Alamos National Laboratory 440f74e101Schristos # 450f74e101Schristos # Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 460f74e101Schristos # This software was produced under a U.S. Government contract 470f74e101Schristos # (W-7405-ENG-36) by Los Alamos National Laboratory, which is 480f74e101Schristos # operated by the University of California for the U.S. Department 490f74e101Schristos # of Energy. The U.S. Government is licensed to use, reproduce, 500f74e101Schristos # and distribute this software. Permission is granted to the 510f74e101Schristos # public to copy and use this software without charge, provided 520f74e101Schristos # that this Notice and any statement of authorship are reproduced 530f74e101Schristos # on all copies. Neither the Government nor the University makes 540f74e101Schristos # any warranty, express or implied, or assumes any liability or 550f74e101Schristos # responsibility for the use of this software. 560f74e101Schristos # @(#)snmp.awk.x 1.1 (LANL) 1/15/90 570f74e101Schristos */ 580f74e101Schristos 5911b3aaa1Schristos #include <sys/cdefs.h> 600f74e101Schristos #ifndef lint 61*26ba0b50Schristos __RCSID("$NetBSD: print-snmp.c,v 1.8 2024/09/02 16:15:33 christos Exp $"); 620f74e101Schristos #endif 630f74e101Schristos 64dc860a36Sspz /* \summary: Simple Network Management Protocol (SNMP) printer */ 65dc860a36Sspz 66c74ad251Schristos #include <config.h> 670f74e101Schristos 68c74ad251Schristos #include "netdissect-stdinc.h" 690f74e101Schristos 700f74e101Schristos #include <stdio.h> 710f74e101Schristos #include <string.h> 72*26ba0b50Schristos #include <limits.h> 730f74e101Schristos 74b3a00663Schristos #ifdef USE_LIBSMI 750f74e101Schristos #include <smi.h> 760f74e101Schristos #endif 770f74e101Schristos 78c74ad251Schristos #include "netdissect-ctype.h" 79c74ad251Schristos 80fdccd7e4Schristos #include "netdissect.h" 81c74ad251Schristos #include "extract.h" 820f74e101Schristos 830f74e101Schristos #undef OPAQUE /* defined in <wingdi.h> */ 840f74e101Schristos 85b3a00663Schristos 860f74e101Schristos /* 870f74e101Schristos * Universal ASN.1 types 880f74e101Schristos * (we only care about the tag values for those allowed in the Internet SMI) 890f74e101Schristos */ 90b3a00663Schristos static const char *Universal[] = { 910f74e101Schristos "U-0", 920f74e101Schristos "Boolean", 930f74e101Schristos "Integer", 940f74e101Schristos #define INTEGER 2 950f74e101Schristos "Bitstring", 960f74e101Schristos "String", 970f74e101Schristos #define STRING 4 980f74e101Schristos "Null", 990f74e101Schristos #define ASN_NULL 5 1000f74e101Schristos "ObjID", 1010f74e101Schristos #define OBJECTID 6 1020f74e101Schristos "ObjectDes", 1030f74e101Schristos "U-8","U-9","U-10","U-11", /* 8-11 */ 1040f74e101Schristos "U-12","U-13","U-14","U-15", /* 12-15 */ 1050f74e101Schristos "Sequence", 1060f74e101Schristos #define SEQUENCE 16 1070f74e101Schristos "Set" 1080f74e101Schristos }; 1090f74e101Schristos 1100f74e101Schristos /* 1110f74e101Schristos * Application-wide ASN.1 types from the Internet SMI and their tags 1120f74e101Schristos */ 113b3a00663Schristos static const char *Application[] = { 1140f74e101Schristos "IpAddress", 1150f74e101Schristos #define IPADDR 0 1160f74e101Schristos "Counter", 1170f74e101Schristos #define COUNTER 1 1180f74e101Schristos "Gauge", 1190f74e101Schristos #define GAUGE 2 1200f74e101Schristos "TimeTicks", 1210f74e101Schristos #define TIMETICKS 3 1220f74e101Schristos "Opaque", 1230f74e101Schristos #define OPAQUE 4 1240f74e101Schristos "C-5", 1250f74e101Schristos "Counter64" 1260f74e101Schristos #define COUNTER64 6 1270f74e101Schristos }; 1280f74e101Schristos 1290f74e101Schristos /* 1300f74e101Schristos * Context-specific ASN.1 types for the SNMP PDUs and their tags 1310f74e101Schristos */ 132b3a00663Schristos static const char *Context[] = { 1330f74e101Schristos "GetRequest", 1340f74e101Schristos #define GETREQ 0 1350f74e101Schristos "GetNextRequest", 1360f74e101Schristos #define GETNEXTREQ 1 1370f74e101Schristos "GetResponse", 1380f74e101Schristos #define GETRESP 2 1390f74e101Schristos "SetRequest", 1400f74e101Schristos #define SETREQ 3 1410f74e101Schristos "Trap", 1420f74e101Schristos #define TRAP 4 1430f74e101Schristos "GetBulk", 1440f74e101Schristos #define GETBULKREQ 5 1450f74e101Schristos "Inform", 1460f74e101Schristos #define INFORMREQ 6 1470f74e101Schristos "V2Trap", 1480f74e101Schristos #define V2TRAP 7 1490f74e101Schristos "Report" 1500f74e101Schristos #define REPORT 8 1510f74e101Schristos }; 1520f74e101Schristos 1530f74e101Schristos #define NOTIFY_CLASS(x) (x == TRAP || x == V2TRAP || x == INFORMREQ) 1540f74e101Schristos #define READ_CLASS(x) (x == GETREQ || x == GETNEXTREQ || x == GETBULKREQ) 1550f74e101Schristos #define WRITE_CLASS(x) (x == SETREQ) 1560f74e101Schristos #define RESPONSE_CLASS(x) (x == GETRESP) 1570f74e101Schristos #define INTERNAL_CLASS(x) (x == REPORT) 1580f74e101Schristos 1590f74e101Schristos /* 1600f74e101Schristos * Context-specific ASN.1 types for the SNMP Exceptions and their tags 1610f74e101Schristos */ 162b3a00663Schristos static const char *Exceptions[] = { 1630f74e101Schristos "noSuchObject", 1640f74e101Schristos #define NOSUCHOBJECT 0 1650f74e101Schristos "noSuchInstance", 1660f74e101Schristos #define NOSUCHINSTANCE 1 1670f74e101Schristos "endOfMibView", 1680f74e101Schristos #define ENDOFMIBVIEW 2 1690f74e101Schristos }; 1700f74e101Schristos 1710f74e101Schristos /* 1720f74e101Schristos * Private ASN.1 types 1730f74e101Schristos * The Internet SMI does not specify any 1740f74e101Schristos */ 175b3a00663Schristos static const char *Private[] = { 1760f74e101Schristos "P-0" 1770f74e101Schristos }; 1780f74e101Schristos 1790f74e101Schristos /* 1800f74e101Schristos * error-status values for any SNMP PDU 1810f74e101Schristos */ 182b3a00663Schristos static const char *ErrorStatus[] = { 1830f74e101Schristos "noError", 1840f74e101Schristos "tooBig", 1850f74e101Schristos "noSuchName", 1860f74e101Schristos "badValue", 1870f74e101Schristos "readOnly", 1880f74e101Schristos "genErr", 1890f74e101Schristos "noAccess", 1900f74e101Schristos "wrongType", 1910f74e101Schristos "wrongLength", 1920f74e101Schristos "wrongEncoding", 1930f74e101Schristos "wrongValue", 1940f74e101Schristos "noCreation", 1950f74e101Schristos "inconsistentValue", 1960f74e101Schristos "resourceUnavailable", 1970f74e101Schristos "commitFailed", 1980f74e101Schristos "undoFailed", 1990f74e101Schristos "authorizationError", 2000f74e101Schristos "notWritable", 2010f74e101Schristos "inconsistentName" 2020f74e101Schristos }; 2030f74e101Schristos #define DECODE_ErrorStatus(e) \ 2040f74e101Schristos ( e >= 0 && (size_t)e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \ 2050f74e101Schristos ? ErrorStatus[e] \ 2060f74e101Schristos : (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf)) 2070f74e101Schristos 2080f74e101Schristos /* 2090f74e101Schristos * generic-trap values in the SNMP Trap-PDU 2100f74e101Schristos */ 211b3a00663Schristos static const char *GenericTrap[] = { 2120f74e101Schristos "coldStart", 2130f74e101Schristos "warmStart", 2140f74e101Schristos "linkDown", 2150f74e101Schristos "linkUp", 2160f74e101Schristos "authenticationFailure", 2170f74e101Schristos "egpNeighborLoss", 2180f74e101Schristos "enterpriseSpecific" 2190f74e101Schristos #define GT_ENTERPRISE 6 2200f74e101Schristos }; 2210f74e101Schristos #define DECODE_GenericTrap(t) \ 2220f74e101Schristos ( t >= 0 && (size_t)t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \ 2230f74e101Schristos ? GenericTrap[t] \ 2240f74e101Schristos : (snprintf(buf, sizeof(buf), "gt=%d", t), buf)) 2250f74e101Schristos 2260f74e101Schristos /* 2270f74e101Schristos * ASN.1 type class table 2280f74e101Schristos * Ties together the preceding Universal, Application, Context, and Private 2290f74e101Schristos * type definitions. 2300f74e101Schristos */ 2310f74e101Schristos #define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */ 232b3a00663Schristos static const struct { 2330f74e101Schristos const char *name; 2340f74e101Schristos const char **Id; 2350f74e101Schristos int numIDs; 2360f74e101Schristos } Class[] = { 2370f74e101Schristos defineCLASS(Universal), 2380f74e101Schristos #define UNIVERSAL 0 2390f74e101Schristos defineCLASS(Application), 2400f74e101Schristos #define APPLICATION 1 2410f74e101Schristos defineCLASS(Context), 2420f74e101Schristos #define CONTEXT 2 2430f74e101Schristos defineCLASS(Private), 2440f74e101Schristos #define PRIVATE 3 2450f74e101Schristos defineCLASS(Exceptions), 2460f74e101Schristos #define EXCEPTIONS 4 2470f74e101Schristos }; 2480f74e101Schristos 2490f74e101Schristos /* 2500f74e101Schristos * defined forms for ASN.1 types 2510f74e101Schristos */ 252b3a00663Schristos static const char *Form[] = { 2530f74e101Schristos "Primitive", 2540f74e101Schristos #define PRIMITIVE 0 2550f74e101Schristos "Constructed", 2560f74e101Schristos #define CONSTRUCTED 1 2570f74e101Schristos }; 2580f74e101Schristos 2590f74e101Schristos /* 2600f74e101Schristos * A structure for the OID tree for the compiled-in MIB. 2610f74e101Schristos * This is stored as a general-order tree. 2620f74e101Schristos */ 263dc860a36Sspz static struct obj { 2640f74e101Schristos const char *desc; /* name of object */ 2650f74e101Schristos u_char oid; /* sub-id following parent */ 2660f74e101Schristos u_char type; /* object type (unused) */ 2670f74e101Schristos struct obj *child, *next; /* child and next sibling pointers */ 2680f74e101Schristos } *objp = NULL; 2690f74e101Schristos 2700f74e101Schristos /* 2710f74e101Schristos * Include the compiled in SNMP MIB. "mib.h" is produced by feeding 2720f74e101Schristos * RFC-1156 format files into "makemib". "mib.h" MUST define at least 2730f74e101Schristos * a value for `mibroot'. 2740f74e101Schristos * 2750f74e101Schristos * In particular, this is gross, as this is including initialized structures, 2760f74e101Schristos * and by right shouldn't be an "include" file. 2770f74e101Schristos */ 2780f74e101Schristos #include "mib.h" 2790f74e101Schristos 2800f74e101Schristos /* 2810f74e101Schristos * This defines a list of OIDs which will be abbreviated on output. 2820f74e101Schristos * Currently, this includes the prefixes for the Internet MIB, the 2830f74e101Schristos * private enterprises tree, and the experimental tree. 2840f74e101Schristos */ 285dc860a36Sspz #define OID_FIRST_OCTET(x, y) (((x)*40) + (y)) /* X.690 8.19.4 */ 286dc860a36Sspz 287dc860a36Sspz #ifndef NO_ABREV_MIB 288dc860a36Sspz static const uint8_t mib_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 2, 1 }; 289dc860a36Sspz #endif 290dc860a36Sspz #ifndef NO_ABREV_ENTER 291dc860a36Sspz static const uint8_t enterprises_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 4, 1 }; 292dc860a36Sspz #endif 293dc860a36Sspz #ifndef NO_ABREV_EXPERI 294dc860a36Sspz static const uint8_t experimental_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 3 }; 295dc860a36Sspz #endif 296dc860a36Sspz #ifndef NO_ABBREV_SNMPMODS 297dc860a36Sspz static const uint8_t snmpModules_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 6, 3 }; 298dc860a36Sspz #endif 299dc860a36Sspz 300dc860a36Sspz #define OBJ_ABBREV_ENTRY(prefix, obj) \ 301dc860a36Sspz { prefix, &_ ## obj ## _obj, obj ## _oid, sizeof (obj ## _oid) } 302b3a00663Schristos static const struct obj_abrev { 3030f74e101Schristos const char *prefix; /* prefix for this abrev */ 3040f74e101Schristos struct obj *node; /* pointer into object table */ 305dc860a36Sspz const uint8_t *oid; /* ASN.1 encoded OID */ 306dc860a36Sspz size_t oid_len; /* length of OID */ 3070f74e101Schristos } obj_abrev_list[] = { 3080f74e101Schristos #ifndef NO_ABREV_MIB 3090f74e101Schristos /* .iso.org.dod.internet.mgmt.mib */ 310dc860a36Sspz OBJ_ABBREV_ENTRY("", mib), 3110f74e101Schristos #endif 3120f74e101Schristos #ifndef NO_ABREV_ENTER 3130f74e101Schristos /* .iso.org.dod.internet.private.enterprises */ 314dc860a36Sspz OBJ_ABBREV_ENTRY("E:", enterprises), 3150f74e101Schristos #endif 3160f74e101Schristos #ifndef NO_ABREV_EXPERI 3170f74e101Schristos /* .iso.org.dod.internet.experimental */ 318dc860a36Sspz OBJ_ABBREV_ENTRY("X:", experimental), 3190f74e101Schristos #endif 3200f74e101Schristos #ifndef NO_ABBREV_SNMPMODS 3210f74e101Schristos /* .iso.org.dod.internet.snmpV2.snmpModules */ 322dc860a36Sspz OBJ_ABBREV_ENTRY("S:", snmpModules), 3230f74e101Schristos #endif 324dc860a36Sspz { 0,0,0,0 } 3250f74e101Schristos }; 3260f74e101Schristos 3270f74e101Schristos /* 3280f74e101Schristos * This is used in the OID print routine to walk down the object tree 3290f74e101Schristos * rooted at `mibroot'. 3300f74e101Schristos */ 3310f74e101Schristos #define OBJ_PRINT(o, suppressdot) \ 3320f74e101Schristos { \ 3330f74e101Schristos if (objp) { \ 3340f74e101Schristos do { \ 3350f74e101Schristos if ((o) == objp->oid) \ 3360f74e101Schristos break; \ 3370f74e101Schristos } while ((objp = objp->next) != NULL); \ 3380f74e101Schristos } \ 3390f74e101Schristos if (objp) { \ 340c74ad251Schristos ND_PRINT(suppressdot?"%s":".%s", objp->desc); \ 3410f74e101Schristos objp = objp->child; \ 3420f74e101Schristos } else \ 343c74ad251Schristos ND_PRINT(suppressdot?"%u":".%u", (o)); \ 3440f74e101Schristos } 3450f74e101Schristos 3460f74e101Schristos /* 3470f74e101Schristos * This is the definition for the Any-Data-Type storage used purely for 3480f74e101Schristos * temporary internal representation while decoding an ASN.1 data stream. 3490f74e101Schristos */ 3500f74e101Schristos struct be { 351b3a00663Schristos uint32_t asnlen; 3520f74e101Schristos union { 353fdccd7e4Schristos const uint8_t *raw; 3540f74e101Schristos int32_t integer; 355b3a00663Schristos uint32_t uns; 3560f74e101Schristos const u_char *str; 357dc860a36Sspz uint64_t uns64; 3580f74e101Schristos } data; 3590f74e101Schristos u_short id; 3600f74e101Schristos u_char form, class; /* tag info */ 3610f74e101Schristos u_char type; 3620f74e101Schristos #define BE_ANY 255 3630f74e101Schristos #define BE_NONE 0 3640f74e101Schristos #define BE_NULL 1 3650f74e101Schristos #define BE_OCTET 2 3660f74e101Schristos #define BE_OID 3 3670f74e101Schristos #define BE_INT 4 3680f74e101Schristos #define BE_UNS 5 3690f74e101Schristos #define BE_STR 6 3700f74e101Schristos #define BE_SEQ 7 3710f74e101Schristos #define BE_INETADDR 8 3720f74e101Schristos #define BE_PDU 9 3730f74e101Schristos #define BE_UNS64 10 3740f74e101Schristos #define BE_NOSUCHOBJECT 128 3750f74e101Schristos #define BE_NOSUCHINST 129 3760f74e101Schristos #define BE_ENDOFMIBVIEW 130 3770f74e101Schristos }; 3780f74e101Schristos 3790f74e101Schristos /* 3800f74e101Schristos * SNMP versions recognized by this module 3810f74e101Schristos */ 382b3a00663Schristos static const char *SnmpVersion[] = { 3830f74e101Schristos "SNMPv1", 3840f74e101Schristos #define SNMP_VERSION_1 0 3850f74e101Schristos "SNMPv2c", 3860f74e101Schristos #define SNMP_VERSION_2 1 3870f74e101Schristos "SNMPv2u", 3880f74e101Schristos #define SNMP_VERSION_2U 2 3890f74e101Schristos "SNMPv3" 3900f74e101Schristos #define SNMP_VERSION_3 3 3910f74e101Schristos }; 3920f74e101Schristos 3930f74e101Schristos /* 3940f74e101Schristos * Defaults for SNMP PDU components 3950f74e101Schristos */ 3960f74e101Schristos #define DEF_COMMUNITY "public" 3970f74e101Schristos 3980f74e101Schristos /* 3990f74e101Schristos * constants for ASN.1 decoding 4000f74e101Schristos */ 4010f74e101Schristos #define OIDMUX 40 4020f74e101Schristos #define ASNLEN_INETADDR 4 4030f74e101Schristos #define ASN_SHIFT7 7 4040f74e101Schristos #define ASN_SHIFT8 8 4050f74e101Schristos #define ASN_BIT8 0x80 4060f74e101Schristos #define ASN_LONGLEN 0x80 4070f74e101Schristos 4080f74e101Schristos #define ASN_ID_BITS 0x1f 4090f74e101Schristos #define ASN_FORM_BITS 0x20 4100f74e101Schristos #define ASN_FORM_SHIFT 5 4110f74e101Schristos #define ASN_CLASS_BITS 0xc0 4120f74e101Schristos #define ASN_CLASS_SHIFT 6 4130f74e101Schristos 4140f74e101Schristos #define ASN_ID_EXT 0x1f /* extension ID in tag field */ 4150f74e101Schristos 4160f74e101Schristos /* 4170f74e101Schristos * This decodes the next ASN.1 object in the stream pointed to by "p" 4180f74e101Schristos * (and of real-length "len") and stores the intermediate data in the 4190f74e101Schristos * provided BE object. 4200f74e101Schristos * 4210f74e101Schristos * This returns -l if it fails (i.e., the ASN.1 stream is not valid). 4220f74e101Schristos * O/w, this returns the number of bytes parsed from "p". 4230f74e101Schristos */ 4240f74e101Schristos static int 425b3a00663Schristos asn1_parse(netdissect_options *ndo, 426c74ad251Schristos const u_char *p, u_int len, struct be *elem) 4270f74e101Schristos { 4280f74e101Schristos u_char form, class, id; 429c74ad251Schristos u_int i, hdr; 4300f74e101Schristos 4310f74e101Schristos elem->asnlen = 0; 4320f74e101Schristos elem->type = BE_ANY; 4330f74e101Schristos if (len < 1) { 434c74ad251Schristos ND_PRINT("[nothing to parse]"); 4350f74e101Schristos return -1; 4360f74e101Schristos } 4370f74e101Schristos 4380f74e101Schristos /* 4390f74e101Schristos * it would be nice to use a bit field, but you can't depend on them. 4400f74e101Schristos * +---+---+---+---+---+---+---+---+ 4410f74e101Schristos * + class |frm| id | 4420f74e101Schristos * +---+---+---+---+---+---+---+---+ 4430f74e101Schristos * 7 6 5 4 3 2 1 0 4440f74e101Schristos */ 445c74ad251Schristos id = GET_U_1(p) & ASN_ID_BITS; /* lower 5 bits, range 00-1f */ 4460f74e101Schristos #ifdef notdef 447c74ad251Schristos form = (GET_U_1(p) & 0xe0) >> 5; /* move upper 3 bits to lower 3 */ 4480f74e101Schristos class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */ 4490f74e101Schristos form &= 0x1; /* bit 5 -> bit 0, range 0-1 */ 4500f74e101Schristos #else 451c74ad251Schristos form = (u_char)(GET_U_1(p) & ASN_FORM_BITS) >> ASN_FORM_SHIFT; 452c74ad251Schristos class = (u_char)(GET_U_1(p) & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT; 4530f74e101Schristos #endif 4540f74e101Schristos elem->form = form; 4550f74e101Schristos elem->class = class; 4560f74e101Schristos elem->id = id; 4570f74e101Schristos p++; len--; hdr = 1; 4580f74e101Schristos /* extended tag field */ 4590f74e101Schristos if (id == ASN_ID_EXT) { 4600f74e101Schristos /* 4610f74e101Schristos * The ID follows, as a sequence of octets with the 4620f74e101Schristos * 8th bit set and the remaining 7 bits being 4630f74e101Schristos * the next 7 bits of the value, terminated with 4640f74e101Schristos * an octet with the 8th bit not set. 4650f74e101Schristos * 4660f74e101Schristos * First, assemble all the octets with the 8th 4670f74e101Schristos * bit set. XXX - this doesn't handle a value 4680f74e101Schristos * that won't fit in 32 bits. 4690f74e101Schristos */ 470dc860a36Sspz id = 0; 471c74ad251Schristos while (GET_U_1(p) & ASN_BIT8) { 4720f74e101Schristos if (len < 1) { 473c74ad251Schristos ND_PRINT("[Xtagfield?]"); 4740f74e101Schristos return -1; 4750f74e101Schristos } 476c74ad251Schristos id = (id << 7) | (GET_U_1(p) & ~ASN_BIT8); 477dc860a36Sspz len--; 478dc860a36Sspz hdr++; 479dc860a36Sspz p++; 4800f74e101Schristos } 4810f74e101Schristos if (len < 1) { 482c74ad251Schristos ND_PRINT("[Xtagfield?]"); 4830f74e101Schristos return -1; 4840f74e101Schristos } 485c74ad251Schristos elem->id = id = (id << 7) | GET_U_1(p); 4860f74e101Schristos --len; 4870f74e101Schristos ++hdr; 4880f74e101Schristos ++p; 4890f74e101Schristos } 4900f74e101Schristos if (len < 1) { 491c74ad251Schristos ND_PRINT("[no asnlen]"); 4920f74e101Schristos return -1; 4930f74e101Schristos } 494c74ad251Schristos elem->asnlen = GET_U_1(p); 4950f74e101Schristos p++; len--; hdr++; 4960f74e101Schristos if (elem->asnlen & ASN_BIT8) { 497b3a00663Schristos uint32_t noct = elem->asnlen % ASN_BIT8; 4980f74e101Schristos elem->asnlen = 0; 4990f74e101Schristos if (len < noct) { 500c74ad251Schristos ND_PRINT("[asnlen? %d<%d]", len, noct); 5010f74e101Schristos return -1; 5020f74e101Schristos } 503c74ad251Schristos ND_TCHECK_LEN(p, noct); 504c74ad251Schristos for (; noct != 0; len--, hdr++, noct--) { 505c74ad251Schristos elem->asnlen = (elem->asnlen << ASN_SHIFT8) | GET_U_1(p); 506c74ad251Schristos p++; 507c74ad251Schristos } 5080f74e101Schristos } 5090f74e101Schristos if (len < elem->asnlen) { 510c74ad251Schristos ND_PRINT("[len%d<asnlen%u]", len, elem->asnlen); 5110f74e101Schristos return -1; 5120f74e101Schristos } 5130f74e101Schristos if (form >= sizeof(Form)/sizeof(Form[0])) { 514c74ad251Schristos ND_PRINT("[form?%d]", form); 5150f74e101Schristos return -1; 5160f74e101Schristos } 5170f74e101Schristos if (class >= sizeof(Class)/sizeof(Class[0])) { 518c74ad251Schristos ND_PRINT("[class?%c/%d]", *Form[form], class); 5190f74e101Schristos return -1; 5200f74e101Schristos } 5210f74e101Schristos if ((int)id >= Class[class].numIDs) { 522c74ad251Schristos ND_PRINT("[id?%c/%s/%d]", *Form[form], Class[class].name, id); 5230f74e101Schristos return -1; 5240f74e101Schristos } 525c74ad251Schristos ND_TCHECK_LEN(p, elem->asnlen); 5260f74e101Schristos 5270f74e101Schristos switch (form) { 5280f74e101Schristos case PRIMITIVE: 5290f74e101Schristos switch (class) { 5300f74e101Schristos case UNIVERSAL: 5310f74e101Schristos switch (id) { 5320f74e101Schristos case STRING: 5330f74e101Schristos elem->type = BE_STR; 5340f74e101Schristos elem->data.str = p; 5350f74e101Schristos break; 5360f74e101Schristos 5370f74e101Schristos case INTEGER: { 538*26ba0b50Schristos uint32_t data; 5390f74e101Schristos elem->type = BE_INT; 5400f74e101Schristos data = 0; 5410f74e101Schristos 542dc860a36Sspz if (elem->asnlen == 0) { 543c74ad251Schristos ND_PRINT("[asnlen=0]"); 544dc860a36Sspz return -1; 545dc860a36Sspz } 546c74ad251Schristos if (GET_U_1(p) & ASN_BIT8) /* negative */ 547*26ba0b50Schristos data = UINT_MAX; 548c74ad251Schristos for (i = elem->asnlen; i != 0; p++, i--) 549c74ad251Schristos data = (data << ASN_SHIFT8) | GET_U_1(p); 5500f74e101Schristos elem->data.integer = data; 5510f74e101Schristos break; 5520f74e101Schristos } 5530f74e101Schristos 5540f74e101Schristos case OBJECTID: 5550f74e101Schristos elem->type = BE_OID; 556fdccd7e4Schristos elem->data.raw = (const uint8_t *)p; 5570f74e101Schristos break; 5580f74e101Schristos 5590f74e101Schristos case ASN_NULL: 5600f74e101Schristos elem->type = BE_NULL; 5610f74e101Schristos elem->data.raw = NULL; 5620f74e101Schristos break; 5630f74e101Schristos 5640f74e101Schristos default: 5650f74e101Schristos elem->type = BE_OCTET; 566fdccd7e4Schristos elem->data.raw = (const uint8_t *)p; 567c74ad251Schristos ND_PRINT("[P/U/%s]", Class[class].Id[id]); 5680f74e101Schristos break; 5690f74e101Schristos } 5700f74e101Schristos break; 5710f74e101Schristos 5720f74e101Schristos case APPLICATION: 5730f74e101Schristos switch (id) { 5740f74e101Schristos case IPADDR: 5750f74e101Schristos elem->type = BE_INETADDR; 576fdccd7e4Schristos elem->data.raw = (const uint8_t *)p; 5770f74e101Schristos break; 5780f74e101Schristos 5790f74e101Schristos case COUNTER: 5800f74e101Schristos case GAUGE: 5810f74e101Schristos case TIMETICKS: { 582c74ad251Schristos uint32_t data; 5830f74e101Schristos elem->type = BE_UNS; 5840f74e101Schristos data = 0; 585c74ad251Schristos for (i = elem->asnlen; i != 0; p++, i--) 586c74ad251Schristos data = (data << 8) + GET_U_1(p); 5870f74e101Schristos elem->data.uns = data; 5880f74e101Schristos break; 5890f74e101Schristos } 5900f74e101Schristos 5910f74e101Schristos case COUNTER64: { 592c74ad251Schristos uint64_t data64; 5930f74e101Schristos elem->type = BE_UNS64; 594dc860a36Sspz data64 = 0; 595c74ad251Schristos for (i = elem->asnlen; i != 0; p++, i--) 596c74ad251Schristos data64 = (data64 << 8) + GET_U_1(p); 597dc860a36Sspz elem->data.uns64 = data64; 5980f74e101Schristos break; 5990f74e101Schristos } 6000f74e101Schristos 6010f74e101Schristos default: 6020f74e101Schristos elem->type = BE_OCTET; 603fdccd7e4Schristos elem->data.raw = (const uint8_t *)p; 604c74ad251Schristos ND_PRINT("[P/A/%s]", 605c74ad251Schristos Class[class].Id[id]); 6060f74e101Schristos break; 6070f74e101Schristos } 6080f74e101Schristos break; 6090f74e101Schristos 6100f74e101Schristos case CONTEXT: 6110f74e101Schristos switch (id) { 6120f74e101Schristos case NOSUCHOBJECT: 6130f74e101Schristos elem->type = BE_NOSUCHOBJECT; 6140f74e101Schristos elem->data.raw = NULL; 6150f74e101Schristos break; 6160f74e101Schristos 6170f74e101Schristos case NOSUCHINSTANCE: 6180f74e101Schristos elem->type = BE_NOSUCHINST; 6190f74e101Schristos elem->data.raw = NULL; 6200f74e101Schristos break; 6210f74e101Schristos 6220f74e101Schristos case ENDOFMIBVIEW: 6230f74e101Schristos elem->type = BE_ENDOFMIBVIEW; 6240f74e101Schristos elem->data.raw = NULL; 6250f74e101Schristos break; 6260f74e101Schristos } 6270f74e101Schristos break; 6280f74e101Schristos 6290f74e101Schristos default: 630c74ad251Schristos ND_PRINT("[P/%s/%s]", Class[class].name, Class[class].Id[id]); 6310f74e101Schristos elem->type = BE_OCTET; 632fdccd7e4Schristos elem->data.raw = (const uint8_t *)p; 6330f74e101Schristos break; 6340f74e101Schristos } 6350f74e101Schristos break; 6360f74e101Schristos 6370f74e101Schristos case CONSTRUCTED: 6380f74e101Schristos switch (class) { 6390f74e101Schristos case UNIVERSAL: 6400f74e101Schristos switch (id) { 6410f74e101Schristos case SEQUENCE: 6420f74e101Schristos elem->type = BE_SEQ; 643fdccd7e4Schristos elem->data.raw = (const uint8_t *)p; 6440f74e101Schristos break; 6450f74e101Schristos 6460f74e101Schristos default: 6470f74e101Schristos elem->type = BE_OCTET; 648fdccd7e4Schristos elem->data.raw = (const uint8_t *)p; 649c74ad251Schristos ND_PRINT("C/U/%s", Class[class].Id[id]); 6500f74e101Schristos break; 6510f74e101Schristos } 6520f74e101Schristos break; 6530f74e101Schristos 6540f74e101Schristos case CONTEXT: 6550f74e101Schristos elem->type = BE_PDU; 656fdccd7e4Schristos elem->data.raw = (const uint8_t *)p; 6570f74e101Schristos break; 6580f74e101Schristos 6590f74e101Schristos default: 6600f74e101Schristos elem->type = BE_OCTET; 661fdccd7e4Schristos elem->data.raw = (const uint8_t *)p; 662c74ad251Schristos ND_PRINT("C/%s/%s", Class[class].name, Class[class].Id[id]); 6630f74e101Schristos break; 6640f74e101Schristos } 6650f74e101Schristos break; 6660f74e101Schristos } 6670f74e101Schristos p += elem->asnlen; 6680f74e101Schristos len -= elem->asnlen; 6690f74e101Schristos return elem->asnlen + hdr; 6700f74e101Schristos 6710f74e101Schristos trunc: 672c74ad251Schristos nd_print_trunc(ndo); 6730f74e101Schristos return -1; 6740f74e101Schristos } 6750f74e101Schristos 676dc860a36Sspz static int 677dc860a36Sspz asn1_print_octets(netdissect_options *ndo, struct be *elem) 678dc860a36Sspz { 679dc860a36Sspz const u_char *p = (const u_char *)elem->data.raw; 680dc860a36Sspz uint32_t asnlen = elem->asnlen; 681dc860a36Sspz uint32_t i; 682dc860a36Sspz 683c74ad251Schristos ND_TCHECK_LEN(p, asnlen); 684c74ad251Schristos for (i = asnlen; i != 0; p++, i--) 685c74ad251Schristos ND_PRINT("_%.2x", GET_U_1(p)); 686dc860a36Sspz return 0; 687dc860a36Sspz 688dc860a36Sspz trunc: 689c74ad251Schristos nd_print_trunc(ndo); 690dc860a36Sspz return -1; 691dc860a36Sspz } 692dc860a36Sspz 693dc860a36Sspz static int 694dc860a36Sspz asn1_print_string(netdissect_options *ndo, struct be *elem) 695dc860a36Sspz { 696c74ad251Schristos int printable = 1, first = 1; 697dc860a36Sspz const u_char *p; 698dc860a36Sspz uint32_t asnlen = elem->asnlen; 699dc860a36Sspz uint32_t i; 700dc860a36Sspz 701dc860a36Sspz p = elem->data.str; 702c74ad251Schristos ND_TCHECK_LEN(p, asnlen); 703c74ad251Schristos for (i = asnlen; printable && i != 0; p++, i--) 704c74ad251Schristos printable = ND_ASCII_ISPRINT(GET_U_1(p)); 705dc860a36Sspz p = elem->data.str; 706dc860a36Sspz if (printable) { 707c74ad251Schristos ND_PRINT("\""); 708c74ad251Schristos if (nd_printn(ndo, p, asnlen, ndo->ndo_snapend)) { 709c74ad251Schristos ND_PRINT("\""); 710dc860a36Sspz goto trunc; 711dc860a36Sspz } 712c74ad251Schristos ND_PRINT("\""); 713dc860a36Sspz } else { 714c74ad251Schristos for (i = asnlen; i != 0; p++, i--) { 715c74ad251Schristos ND_PRINT(first ? "%.2x" : "_%.2x", GET_U_1(p)); 716dc860a36Sspz first = 0; 717dc860a36Sspz } 718dc860a36Sspz } 719dc860a36Sspz return 0; 720dc860a36Sspz 721dc860a36Sspz trunc: 722c74ad251Schristos nd_print_trunc(ndo); 723dc860a36Sspz return -1; 724dc860a36Sspz } 725dc860a36Sspz 7260f74e101Schristos /* 7270f74e101Schristos * Display the ASN.1 object represented by the BE object. 7280f74e101Schristos * This used to be an integral part of asn1_parse() before the intermediate 7290f74e101Schristos * BE form was added. 7300f74e101Schristos */ 7310f74e101Schristos static int 732b3a00663Schristos asn1_print(netdissect_options *ndo, 733b3a00663Schristos struct be *elem) 7340f74e101Schristos { 735dc860a36Sspz const u_char *p; 736b3a00663Schristos uint32_t asnlen = elem->asnlen; 737b3a00663Schristos uint32_t i; 7380f74e101Schristos 7390f74e101Schristos switch (elem->type) { 7400f74e101Schristos 7410f74e101Schristos case BE_OCTET: 742dc860a36Sspz if (asn1_print_octets(ndo, elem) == -1) 743dc860a36Sspz return -1; 7440f74e101Schristos break; 7450f74e101Schristos 7460f74e101Schristos case BE_NULL: 7470f74e101Schristos break; 7480f74e101Schristos 7490f74e101Schristos case BE_OID: { 750*26ba0b50Schristos int first = -1; 751*26ba0b50Schristos uint32_t o = 0; 7520f74e101Schristos 753dc860a36Sspz p = (const u_char *)elem->data.raw; 754fdccd7e4Schristos i = asnlen; 755dc860a36Sspz if (!ndo->ndo_nflag && asnlen > 2) { 756b3a00663Schristos const struct obj_abrev *a = &obj_abrev_list[0]; 7570f74e101Schristos for (; a->node; a++) { 758dc860a36Sspz if (i < a->oid_len) 759dc860a36Sspz continue; 760c74ad251Schristos if (!ND_TTEST_LEN(p, a->oid_len)) 761dc860a36Sspz continue; 762dc860a36Sspz if (memcmp(a->oid, p, a->oid_len) == 0) { 7630f74e101Schristos objp = a->node->child; 764dc860a36Sspz i -= a->oid_len; 765dc860a36Sspz p += a->oid_len; 766c74ad251Schristos ND_PRINT("%s", a->prefix); 7670f74e101Schristos first = 1; 7680f74e101Schristos break; 7690f74e101Schristos } 7700f74e101Schristos } 7710f74e101Schristos } 7720f74e101Schristos 773c74ad251Schristos for (; i != 0; p++, i--) { 774c74ad251Schristos o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8); 775c74ad251Schristos if (GET_U_1(p) & ASN_LONGLEN) 7760f74e101Schristos continue; 7770f74e101Schristos 7780f74e101Schristos /* 779dc860a36Sspz * first subitem encodes two items with 780dc860a36Sspz * 1st*OIDMUX+2nd 7810f74e101Schristos * (see X.690:1997 clause 8.19 for the details) 7820f74e101Schristos */ 7830f74e101Schristos if (first < 0) { 7840f74e101Schristos int s; 785b3a00663Schristos if (!ndo->ndo_nflag) 7860f74e101Schristos objp = mibroot; 7870f74e101Schristos first = 0; 7880f74e101Schristos s = o / OIDMUX; 7890f74e101Schristos if (s > 2) s = 2; 7900f74e101Schristos OBJ_PRINT(s, first); 7910f74e101Schristos o -= s * OIDMUX; 7920f74e101Schristos } 7930f74e101Schristos OBJ_PRINT(o, first); 7940f74e101Schristos if (--first < 0) 7950f74e101Schristos first = 0; 7960f74e101Schristos o = 0; 7970f74e101Schristos } 7980f74e101Schristos break; 7990f74e101Schristos } 8000f74e101Schristos 8010f74e101Schristos case BE_INT: 802c74ad251Schristos ND_PRINT("%d", elem->data.integer); 8030f74e101Schristos break; 8040f74e101Schristos 8050f74e101Schristos case BE_UNS: 806c74ad251Schristos ND_PRINT("%u", elem->data.uns); 8070f74e101Schristos break; 8080f74e101Schristos 809dc860a36Sspz case BE_UNS64: 810c74ad251Schristos ND_PRINT("%" PRIu64, elem->data.uns64); 8110f74e101Schristos break; 8120f74e101Schristos 813dc860a36Sspz case BE_STR: 814dc860a36Sspz if (asn1_print_string(ndo, elem) == -1) 815dc860a36Sspz return -1; 8160f74e101Schristos break; 8170f74e101Schristos 8180f74e101Schristos case BE_SEQ: 819c74ad251Schristos ND_PRINT("Seq(%u)", elem->asnlen); 8200f74e101Schristos break; 8210f74e101Schristos 8220f74e101Schristos case BE_INETADDR: 8230f74e101Schristos if (asnlen != ASNLEN_INETADDR) 824c74ad251Schristos ND_PRINT("[inetaddr len!=%d]", ASNLEN_INETADDR); 825dc860a36Sspz p = (const u_char *)elem->data.raw; 826c74ad251Schristos ND_TCHECK_LEN(p, asnlen); 827c74ad251Schristos for (i = asnlen; i != 0; p++, i--) { 828c74ad251Schristos ND_PRINT((i == asnlen) ? "%u" : ".%u", GET_U_1(p)); 8290f74e101Schristos } 8300f74e101Schristos break; 8310f74e101Schristos 8320f74e101Schristos case BE_NOSUCHOBJECT: 8330f74e101Schristos case BE_NOSUCHINST: 8340f74e101Schristos case BE_ENDOFMIBVIEW: 835c74ad251Schristos ND_PRINT("[%s]", Class[EXCEPTIONS].Id[elem->id]); 8360f74e101Schristos break; 8370f74e101Schristos 8380f74e101Schristos case BE_PDU: 839c74ad251Schristos ND_PRINT("%s(%u)", Class[CONTEXT].Id[elem->id], elem->asnlen); 8400f74e101Schristos break; 8410f74e101Schristos 8420f74e101Schristos case BE_ANY: 843c74ad251Schristos ND_PRINT("[BE_ANY!?]"); 8440f74e101Schristos break; 8450f74e101Schristos 8460f74e101Schristos default: 847c74ad251Schristos ND_PRINT("[be!?]"); 8480f74e101Schristos break; 8490f74e101Schristos } 8500f74e101Schristos return 0; 8510f74e101Schristos 8520f74e101Schristos trunc: 853c74ad251Schristos nd_print_trunc(ndo); 8540f74e101Schristos return -1; 8550f74e101Schristos } 8560f74e101Schristos 8570f74e101Schristos #ifdef notdef 8580f74e101Schristos /* 8590f74e101Schristos * This is a brute force ASN.1 printer: recurses to dump an entire structure. 8600f74e101Schristos * This will work for any ASN.1 stream, not just an SNMP PDU. 8610f74e101Schristos * 8620f74e101Schristos * By adding newlines and spaces at the correct places, this would print in 8630f74e101Schristos * Rose-Normal-Form. 8640f74e101Schristos * 8650f74e101Schristos * This is not currently used. 8660f74e101Schristos */ 8670f74e101Schristos static void 8680f74e101Schristos asn1_decode(u_char *p, u_int length) 8690f74e101Schristos { 8700f74e101Schristos struct be elem; 8710f74e101Schristos int i = 0; 8720f74e101Schristos 8730f74e101Schristos while (i >= 0 && length > 0) { 874b3a00663Schristos i = asn1_parse(ndo, p, length, &elem); 8750f74e101Schristos if (i >= 0) { 876c74ad251Schristos ND_PRINT(" "); 877b3a00663Schristos if (asn1_print(ndo, &elem) < 0) 8780f74e101Schristos return; 8790f74e101Schristos if (elem.type == BE_SEQ || elem.type == BE_PDU) { 880c74ad251Schristos ND_PRINT(" {"); 8810f74e101Schristos asn1_decode(elem.data.raw, elem.asnlen); 882c74ad251Schristos ND_PRINT(" }"); 8830f74e101Schristos } 8840f74e101Schristos length -= i; 8850f74e101Schristos p += i; 8860f74e101Schristos } 8870f74e101Schristos } 8880f74e101Schristos } 8890f74e101Schristos #endif 8900f74e101Schristos 891b3a00663Schristos #ifdef USE_LIBSMI 8920f74e101Schristos 8930f74e101Schristos struct smi2be { 8940f74e101Schristos SmiBasetype basetype; 8950f74e101Schristos int be; 8960f74e101Schristos }; 8970f74e101Schristos 898b3a00663Schristos static const struct smi2be smi2betab[] = { 8990f74e101Schristos { SMI_BASETYPE_INTEGER32, BE_INT }, 9000f74e101Schristos { SMI_BASETYPE_OCTETSTRING, BE_STR }, 9010f74e101Schristos { SMI_BASETYPE_OCTETSTRING, BE_INETADDR }, 9020f74e101Schristos { SMI_BASETYPE_OBJECTIDENTIFIER, BE_OID }, 9030f74e101Schristos { SMI_BASETYPE_UNSIGNED32, BE_UNS }, 9040f74e101Schristos { SMI_BASETYPE_INTEGER64, BE_NONE }, 9050f74e101Schristos { SMI_BASETYPE_UNSIGNED64, BE_UNS64 }, 9060f74e101Schristos { SMI_BASETYPE_FLOAT32, BE_NONE }, 9070f74e101Schristos { SMI_BASETYPE_FLOAT64, BE_NONE }, 9080f74e101Schristos { SMI_BASETYPE_FLOAT128, BE_NONE }, 9090f74e101Schristos { SMI_BASETYPE_ENUM, BE_INT }, 9100f74e101Schristos { SMI_BASETYPE_BITS, BE_STR }, 9110f74e101Schristos { SMI_BASETYPE_UNKNOWN, BE_NONE } 9120f74e101Schristos }; 9130f74e101Schristos 9140f74e101Schristos static int 915b3a00663Schristos smi_decode_oid(netdissect_options *ndo, 916b3a00663Schristos struct be *elem, unsigned int *oid, 9170f74e101Schristos unsigned int oidsize, unsigned int *oidlen) 9180f74e101Schristos { 919fdccd7e4Schristos const u_char *p = (const u_char *)elem->data.raw; 920b3a00663Schristos uint32_t asnlen = elem->asnlen; 921c74ad251Schristos uint32_t i = asnlen; 922c74ad251Schristos int o = 0, first = -1; 923b3a00663Schristos unsigned int firstval; 9240f74e101Schristos 925c74ad251Schristos for (*oidlen = 0; i != 0; p++, i--) { 926c74ad251Schristos o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8); 927c74ad251Schristos if (GET_U_1(p) & ASN_LONGLEN) 9280f74e101Schristos continue; 9290f74e101Schristos 9300f74e101Schristos /* 9310f74e101Schristos * first subitem encodes two items with 1st*OIDMUX+2nd 9320f74e101Schristos * (see X.690:1997 clause 8.19 for the details) 9330f74e101Schristos */ 9340f74e101Schristos if (first < 0) { 9350f74e101Schristos first = 0; 936b3a00663Schristos firstval = o / OIDMUX; 937b3a00663Schristos if (firstval > 2) firstval = 2; 938b3a00663Schristos o -= firstval * OIDMUX; 9390f74e101Schristos if (*oidlen < oidsize) { 940b3a00663Schristos oid[(*oidlen)++] = firstval; 9410f74e101Schristos } 9420f74e101Schristos } 9430f74e101Schristos if (*oidlen < oidsize) { 9440f74e101Schristos oid[(*oidlen)++] = o; 9450f74e101Schristos } 9460f74e101Schristos o = 0; 9470f74e101Schristos } 9480f74e101Schristos return 0; 9490f74e101Schristos } 9500f74e101Schristos 9510f74e101Schristos static int smi_check_type(SmiBasetype basetype, int be) 9520f74e101Schristos { 9530f74e101Schristos int i; 9540f74e101Schristos 9550f74e101Schristos for (i = 0; smi2betab[i].basetype != SMI_BASETYPE_UNKNOWN; i++) { 9560f74e101Schristos if (smi2betab[i].basetype == basetype && smi2betab[i].be == be) { 9570f74e101Schristos return 1; 9580f74e101Schristos } 9590f74e101Schristos } 9600f74e101Schristos 9610f74e101Schristos return 0; 9620f74e101Schristos } 9630f74e101Schristos 9640f74e101Schristos static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange, 9650f74e101Schristos struct be *elem) 9660f74e101Schristos { 9670f74e101Schristos int ok = 1; 9680f74e101Schristos 9690f74e101Schristos switch (smiType->basetype) { 9700f74e101Schristos case SMI_BASETYPE_OBJECTIDENTIFIER: 9710f74e101Schristos case SMI_BASETYPE_OCTETSTRING: 9720f74e101Schristos if (smiRange->minValue.value.unsigned32 9730f74e101Schristos == smiRange->maxValue.value.unsigned32) { 9740f74e101Schristos ok = (elem->asnlen == smiRange->minValue.value.unsigned32); 9750f74e101Schristos } else { 9760f74e101Schristos ok = (elem->asnlen >= smiRange->minValue.value.unsigned32 9770f74e101Schristos && elem->asnlen <= smiRange->maxValue.value.unsigned32); 9780f74e101Schristos } 9790f74e101Schristos break; 9800f74e101Schristos 9810f74e101Schristos case SMI_BASETYPE_INTEGER32: 9820f74e101Schristos ok = (elem->data.integer >= smiRange->minValue.value.integer32 9830f74e101Schristos && elem->data.integer <= smiRange->maxValue.value.integer32); 9840f74e101Schristos break; 9850f74e101Schristos 9860f74e101Schristos case SMI_BASETYPE_UNSIGNED32: 9870f74e101Schristos ok = (elem->data.uns >= smiRange->minValue.value.unsigned32 9880f74e101Schristos && elem->data.uns <= smiRange->maxValue.value.unsigned32); 9890f74e101Schristos break; 9900f74e101Schristos 9910f74e101Schristos case SMI_BASETYPE_UNSIGNED64: 9920f74e101Schristos /* XXX */ 9930f74e101Schristos break; 9940f74e101Schristos 9950f74e101Schristos /* case SMI_BASETYPE_INTEGER64: SMIng */ 9960f74e101Schristos /* case SMI_BASETYPE_FLOAT32: SMIng */ 9970f74e101Schristos /* case SMI_BASETYPE_FLOAT64: SMIng */ 9980f74e101Schristos /* case SMI_BASETYPE_FLOAT128: SMIng */ 9990f74e101Schristos 10000f74e101Schristos case SMI_BASETYPE_ENUM: 10010f74e101Schristos case SMI_BASETYPE_BITS: 10020f74e101Schristos case SMI_BASETYPE_UNKNOWN: 10030f74e101Schristos ok = 1; 10040f74e101Schristos break; 10050f74e101Schristos 10060f74e101Schristos default: 10070f74e101Schristos ok = 0; 10080f74e101Schristos break; 10090f74e101Schristos } 10100f74e101Schristos 10110f74e101Schristos return ok; 10120f74e101Schristos } 10130f74e101Schristos 10140f74e101Schristos static int smi_check_range(SmiType *smiType, struct be *elem) 10150f74e101Schristos { 10160f74e101Schristos SmiRange *smiRange; 10170f74e101Schristos int ok = 1; 10180f74e101Schristos 10190f74e101Schristos for (smiRange = smiGetFirstRange(smiType); 10200f74e101Schristos smiRange; 10210f74e101Schristos smiRange = smiGetNextRange(smiRange)) { 10220f74e101Schristos 10230f74e101Schristos ok = smi_check_a_range(smiType, smiRange, elem); 10240f74e101Schristos 10250f74e101Schristos if (ok) { 10260f74e101Schristos break; 10270f74e101Schristos } 10280f74e101Schristos } 10290f74e101Schristos 10300f74e101Schristos if (ok) { 10310f74e101Schristos SmiType *parentType; 10320f74e101Schristos parentType = smiGetParentType(smiType); 10330f74e101Schristos if (parentType) { 10340f74e101Schristos ok = smi_check_range(parentType, elem); 10350f74e101Schristos } 10360f74e101Schristos } 10370f74e101Schristos 10380f74e101Schristos return ok; 10390f74e101Schristos } 10400f74e101Schristos 1041b3a00663Schristos static SmiNode * 1042b3a00663Schristos smi_print_variable(netdissect_options *ndo, 1043b3a00663Schristos struct be *elem, int *status) 10440f74e101Schristos { 10450f74e101Schristos unsigned int oid[128], oidlen; 10460f74e101Schristos SmiNode *smiNode = NULL; 10470f74e101Schristos unsigned int i; 10480f74e101Schristos 1049dc860a36Sspz if (!nd_smi_module_loaded) { 1050dc860a36Sspz *status = asn1_print(ndo, elem); 1051dc860a36Sspz return NULL; 1052dc860a36Sspz } 1053b3a00663Schristos *status = smi_decode_oid(ndo, elem, oid, sizeof(oid) / sizeof(unsigned int), 10540f74e101Schristos &oidlen); 10550f74e101Schristos if (*status < 0) 10560f74e101Schristos return NULL; 10570f74e101Schristos smiNode = smiGetNodeByOID(oidlen, oid); 10580f74e101Schristos if (! smiNode) { 1059b3a00663Schristos *status = asn1_print(ndo, elem); 10600f74e101Schristos return NULL; 10610f74e101Schristos } 1062b3a00663Schristos if (ndo->ndo_vflag) { 1063c74ad251Schristos ND_PRINT("%s::", smiGetNodeModule(smiNode)->name); 10640f74e101Schristos } 1065c74ad251Schristos ND_PRINT("%s", smiNode->name); 10660f74e101Schristos if (smiNode->oidlen < oidlen) { 10670f74e101Schristos for (i = smiNode->oidlen; i < oidlen; i++) { 1068c74ad251Schristos ND_PRINT(".%u", oid[i]); 10690f74e101Schristos } 10700f74e101Schristos } 10710f74e101Schristos *status = 0; 10720f74e101Schristos return smiNode; 10730f74e101Schristos } 10740f74e101Schristos 10750f74e101Schristos static int 1076b3a00663Schristos smi_print_value(netdissect_options *ndo, 1077fdccd7e4Schristos SmiNode *smiNode, u_short pduid, struct be *elem) 10780f74e101Schristos { 10790f74e101Schristos unsigned int i, oid[128], oidlen; 10800f74e101Schristos SmiType *smiType; 10810f74e101Schristos SmiNamedNumber *nn; 10820f74e101Schristos int done = 0; 10830f74e101Schristos 10840f74e101Schristos if (! smiNode || ! (smiNode->nodekind 10850f74e101Schristos & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) { 1086b3a00663Schristos return asn1_print(ndo, elem); 10870f74e101Schristos } 10880f74e101Schristos 10890f74e101Schristos if (elem->type == BE_NOSUCHOBJECT 10900f74e101Schristos || elem->type == BE_NOSUCHINST 10910f74e101Schristos || elem->type == BE_ENDOFMIBVIEW) { 1092b3a00663Schristos return asn1_print(ndo, elem); 10930f74e101Schristos } 10940f74e101Schristos 10950f74e101Schristos if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) { 1096*26ba0b50Schristos ND_PRINT("[notNotifiable]"); 10970f74e101Schristos } 10980f74e101Schristos 10990f74e101Schristos if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) { 1100c74ad251Schristos ND_PRINT("[notReadable]"); 11010f74e101Schristos } 11020f74e101Schristos 11030f74e101Schristos if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) { 1104c74ad251Schristos ND_PRINT("[notWritable]"); 11050f74e101Schristos } 11060f74e101Schristos 11070f74e101Schristos if (RESPONSE_CLASS(pduid) 11080f74e101Schristos && smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) { 1109c74ad251Schristos ND_PRINT("[noAccess]"); 11100f74e101Schristos } 11110f74e101Schristos 11120f74e101Schristos smiType = smiGetNodeType(smiNode); 11130f74e101Schristos if (! smiType) { 1114b3a00663Schristos return asn1_print(ndo, elem); 11150f74e101Schristos } 11160f74e101Schristos 11170f74e101Schristos if (! smi_check_type(smiType->basetype, elem->type)) { 1118c74ad251Schristos ND_PRINT("[wrongType]"); 11190f74e101Schristos } 11200f74e101Schristos 11210f74e101Schristos if (! smi_check_range(smiType, elem)) { 1122c74ad251Schristos ND_PRINT("[outOfRange]"); 11230f74e101Schristos } 11240f74e101Schristos 11250f74e101Schristos /* resolve bits to named bits */ 11260f74e101Schristos 11270f74e101Schristos /* check whether instance identifier is valid */ 11280f74e101Schristos 11290f74e101Schristos /* apply display hints (integer, octetstring) */ 11300f74e101Schristos 11310f74e101Schristos /* convert instance identifier to index type values */ 11320f74e101Schristos 11330f74e101Schristos switch (elem->type) { 11340f74e101Schristos case BE_OID: 11350f74e101Schristos if (smiType->basetype == SMI_BASETYPE_BITS) { 11360f74e101Schristos /* print bit labels */ 11370f74e101Schristos } else { 1138dc860a36Sspz if (nd_smi_module_loaded && 1139b3a00663Schristos smi_decode_oid(ndo, elem, oid, 11400f74e101Schristos sizeof(oid)/sizeof(unsigned int), 1141dc860a36Sspz &oidlen) == 0) { 11420f74e101Schristos smiNode = smiGetNodeByOID(oidlen, oid); 11430f74e101Schristos if (smiNode) { 1144b3a00663Schristos if (ndo->ndo_vflag) { 1145c74ad251Schristos ND_PRINT("%s::", smiGetNodeModule(smiNode)->name); 11460f74e101Schristos } 1147c74ad251Schristos ND_PRINT("%s", smiNode->name); 11480f74e101Schristos if (smiNode->oidlen < oidlen) { 11490f74e101Schristos for (i = smiNode->oidlen; 11500f74e101Schristos i < oidlen; i++) { 1151c74ad251Schristos ND_PRINT(".%u", oid[i]); 11520f74e101Schristos } 11530f74e101Schristos } 11540f74e101Schristos done++; 11550f74e101Schristos } 11560f74e101Schristos } 1157dc860a36Sspz } 11580f74e101Schristos break; 11590f74e101Schristos 11600f74e101Schristos case BE_INT: 11610f74e101Schristos if (smiType->basetype == SMI_BASETYPE_ENUM) { 11620f74e101Schristos for (nn = smiGetFirstNamedNumber(smiType); 11630f74e101Schristos nn; 11640f74e101Schristos nn = smiGetNextNamedNumber(nn)) { 11650f74e101Schristos if (nn->value.value.integer32 11660f74e101Schristos == elem->data.integer) { 1167c74ad251Schristos ND_PRINT("%s", nn->name); 1168c74ad251Schristos ND_PRINT("(%d)", elem->data.integer); 11690f74e101Schristos done++; 11700f74e101Schristos break; 11710f74e101Schristos } 11720f74e101Schristos } 11730f74e101Schristos } 11740f74e101Schristos break; 11750f74e101Schristos } 11760f74e101Schristos 11770f74e101Schristos if (! done) { 1178b3a00663Schristos return asn1_print(ndo, elem); 11790f74e101Schristos } 11800f74e101Schristos return 0; 11810f74e101Schristos } 11820f74e101Schristos #endif 11830f74e101Schristos 11840f74e101Schristos /* 11850f74e101Schristos * General SNMP header 11860f74e101Schristos * SEQUENCE { 11870f74e101Schristos * version INTEGER {version-1(0)}, 11880f74e101Schristos * community OCTET STRING, 11890f74e101Schristos * data ANY -- PDUs 11900f74e101Schristos * } 11910f74e101Schristos * PDUs for all but Trap: (see rfc1157 from page 15 on) 11920f74e101Schristos * SEQUENCE { 11930f74e101Schristos * request-id INTEGER, 11940f74e101Schristos * error-status INTEGER, 11950f74e101Schristos * error-index INTEGER, 11960f74e101Schristos * varbindlist SEQUENCE OF 11970f74e101Schristos * SEQUENCE { 11980f74e101Schristos * name ObjectName, 11990f74e101Schristos * value ObjectValue 12000f74e101Schristos * } 12010f74e101Schristos * } 12020f74e101Schristos * PDU for Trap: 12030f74e101Schristos * SEQUENCE { 12040f74e101Schristos * enterprise OBJECT IDENTIFIER, 12050f74e101Schristos * agent-addr NetworkAddress, 12060f74e101Schristos * generic-trap INTEGER, 12070f74e101Schristos * specific-trap INTEGER, 12080f74e101Schristos * time-stamp TimeTicks, 12090f74e101Schristos * varbindlist SEQUENCE OF 12100f74e101Schristos * SEQUENCE { 12110f74e101Schristos * name ObjectName, 12120f74e101Schristos * value ObjectValue 12130f74e101Schristos * } 12140f74e101Schristos * } 12150f74e101Schristos */ 12160f74e101Schristos 12170f74e101Schristos /* 12180f74e101Schristos * Decode SNMP varBind 12190f74e101Schristos */ 12200f74e101Schristos static void 1221b3a00663Schristos varbind_print(netdissect_options *ndo, 1222fdccd7e4Schristos u_short pduid, const u_char *np, u_int length) 12230f74e101Schristos { 12240f74e101Schristos struct be elem; 1225c74ad251Schristos int count = 0; 1226b3a00663Schristos #ifdef USE_LIBSMI 12270f74e101Schristos SmiNode *smiNode = NULL; 12280f74e101Schristos #endif 12290f74e101Schristos int status; 12300f74e101Schristos 12310f74e101Schristos /* Sequence of varBind */ 1232b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 12330f74e101Schristos return; 12340f74e101Schristos if (elem.type != BE_SEQ) { 1235c74ad251Schristos ND_PRINT("[!SEQ of varbind]"); 1236b3a00663Schristos asn1_print(ndo, &elem); 12370f74e101Schristos return; 12380f74e101Schristos } 12390f74e101Schristos if ((u_int)count < length) 1240c74ad251Schristos ND_PRINT("[%d extra after SEQ of varbind]", length - count); 12410f74e101Schristos /* descend */ 12420f74e101Schristos length = elem.asnlen; 1243fdccd7e4Schristos np = (const u_char *)elem.data.raw; 12440f74e101Schristos 1245c74ad251Schristos while (length) { 12460f74e101Schristos const u_char *vbend; 12470f74e101Schristos u_int vblength; 12480f74e101Schristos 1249c74ad251Schristos ND_PRINT(" "); 12500f74e101Schristos 12510f74e101Schristos /* Sequence */ 1252b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 12530f74e101Schristos return; 12540f74e101Schristos if (elem.type != BE_SEQ) { 1255c74ad251Schristos ND_PRINT("[!varbind]"); 1256b3a00663Schristos asn1_print(ndo, &elem); 12570f74e101Schristos return; 12580f74e101Schristos } 12590f74e101Schristos vbend = np + count; 12600f74e101Schristos vblength = length - count; 12610f74e101Schristos /* descend */ 12620f74e101Schristos length = elem.asnlen; 1263fdccd7e4Schristos np = (const u_char *)elem.data.raw; 12640f74e101Schristos 12650f74e101Schristos /* objName (OID) */ 1266b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 12670f74e101Schristos return; 12680f74e101Schristos if (elem.type != BE_OID) { 1269c74ad251Schristos ND_PRINT("[objName!=OID]"); 1270b3a00663Schristos asn1_print(ndo, &elem); 12710f74e101Schristos return; 12720f74e101Schristos } 1273b3a00663Schristos #ifdef USE_LIBSMI 1274b3a00663Schristos smiNode = smi_print_variable(ndo, &elem, &status); 12750f74e101Schristos #else 1276b3a00663Schristos status = asn1_print(ndo, &elem); 12770f74e101Schristos #endif 12780f74e101Schristos if (status < 0) 12790f74e101Schristos return; 12800f74e101Schristos length -= count; 12810f74e101Schristos np += count; 12820f74e101Schristos 12830f74e101Schristos if (pduid != GETREQ && pduid != GETNEXTREQ 12840f74e101Schristos && pduid != GETBULKREQ) 1285c74ad251Schristos ND_PRINT("="); 12860f74e101Schristos 12870f74e101Schristos /* objVal (ANY) */ 1288b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 12890f74e101Schristos return; 12900f74e101Schristos if (pduid == GETREQ || pduid == GETNEXTREQ 12910f74e101Schristos || pduid == GETBULKREQ) { 12920f74e101Schristos if (elem.type != BE_NULL) { 1293c74ad251Schristos ND_PRINT("[objVal!=NULL]"); 1294b3a00663Schristos if (asn1_print(ndo, &elem) < 0) 12950f74e101Schristos return; 12960f74e101Schristos } 12970f74e101Schristos } else { 12980f74e101Schristos if (elem.type != BE_NULL) { 1299b3a00663Schristos #ifdef USE_LIBSMI 1300b3a00663Schristos status = smi_print_value(ndo, smiNode, pduid, &elem); 13010f74e101Schristos #else 1302b3a00663Schristos status = asn1_print(ndo, &elem); 13030f74e101Schristos #endif 13040f74e101Schristos } 13050f74e101Schristos if (status < 0) 13060f74e101Schristos return; 13070f74e101Schristos } 13080f74e101Schristos length = vblength; 13090f74e101Schristos np = vbend; 13100f74e101Schristos } 13110f74e101Schristos } 13120f74e101Schristos 13130f74e101Schristos /* 13140f74e101Schristos * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest, 13150f74e101Schristos * GetBulk, Inform, V2Trap, and Report 13160f74e101Schristos */ 13170f74e101Schristos static void 1318b3a00663Schristos snmppdu_print(netdissect_options *ndo, 1319b3a00663Schristos u_short pduid, const u_char *np, u_int length) 13200f74e101Schristos { 13210f74e101Schristos struct be elem; 1322fdccd7e4Schristos int count = 0, error_status; 13230f74e101Schristos 13240f74e101Schristos /* reqId (Integer) */ 1325b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 13260f74e101Schristos return; 13270f74e101Schristos if (elem.type != BE_INT) { 1328c74ad251Schristos ND_PRINT("[reqId!=INT]"); 1329b3a00663Schristos asn1_print(ndo, &elem); 13300f74e101Schristos return; 13310f74e101Schristos } 1332b3a00663Schristos if (ndo->ndo_vflag) 1333c74ad251Schristos ND_PRINT("R=%d ", elem.data.integer); 13340f74e101Schristos length -= count; 13350f74e101Schristos np += count; 13360f74e101Schristos 13370f74e101Schristos /* errorStatus (Integer) */ 1338b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 13390f74e101Schristos return; 13400f74e101Schristos if (elem.type != BE_INT) { 1341c74ad251Schristos ND_PRINT("[errorStatus!=INT]"); 1342b3a00663Schristos asn1_print(ndo, &elem); 13430f74e101Schristos return; 13440f74e101Schristos } 1345fdccd7e4Schristos error_status = 0; 13460f74e101Schristos if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ 13470f74e101Schristos || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT) 13480f74e101Schristos && elem.data.integer != 0) { 13490f74e101Schristos char errbuf[20]; 1350c74ad251Schristos ND_PRINT("[errorStatus(%s)!=0]", 1351c74ad251Schristos DECODE_ErrorStatus(elem.data.integer)); 13520f74e101Schristos } else if (pduid == GETBULKREQ) { 1353c74ad251Schristos ND_PRINT(" N=%d", elem.data.integer); 13540f74e101Schristos } else if (elem.data.integer != 0) { 13550f74e101Schristos char errbuf[20]; 1356c74ad251Schristos ND_PRINT(" %s", DECODE_ErrorStatus(elem.data.integer)); 1357fdccd7e4Schristos error_status = elem.data.integer; 13580f74e101Schristos } 13590f74e101Schristos length -= count; 13600f74e101Schristos np += count; 13610f74e101Schristos 13620f74e101Schristos /* errorIndex (Integer) */ 1363b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 13640f74e101Schristos return; 13650f74e101Schristos if (elem.type != BE_INT) { 1366c74ad251Schristos ND_PRINT("[errorIndex!=INT]"); 1367b3a00663Schristos asn1_print(ndo, &elem); 13680f74e101Schristos return; 13690f74e101Schristos } 13700f74e101Schristos if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ 13710f74e101Schristos || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT) 13720f74e101Schristos && elem.data.integer != 0) 1373c74ad251Schristos ND_PRINT("[errorIndex(%d)!=0]", elem.data.integer); 13740f74e101Schristos else if (pduid == GETBULKREQ) 1375c74ad251Schristos ND_PRINT(" M=%d", elem.data.integer); 13760f74e101Schristos else if (elem.data.integer != 0) { 1377fdccd7e4Schristos if (!error_status) 1378c74ad251Schristos ND_PRINT("[errorIndex(%d) w/o errorStatus]", elem.data.integer); 1379fdccd7e4Schristos else 1380c74ad251Schristos ND_PRINT("@%d", elem.data.integer); 1381fdccd7e4Schristos } else if (error_status) { 1382c74ad251Schristos ND_PRINT("[errorIndex==0]"); 13830f74e101Schristos } 13840f74e101Schristos length -= count; 13850f74e101Schristos np += count; 13860f74e101Schristos 1387b3a00663Schristos varbind_print(ndo, pduid, np, length); 13880f74e101Schristos } 13890f74e101Schristos 13900f74e101Schristos /* 13910f74e101Schristos * Decode SNMP Trap PDU 13920f74e101Schristos */ 13930f74e101Schristos static void 1394b3a00663Schristos trappdu_print(netdissect_options *ndo, 1395b3a00663Schristos const u_char *np, u_int length) 13960f74e101Schristos { 13970f74e101Schristos struct be elem; 13980f74e101Schristos int count = 0, generic; 13990f74e101Schristos 1400c74ad251Schristos ND_PRINT(" "); 14010f74e101Schristos 14020f74e101Schristos /* enterprise (oid) */ 1403b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 14040f74e101Schristos return; 14050f74e101Schristos if (elem.type != BE_OID) { 1406c74ad251Schristos ND_PRINT("[enterprise!=OID]"); 1407b3a00663Schristos asn1_print(ndo, &elem); 14080f74e101Schristos return; 14090f74e101Schristos } 1410b3a00663Schristos if (asn1_print(ndo, &elem) < 0) 14110f74e101Schristos return; 14120f74e101Schristos length -= count; 14130f74e101Schristos np += count; 14140f74e101Schristos 1415c74ad251Schristos ND_PRINT(" "); 14160f74e101Schristos 14170f74e101Schristos /* agent-addr (inetaddr) */ 1418b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 14190f74e101Schristos return; 14200f74e101Schristos if (elem.type != BE_INETADDR) { 1421c74ad251Schristos ND_PRINT("[agent-addr!=INETADDR]"); 1422b3a00663Schristos asn1_print(ndo, &elem); 14230f74e101Schristos return; 14240f74e101Schristos } 1425b3a00663Schristos if (asn1_print(ndo, &elem) < 0) 14260f74e101Schristos return; 14270f74e101Schristos length -= count; 14280f74e101Schristos np += count; 14290f74e101Schristos 14300f74e101Schristos /* generic-trap (Integer) */ 1431b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 14320f74e101Schristos return; 14330f74e101Schristos if (elem.type != BE_INT) { 1434c74ad251Schristos ND_PRINT("[generic-trap!=INT]"); 1435b3a00663Schristos asn1_print(ndo, &elem); 14360f74e101Schristos return; 14370f74e101Schristos } 14380f74e101Schristos generic = elem.data.integer; 14390f74e101Schristos { 14400f74e101Schristos char buf[20]; 1441c74ad251Schristos ND_PRINT(" %s", DECODE_GenericTrap(generic)); 14420f74e101Schristos } 14430f74e101Schristos length -= count; 14440f74e101Schristos np += count; 14450f74e101Schristos 14460f74e101Schristos /* specific-trap (Integer) */ 1447b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 14480f74e101Schristos return; 14490f74e101Schristos if (elem.type != BE_INT) { 1450c74ad251Schristos ND_PRINT("[specific-trap!=INT]"); 1451b3a00663Schristos asn1_print(ndo, &elem); 14520f74e101Schristos return; 14530f74e101Schristos } 14540f74e101Schristos if (generic != GT_ENTERPRISE) { 14550f74e101Schristos if (elem.data.integer != 0) 1456c74ad251Schristos ND_PRINT("[specific-trap(%d)!=0]", elem.data.integer); 14570f74e101Schristos } else 1458c74ad251Schristos ND_PRINT(" s=%d", elem.data.integer); 14590f74e101Schristos length -= count; 14600f74e101Schristos np += count; 14610f74e101Schristos 1462c74ad251Schristos ND_PRINT(" "); 14630f74e101Schristos 14640f74e101Schristos /* time-stamp (TimeTicks) */ 1465b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 14660f74e101Schristos return; 14670f74e101Schristos if (elem.type != BE_UNS) { /* XXX */ 1468c74ad251Schristos ND_PRINT("[time-stamp!=TIMETICKS]"); 1469b3a00663Schristos asn1_print(ndo, &elem); 14700f74e101Schristos return; 14710f74e101Schristos } 1472b3a00663Schristos if (asn1_print(ndo, &elem) < 0) 14730f74e101Schristos return; 14740f74e101Schristos length -= count; 14750f74e101Schristos np += count; 14760f74e101Schristos 1477b3a00663Schristos varbind_print(ndo, TRAP, np, length); 14780f74e101Schristos } 14790f74e101Schristos 14800f74e101Schristos /* 14810f74e101Schristos * Decode arbitrary SNMP PDUs. 14820f74e101Schristos */ 14830f74e101Schristos static void 1484b3a00663Schristos pdu_print(netdissect_options *ndo, 1485b3a00663Schristos const u_char *np, u_int length, int version) 14860f74e101Schristos { 14870f74e101Schristos struct be pdu; 14880f74e101Schristos int count = 0; 14890f74e101Schristos 14900f74e101Schristos /* PDU (Context) */ 1491b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &pdu)) < 0) 14920f74e101Schristos return; 14930f74e101Schristos if (pdu.type != BE_PDU) { 1494c74ad251Schristos ND_PRINT("[no PDU]"); 14950f74e101Schristos return; 14960f74e101Schristos } 14970f74e101Schristos if ((u_int)count < length) 1498c74ad251Schristos ND_PRINT("[%d extra after PDU]", length - count); 1499b3a00663Schristos if (ndo->ndo_vflag) { 1500c74ad251Schristos ND_PRINT("{ "); 15010f74e101Schristos } 1502b3a00663Schristos if (asn1_print(ndo, &pdu) < 0) 15030f74e101Schristos return; 1504c74ad251Schristos ND_PRINT(" "); 15050f74e101Schristos /* descend into PDU */ 15060f74e101Schristos length = pdu.asnlen; 1507fdccd7e4Schristos np = (const u_char *)pdu.data.raw; 15080f74e101Schristos 15090f74e101Schristos if (version == SNMP_VERSION_1 && 15100f74e101Schristos (pdu.id == GETBULKREQ || pdu.id == INFORMREQ || 15110f74e101Schristos pdu.id == V2TRAP || pdu.id == REPORT)) { 1512c74ad251Schristos ND_PRINT("[v2 PDU in v1 message]"); 15130f74e101Schristos return; 15140f74e101Schristos } 15150f74e101Schristos 15160f74e101Schristos if (version == SNMP_VERSION_2 && pdu.id == TRAP) { 1517c74ad251Schristos ND_PRINT("[v1 PDU in v2 message]"); 15180f74e101Schristos return; 15190f74e101Schristos } 15200f74e101Schristos 15210f74e101Schristos switch (pdu.id) { 15220f74e101Schristos case TRAP: 1523b3a00663Schristos trappdu_print(ndo, np, length); 15240f74e101Schristos break; 15250f74e101Schristos case GETREQ: 15260f74e101Schristos case GETNEXTREQ: 15270f74e101Schristos case GETRESP: 15280f74e101Schristos case SETREQ: 15290f74e101Schristos case GETBULKREQ: 15300f74e101Schristos case INFORMREQ: 15310f74e101Schristos case V2TRAP: 15320f74e101Schristos case REPORT: 1533b3a00663Schristos snmppdu_print(ndo, pdu.id, np, length); 15340f74e101Schristos break; 15350f74e101Schristos } 15360f74e101Schristos 1537b3a00663Schristos if (ndo->ndo_vflag) { 1538c74ad251Schristos ND_PRINT(" } "); 15390f74e101Schristos } 15400f74e101Schristos } 15410f74e101Schristos 15420f74e101Schristos /* 15430f74e101Schristos * Decode a scoped SNMP PDU. 15440f74e101Schristos */ 15450f74e101Schristos static void 1546b3a00663Schristos scopedpdu_print(netdissect_options *ndo, 1547b3a00663Schristos const u_char *np, u_int length, int version) 15480f74e101Schristos { 15490f74e101Schristos struct be elem; 1550dc860a36Sspz int count = 0; 15510f74e101Schristos 15520f74e101Schristos /* Sequence */ 1553b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 15540f74e101Schristos return; 15550f74e101Schristos if (elem.type != BE_SEQ) { 1556c74ad251Schristos ND_PRINT("[!scoped PDU]"); 1557b3a00663Schristos asn1_print(ndo, &elem); 15580f74e101Schristos return; 15590f74e101Schristos } 15600f74e101Schristos length = elem.asnlen; 1561fdccd7e4Schristos np = (const u_char *)elem.data.raw; 15620f74e101Schristos 15630f74e101Schristos /* contextEngineID (OCTET STRING) */ 1564b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 15650f74e101Schristos return; 15660f74e101Schristos if (elem.type != BE_STR) { 1567c74ad251Schristos ND_PRINT("[contextEngineID!=STR]"); 1568b3a00663Schristos asn1_print(ndo, &elem); 15690f74e101Schristos return; 15700f74e101Schristos } 15710f74e101Schristos length -= count; 15720f74e101Schristos np += count; 15730f74e101Schristos 1574c74ad251Schristos ND_PRINT("E="); 1575dc860a36Sspz if (asn1_print_octets(ndo, &elem) == -1) 1576dc860a36Sspz return; 1577c74ad251Schristos ND_PRINT(" "); 15780f74e101Schristos 15790f74e101Schristos /* contextName (OCTET STRING) */ 1580b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 15810f74e101Schristos return; 15820f74e101Schristos if (elem.type != BE_STR) { 1583c74ad251Schristos ND_PRINT("[contextName!=STR]"); 1584b3a00663Schristos asn1_print(ndo, &elem); 15850f74e101Schristos return; 15860f74e101Schristos } 15870f74e101Schristos length -= count; 15880f74e101Schristos np += count; 15890f74e101Schristos 1590c74ad251Schristos ND_PRINT("C="); 1591dc860a36Sspz if (asn1_print_string(ndo, &elem) == -1) 1592dc860a36Sspz return; 1593c74ad251Schristos ND_PRINT(" "); 15940f74e101Schristos 1595b3a00663Schristos pdu_print(ndo, np, length, version); 15960f74e101Schristos } 15970f74e101Schristos 15980f74e101Schristos /* 15990f74e101Schristos * Decode SNMP Community Header (SNMPv1 and SNMPv2c) 16000f74e101Schristos */ 16010f74e101Schristos static void 1602b3a00663Schristos community_print(netdissect_options *ndo, 1603b3a00663Schristos const u_char *np, u_int length, int version) 16040f74e101Schristos { 16050f74e101Schristos struct be elem; 16060f74e101Schristos int count = 0; 16070f74e101Schristos 16080f74e101Schristos /* Community (String) */ 1609b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 16100f74e101Schristos return; 16110f74e101Schristos if (elem.type != BE_STR) { 1612c74ad251Schristos ND_PRINT("[comm!=STR]"); 1613b3a00663Schristos asn1_print(ndo, &elem); 16140f74e101Schristos return; 16150f74e101Schristos } 16160f74e101Schristos /* default community */ 16170f74e101Schristos if (!(elem.asnlen == sizeof(DEF_COMMUNITY) - 1 && 1618fdccd7e4Schristos strncmp((const char *)elem.data.str, DEF_COMMUNITY, 1619dc860a36Sspz sizeof(DEF_COMMUNITY) - 1) == 0)) { 16200f74e101Schristos /* ! "public" */ 1621c74ad251Schristos ND_PRINT("C="); 1622dc860a36Sspz if (asn1_print_string(ndo, &elem) == -1) 1623dc860a36Sspz return; 1624c74ad251Schristos ND_PRINT(" "); 1625dc860a36Sspz } 16260f74e101Schristos length -= count; 16270f74e101Schristos np += count; 16280f74e101Schristos 1629b3a00663Schristos pdu_print(ndo, np, length, version); 16300f74e101Schristos } 16310f74e101Schristos 16320f74e101Schristos /* 16330f74e101Schristos * Decode SNMPv3 User-based Security Message Header (SNMPv3) 16340f74e101Schristos */ 16350f74e101Schristos static void 1636b3a00663Schristos usm_print(netdissect_options *ndo, 1637b3a00663Schristos const u_char *np, u_int length) 16380f74e101Schristos { 16390f74e101Schristos struct be elem; 16400f74e101Schristos int count = 0; 16410f74e101Schristos 16420f74e101Schristos /* Sequence */ 1643b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 16440f74e101Schristos return; 16450f74e101Schristos if (elem.type != BE_SEQ) { 1646c74ad251Schristos ND_PRINT("[!usm]"); 1647b3a00663Schristos asn1_print(ndo, &elem); 16480f74e101Schristos return; 16490f74e101Schristos } 16500f74e101Schristos length = elem.asnlen; 1651fdccd7e4Schristos np = (const u_char *)elem.data.raw; 16520f74e101Schristos 16530f74e101Schristos /* msgAuthoritativeEngineID (OCTET STRING) */ 1654b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 16550f74e101Schristos return; 16560f74e101Schristos if (elem.type != BE_STR) { 1657c74ad251Schristos ND_PRINT("[msgAuthoritativeEngineID!=STR]"); 1658b3a00663Schristos asn1_print(ndo, &elem); 16590f74e101Schristos return; 16600f74e101Schristos } 16610f74e101Schristos length -= count; 16620f74e101Schristos np += count; 16630f74e101Schristos 16640f74e101Schristos /* msgAuthoritativeEngineBoots (INTEGER) */ 1665b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 16660f74e101Schristos return; 16670f74e101Schristos if (elem.type != BE_INT) { 1668c74ad251Schristos ND_PRINT("[msgAuthoritativeEngineBoots!=INT]"); 1669b3a00663Schristos asn1_print(ndo, &elem); 16700f74e101Schristos return; 16710f74e101Schristos } 1672b3a00663Schristos if (ndo->ndo_vflag) 1673c74ad251Schristos ND_PRINT("B=%d ", elem.data.integer); 16740f74e101Schristos length -= count; 16750f74e101Schristos np += count; 16760f74e101Schristos 16770f74e101Schristos /* msgAuthoritativeEngineTime (INTEGER) */ 1678b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 16790f74e101Schristos return; 16800f74e101Schristos if (elem.type != BE_INT) { 1681c74ad251Schristos ND_PRINT("[msgAuthoritativeEngineTime!=INT]"); 1682b3a00663Schristos asn1_print(ndo, &elem); 16830f74e101Schristos return; 16840f74e101Schristos } 1685b3a00663Schristos if (ndo->ndo_vflag) 1686c74ad251Schristos ND_PRINT("T=%d ", elem.data.integer); 16870f74e101Schristos length -= count; 16880f74e101Schristos np += count; 16890f74e101Schristos 16900f74e101Schristos /* msgUserName (OCTET STRING) */ 1691b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 16920f74e101Schristos return; 16930f74e101Schristos if (elem.type != BE_STR) { 1694c74ad251Schristos ND_PRINT("[msgUserName!=STR]"); 1695b3a00663Schristos asn1_print(ndo, &elem); 16960f74e101Schristos return; 16970f74e101Schristos } 16980f74e101Schristos length -= count; 16990f74e101Schristos np += count; 17000f74e101Schristos 1701c74ad251Schristos ND_PRINT("U="); 1702dc860a36Sspz if (asn1_print_string(ndo, &elem) == -1) 1703dc860a36Sspz return; 1704c74ad251Schristos ND_PRINT(" "); 17050f74e101Schristos 17060f74e101Schristos /* msgAuthenticationParameters (OCTET STRING) */ 1707b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 17080f74e101Schristos return; 17090f74e101Schristos if (elem.type != BE_STR) { 1710c74ad251Schristos ND_PRINT("[msgAuthenticationParameters!=STR]"); 1711b3a00663Schristos asn1_print(ndo, &elem); 17120f74e101Schristos return; 17130f74e101Schristos } 17140f74e101Schristos length -= count; 17150f74e101Schristos np += count; 17160f74e101Schristos 17170f74e101Schristos /* msgPrivacyParameters (OCTET STRING) */ 1718b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 17190f74e101Schristos return; 17200f74e101Schristos if (elem.type != BE_STR) { 1721c74ad251Schristos ND_PRINT("[msgPrivacyParameters!=STR]"); 1722b3a00663Schristos asn1_print(ndo, &elem); 17230f74e101Schristos return; 17240f74e101Schristos } 17250f74e101Schristos length -= count; 17260f74e101Schristos np += count; 17270f74e101Schristos 17280f74e101Schristos if ((u_int)count < length) 1729c74ad251Schristos ND_PRINT("[%d extra after usm SEQ]", length - count); 17300f74e101Schristos } 17310f74e101Schristos 17320f74e101Schristos /* 17330f74e101Schristos * Decode SNMPv3 Message Header (SNMPv3) 17340f74e101Schristos */ 17350f74e101Schristos static void 1736b3a00663Schristos v3msg_print(netdissect_options *ndo, 1737b3a00663Schristos const u_char *np, u_int length) 17380f74e101Schristos { 17390f74e101Schristos struct be elem; 17400f74e101Schristos int count = 0; 17410f74e101Schristos u_char flags; 17420f74e101Schristos int model; 17430f74e101Schristos const u_char *xnp = np; 17440f74e101Schristos int xlength = length; 17450f74e101Schristos 17460f74e101Schristos /* Sequence */ 1747b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 17480f74e101Schristos return; 17490f74e101Schristos if (elem.type != BE_SEQ) { 1750c74ad251Schristos ND_PRINT("[!message]"); 1751b3a00663Schristos asn1_print(ndo, &elem); 17520f74e101Schristos return; 17530f74e101Schristos } 17540f74e101Schristos length = elem.asnlen; 1755fdccd7e4Schristos np = (const u_char *)elem.data.raw; 17560f74e101Schristos 1757b3a00663Schristos if (ndo->ndo_vflag) { 1758c74ad251Schristos ND_PRINT("{ "); 17590f74e101Schristos } 17600f74e101Schristos 17610f74e101Schristos /* msgID (INTEGER) */ 1762b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 17630f74e101Schristos return; 17640f74e101Schristos if (elem.type != BE_INT) { 1765c74ad251Schristos ND_PRINT("[msgID!=INT]"); 1766b3a00663Schristos asn1_print(ndo, &elem); 17670f74e101Schristos return; 17680f74e101Schristos } 17690f74e101Schristos length -= count; 17700f74e101Schristos np += count; 17710f74e101Schristos 17720f74e101Schristos /* msgMaxSize (INTEGER) */ 1773b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 17740f74e101Schristos return; 17750f74e101Schristos if (elem.type != BE_INT) { 1776c74ad251Schristos ND_PRINT("[msgMaxSize!=INT]"); 1777b3a00663Schristos asn1_print(ndo, &elem); 17780f74e101Schristos return; 17790f74e101Schristos } 17800f74e101Schristos length -= count; 17810f74e101Schristos np += count; 17820f74e101Schristos 17830f74e101Schristos /* msgFlags (OCTET STRING) */ 1784b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 17850f74e101Schristos return; 17860f74e101Schristos if (elem.type != BE_STR) { 1787c74ad251Schristos ND_PRINT("[msgFlags!=STR]"); 1788b3a00663Schristos asn1_print(ndo, &elem); 17890f74e101Schristos return; 17900f74e101Schristos } 17910f74e101Schristos if (elem.asnlen != 1) { 1792c74ad251Schristos ND_PRINT("[msgFlags size %d]", elem.asnlen); 17930f74e101Schristos return; 17940f74e101Schristos } 1795c74ad251Schristos flags = GET_U_1(elem.data.str); 17960f74e101Schristos if (flags != 0x00 && flags != 0x01 && flags != 0x03 17970f74e101Schristos && flags != 0x04 && flags != 0x05 && flags != 0x07) { 1798c74ad251Schristos ND_PRINT("[msgFlags=0x%02X]", flags); 17990f74e101Schristos return; 18000f74e101Schristos } 18010f74e101Schristos length -= count; 18020f74e101Schristos np += count; 18030f74e101Schristos 1804c74ad251Schristos ND_PRINT("F=%s%s%s ", 1805b3a00663Schristos flags & 0x01 ? "a" : "", 1806b3a00663Schristos flags & 0x02 ? "p" : "", 1807c74ad251Schristos flags & 0x04 ? "r" : ""); 18080f74e101Schristos 18090f74e101Schristos /* msgSecurityModel (INTEGER) */ 1810b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 18110f74e101Schristos return; 18120f74e101Schristos if (elem.type != BE_INT) { 1813c74ad251Schristos ND_PRINT("[msgSecurityModel!=INT]"); 1814b3a00663Schristos asn1_print(ndo, &elem); 18150f74e101Schristos return; 18160f74e101Schristos } 18170f74e101Schristos model = elem.data.integer; 18180f74e101Schristos length -= count; 18190f74e101Schristos np += count; 18200f74e101Schristos 18210f74e101Schristos if ((u_int)count < length) 1822c74ad251Schristos ND_PRINT("[%d extra after message SEQ]", length - count); 18230f74e101Schristos 1824b3a00663Schristos if (ndo->ndo_vflag) { 1825c74ad251Schristos ND_PRINT("} "); 18260f74e101Schristos } 18270f74e101Schristos 18280f74e101Schristos if (model == 3) { 1829b3a00663Schristos if (ndo->ndo_vflag) { 1830c74ad251Schristos ND_PRINT("{ USM "); 18310f74e101Schristos } 18320f74e101Schristos } else { 1833c74ad251Schristos ND_PRINT("[security model %d]", model); 18340f74e101Schristos return; 18350f74e101Schristos } 18360f74e101Schristos 18370f74e101Schristos np = xnp + (np - xnp); 18380f74e101Schristos length = xlength - (np - xnp); 18390f74e101Schristos 18400f74e101Schristos /* msgSecurityParameters (OCTET STRING) */ 1841b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 18420f74e101Schristos return; 18430f74e101Schristos if (elem.type != BE_STR) { 1844c74ad251Schristos ND_PRINT("[msgSecurityParameters!=STR]"); 1845b3a00663Schristos asn1_print(ndo, &elem); 18460f74e101Schristos return; 18470f74e101Schristos } 18480f74e101Schristos length -= count; 18490f74e101Schristos np += count; 18500f74e101Schristos 18510f74e101Schristos if (model == 3) { 1852b3a00663Schristos usm_print(ndo, elem.data.str, elem.asnlen); 1853b3a00663Schristos if (ndo->ndo_vflag) { 1854c74ad251Schristos ND_PRINT("} "); 18550f74e101Schristos } 18560f74e101Schristos } 18570f74e101Schristos 1858b3a00663Schristos if (ndo->ndo_vflag) { 1859c74ad251Schristos ND_PRINT("{ ScopedPDU "); 18600f74e101Schristos } 18610f74e101Schristos 1862b3a00663Schristos scopedpdu_print(ndo, np, length, 3); 18630f74e101Schristos 1864b3a00663Schristos if (ndo->ndo_vflag) { 1865c74ad251Schristos ND_PRINT("} "); 18660f74e101Schristos } 18670f74e101Schristos } 18680f74e101Schristos 18690f74e101Schristos /* 18700f74e101Schristos * Decode SNMP header and pass on to PDU printing routines 18710f74e101Schristos */ 18720f74e101Schristos void 1873b3a00663Schristos snmp_print(netdissect_options *ndo, 1874b3a00663Schristos const u_char *np, u_int length) 18750f74e101Schristos { 18760f74e101Schristos struct be elem; 18770f74e101Schristos int count = 0; 18780f74e101Schristos int version = 0; 18790f74e101Schristos 1880c74ad251Schristos ndo->ndo_protocol = "snmp"; 1881c74ad251Schristos ND_PRINT(" "); 18820f74e101Schristos 18830f74e101Schristos /* initial Sequence */ 1884b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 18850f74e101Schristos return; 18860f74e101Schristos if (elem.type != BE_SEQ) { 1887c74ad251Schristos ND_PRINT("[!init SEQ]"); 1888b3a00663Schristos asn1_print(ndo, &elem); 18890f74e101Schristos return; 18900f74e101Schristos } 18910f74e101Schristos if ((u_int)count < length) 1892c74ad251Schristos ND_PRINT("[%d extra after iSEQ]", length - count); 18930f74e101Schristos /* descend */ 18940f74e101Schristos length = elem.asnlen; 1895fdccd7e4Schristos np = (const u_char *)elem.data.raw; 18960f74e101Schristos 18970f74e101Schristos /* Version (INTEGER) */ 1898b3a00663Schristos if ((count = asn1_parse(ndo, np, length, &elem)) < 0) 18990f74e101Schristos return; 19000f74e101Schristos if (elem.type != BE_INT) { 1901c74ad251Schristos ND_PRINT("[version!=INT]"); 1902b3a00663Schristos asn1_print(ndo, &elem); 19030f74e101Schristos return; 19040f74e101Schristos } 19050f74e101Schristos 19060f74e101Schristos switch (elem.data.integer) { 19070f74e101Schristos case SNMP_VERSION_1: 19080f74e101Schristos case SNMP_VERSION_2: 19090f74e101Schristos case SNMP_VERSION_3: 1910b3a00663Schristos if (ndo->ndo_vflag) 1911c74ad251Schristos ND_PRINT("{ %s ", SnmpVersion[elem.data.integer]); 19120f74e101Schristos break; 19130f74e101Schristos default: 1914c74ad251Schristos ND_PRINT("SNMP [version = %d]", elem.data.integer); 19150f74e101Schristos return; 19160f74e101Schristos } 19170f74e101Schristos version = elem.data.integer; 19180f74e101Schristos length -= count; 19190f74e101Schristos np += count; 19200f74e101Schristos 19210f74e101Schristos switch (version) { 19220f74e101Schristos case SNMP_VERSION_1: 19230f74e101Schristos case SNMP_VERSION_2: 1924b3a00663Schristos community_print(ndo, np, length, version); 19250f74e101Schristos break; 19260f74e101Schristos case SNMP_VERSION_3: 1927b3a00663Schristos v3msg_print(ndo, np, length); 19280f74e101Schristos break; 19290f74e101Schristos default: 1930c74ad251Schristos ND_PRINT("[version = %d]", elem.data.integer); 19310f74e101Schristos break; 19320f74e101Schristos } 19330f74e101Schristos 1934b3a00663Schristos if (ndo->ndo_vflag) { 1935c74ad251Schristos ND_PRINT("} "); 19360f74e101Schristos } 19370f74e101Schristos } 1938